Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <unistd.h>
     20 #include <string.h>
     21 #include <fcntl.h>
     22 
     23 #include "fdevent.h"
     24 #include "adb.h"
     25 
     26 #include <linux/fb.h>
     27 #include <sys/ioctl.h>
     28 #include <sys/mman.h>
     29 
     30 /* TODO:
     31 ** - sync with vsync to avoid tearing
     32 */
     33 /* This version number defines the format of the fbinfo struct.
     34    It must match versioning in ddms where this data is consumed. */
     35 #define DDMS_RAWIMAGE_VERSION 1
     36 struct fbinfo {
     37     unsigned int version;
     38     unsigned int bpp;
     39     unsigned int size;
     40     unsigned int width;
     41     unsigned int height;
     42     unsigned int red_offset;
     43     unsigned int red_length;
     44     unsigned int blue_offset;
     45     unsigned int blue_length;
     46     unsigned int green_offset;
     47     unsigned int green_length;
     48     unsigned int alpha_offset;
     49     unsigned int alpha_length;
     50 } __attribute__((packed));
     51 
     52 void framebuffer_service(int fd, void *cookie)
     53 {
     54     struct fbinfo fbinfo;
     55     unsigned int i;
     56     char buf[640];
     57     int fd_screencap;
     58     int w, h, f;
     59     int fds[2];
     60 
     61     if (pipe(fds) < 0) goto done;
     62 
     63     pid_t pid = fork();
     64     if (pid < 0) goto done;
     65 
     66     if (pid == 0) {
     67         dup2(fds[1], STDOUT_FILENO);
     68         close(fds[0]);
     69         close(fds[1]);
     70         const char* command = "screencap";
     71         const char *args[2] = {command, NULL};
     72         execvp(command, (char**)args);
     73         exit(1);
     74     }
     75 
     76     fd_screencap = fds[0];
     77 
     78     /* read w, h & format */
     79     if(readx(fd_screencap, &w, 4)) goto done;
     80     if(readx(fd_screencap, &h, 4)) goto done;
     81     if(readx(fd_screencap, &f, 4)) goto done;
     82 
     83     fbinfo.version = DDMS_RAWIMAGE_VERSION;
     84     /* see hardware/hardware.h */
     85     switch (f) {
     86         case 1: /* RGBA_8888 */
     87             fbinfo.bpp = 32;
     88             fbinfo.size = w * h * 4;
     89             fbinfo.width = w;
     90             fbinfo.height = h;
     91             fbinfo.red_offset = 0;
     92             fbinfo.red_length = 8;
     93             fbinfo.green_offset = 8;
     94             fbinfo.green_length = 8;
     95             fbinfo.blue_offset = 16;
     96             fbinfo.blue_length = 8;
     97             fbinfo.alpha_offset = 24;
     98             fbinfo.alpha_length = 8;
     99             break;
    100         case 2: /* RGBX_8888 */
    101             fbinfo.bpp = 32;
    102             fbinfo.size = w * h * 4;
    103             fbinfo.width = w;
    104             fbinfo.height = h;
    105             fbinfo.red_offset = 0;
    106             fbinfo.red_length = 8;
    107             fbinfo.green_offset = 8;
    108             fbinfo.green_length = 8;
    109             fbinfo.blue_offset = 16;
    110             fbinfo.blue_length = 8;
    111             fbinfo.alpha_offset = 24;
    112             fbinfo.alpha_length = 0;
    113             break;
    114         case 3: /* RGB_888 */
    115             fbinfo.bpp = 24;
    116             fbinfo.size = w * h * 3;
    117             fbinfo.width = w;
    118             fbinfo.height = h;
    119             fbinfo.red_offset = 0;
    120             fbinfo.red_length = 8;
    121             fbinfo.green_offset = 8;
    122             fbinfo.green_length = 8;
    123             fbinfo.blue_offset = 16;
    124             fbinfo.blue_length = 8;
    125             fbinfo.alpha_offset = 24;
    126             fbinfo.alpha_length = 0;
    127             break;
    128         case 4: /* RGB_565 */
    129             fbinfo.bpp = 16;
    130             fbinfo.size = w * h * 2;
    131             fbinfo.width = w;
    132             fbinfo.height = h;
    133             fbinfo.red_offset = 11;
    134             fbinfo.red_length = 5;
    135             fbinfo.green_offset = 5;
    136             fbinfo.green_length = 6;
    137             fbinfo.blue_offset = 0;
    138             fbinfo.blue_length = 5;
    139             fbinfo.alpha_offset = 0;
    140             fbinfo.alpha_length = 0;
    141             break;
    142         case 5: /* BGRA_8888 */
    143             fbinfo.bpp = 32;
    144             fbinfo.size = w * h * 4;
    145             fbinfo.width = w;
    146             fbinfo.height = h;
    147             fbinfo.red_offset = 16;
    148             fbinfo.red_length = 8;
    149             fbinfo.green_offset = 8;
    150             fbinfo.green_length = 8;
    151             fbinfo.blue_offset = 0;
    152             fbinfo.blue_length = 8;
    153             fbinfo.alpha_offset = 24;
    154             fbinfo.alpha_length = 8;
    155            break;
    156         default:
    157             goto done;
    158     }
    159 
    160     /* write header */
    161     if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
    162 
    163     /* write data */
    164     for(i = 0; i < fbinfo.size; i += sizeof(buf)) {
    165       if(readx(fd_screencap, buf, sizeof(buf))) goto done;
    166       if(writex(fd, buf, sizeof(buf))) goto done;
    167     }
    168     if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done;
    169     if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done;
    170 
    171 done:
    172     close(fds[0]);
    173     close(fds[1]);
    174     close(fd);
    175 }
    176