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 <errno.h>
     18 #include <fcntl.h>
     19 #include <linux/fb.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/ioctl.h>
     24 #include <sys/mman.h>
     25 #include <sys/types.h>
     26 #include <sys/wait.h>
     27 #include <unistd.h>
     28 
     29 #include "sysdeps.h"
     30 
     31 #include "adb.h"
     32 #include "adb_io.h"
     33 #include "fdevent.h"
     34 
     35 /* TODO:
     36 ** - sync with vsync to avoid tearing
     37 */
     38 /* This version number defines the format of the fbinfo struct.
     39    It must match versioning in ddms where this data is consumed. */
     40 #define DDMS_RAWIMAGE_VERSION 2
     41 struct fbinfo {
     42     unsigned int version;
     43     unsigned int bpp;
     44     unsigned int colorSpace;
     45     unsigned int size;
     46     unsigned int width;
     47     unsigned int height;
     48     unsigned int red_offset;
     49     unsigned int red_length;
     50     unsigned int blue_offset;
     51     unsigned int blue_length;
     52     unsigned int green_offset;
     53     unsigned int green_length;
     54     unsigned int alpha_offset;
     55     unsigned int alpha_length;
     56 } __attribute__((packed));
     57 
     58 void framebuffer_service(int fd, void *cookie)
     59 {
     60     struct fbinfo fbinfo;
     61     unsigned int i, bsize;
     62     char buf[640];
     63     int fd_screencap;
     64     int w, h, f, c;
     65     int fds[2];
     66     pid_t pid;
     67 
     68     if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail;
     69 
     70     pid = fork();
     71     if (pid < 0) goto done;
     72 
     73     if (pid == 0) {
     74         dup2(fds[1], STDOUT_FILENO);
     75         adb_close(fds[0]);
     76         adb_close(fds[1]);
     77         const char* command = "screencap";
     78         const char *args[2] = {command, NULL};
     79         execvp(command, (char**)args);
     80         exit(1);
     81     }
     82 
     83     adb_close(fds[1]);
     84     fd_screencap = fds[0];
     85 
     86     /* read w, h, format & color space */
     87     if(!ReadFdExactly(fd_screencap, &w, 4)) goto done;
     88     if(!ReadFdExactly(fd_screencap, &h, 4)) goto done;
     89     if(!ReadFdExactly(fd_screencap, &f, 4)) goto done;
     90     if(!ReadFdExactly(fd_screencap, &c, 4)) goto done;
     91 
     92     fbinfo.version = DDMS_RAWIMAGE_VERSION;
     93     fbinfo.colorSpace = c;
     94     /* see hardware/hardware.h */
     95     switch (f) {
     96         case 1: /* RGBA_8888 */
     97             fbinfo.bpp = 32;
     98             fbinfo.size = w * h * 4;
     99             fbinfo.width = w;
    100             fbinfo.height = h;
    101             fbinfo.red_offset = 0;
    102             fbinfo.red_length = 8;
    103             fbinfo.green_offset = 8;
    104             fbinfo.green_length = 8;
    105             fbinfo.blue_offset = 16;
    106             fbinfo.blue_length = 8;
    107             fbinfo.alpha_offset = 24;
    108             fbinfo.alpha_length = 8;
    109             break;
    110         case 2: /* RGBX_8888 */
    111             fbinfo.bpp = 32;
    112             fbinfo.size = w * h * 4;
    113             fbinfo.width = w;
    114             fbinfo.height = h;
    115             fbinfo.red_offset = 0;
    116             fbinfo.red_length = 8;
    117             fbinfo.green_offset = 8;
    118             fbinfo.green_length = 8;
    119             fbinfo.blue_offset = 16;
    120             fbinfo.blue_length = 8;
    121             fbinfo.alpha_offset = 24;
    122             fbinfo.alpha_length = 0;
    123             break;
    124         case 3: /* RGB_888 */
    125             fbinfo.bpp = 24;
    126             fbinfo.size = w * h * 3;
    127             fbinfo.width = w;
    128             fbinfo.height = h;
    129             fbinfo.red_offset = 0;
    130             fbinfo.red_length = 8;
    131             fbinfo.green_offset = 8;
    132             fbinfo.green_length = 8;
    133             fbinfo.blue_offset = 16;
    134             fbinfo.blue_length = 8;
    135             fbinfo.alpha_offset = 24;
    136             fbinfo.alpha_length = 0;
    137             break;
    138         case 4: /* RGB_565 */
    139             fbinfo.bpp = 16;
    140             fbinfo.size = w * h * 2;
    141             fbinfo.width = w;
    142             fbinfo.height = h;
    143             fbinfo.red_offset = 11;
    144             fbinfo.red_length = 5;
    145             fbinfo.green_offset = 5;
    146             fbinfo.green_length = 6;
    147             fbinfo.blue_offset = 0;
    148             fbinfo.blue_length = 5;
    149             fbinfo.alpha_offset = 0;
    150             fbinfo.alpha_length = 0;
    151             break;
    152         case 5: /* BGRA_8888 */
    153             fbinfo.bpp = 32;
    154             fbinfo.size = w * h * 4;
    155             fbinfo.width = w;
    156             fbinfo.height = h;
    157             fbinfo.red_offset = 16;
    158             fbinfo.red_length = 8;
    159             fbinfo.green_offset = 8;
    160             fbinfo.green_length = 8;
    161             fbinfo.blue_offset = 0;
    162             fbinfo.blue_length = 8;
    163             fbinfo.alpha_offset = 24;
    164             fbinfo.alpha_length = 8;
    165            break;
    166         default:
    167             goto done;
    168     }
    169 
    170     /* write header */
    171     if(!WriteFdExactly(fd, &fbinfo, sizeof(fbinfo))) goto done;
    172 
    173     /* write data */
    174     for(i = 0; i < fbinfo.size; i += bsize) {
    175       bsize = sizeof(buf);
    176       if (i + bsize > fbinfo.size)
    177         bsize = fbinfo.size - i;
    178       if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done;
    179       if(!WriteFdExactly(fd, buf, bsize)) goto done;
    180     }
    181 
    182 done:
    183     adb_close(fds[0]);
    184 
    185     TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
    186 pipefail:
    187     adb_close(fd);
    188 }
    189