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