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 1 41 struct fbinfo { 42 unsigned int version; 43 unsigned int bpp; 44 unsigned int size; 45 unsigned int width; 46 unsigned int height; 47 unsigned int red_offset; 48 unsigned int red_length; 49 unsigned int blue_offset; 50 unsigned int blue_length; 51 unsigned int green_offset; 52 unsigned int green_length; 53 unsigned int alpha_offset; 54 unsigned int alpha_length; 55 } __attribute__((packed)); 56 57 void framebuffer_service(int fd, void *cookie) 58 { 59 struct fbinfo fbinfo; 60 unsigned int i, bsize; 61 char buf[640]; 62 int fd_screencap; 63 int w, h, f; 64 int fds[2]; 65 pid_t pid; 66 67 if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail; 68 69 pid = fork(); 70 if (pid < 0) goto done; 71 72 if (pid == 0) { 73 dup2(fds[1], STDOUT_FILENO); 74 adb_close(fds[0]); 75 adb_close(fds[1]); 76 const char* command = "screencap"; 77 const char *args[2] = {command, NULL}; 78 execvp(command, (char**)args); 79 exit(1); 80 } 81 82 adb_close(fds[1]); 83 fd_screencap = fds[0]; 84 85 /* read w, h & format */ 86 if(!ReadFdExactly(fd_screencap, &w, 4)) goto done; 87 if(!ReadFdExactly(fd_screencap, &h, 4)) goto done; 88 if(!ReadFdExactly(fd_screencap, &f, 4)) goto done; 89 90 fbinfo.version = DDMS_RAWIMAGE_VERSION; 91 /* see hardware/hardware.h */ 92 switch (f) { 93 case 1: /* RGBA_8888 */ 94 fbinfo.bpp = 32; 95 fbinfo.size = w * h * 4; 96 fbinfo.width = w; 97 fbinfo.height = h; 98 fbinfo.red_offset = 0; 99 fbinfo.red_length = 8; 100 fbinfo.green_offset = 8; 101 fbinfo.green_length = 8; 102 fbinfo.blue_offset = 16; 103 fbinfo.blue_length = 8; 104 fbinfo.alpha_offset = 24; 105 fbinfo.alpha_length = 8; 106 break; 107 case 2: /* RGBX_8888 */ 108 fbinfo.bpp = 32; 109 fbinfo.size = w * h * 4; 110 fbinfo.width = w; 111 fbinfo.height = h; 112 fbinfo.red_offset = 0; 113 fbinfo.red_length = 8; 114 fbinfo.green_offset = 8; 115 fbinfo.green_length = 8; 116 fbinfo.blue_offset = 16; 117 fbinfo.blue_length = 8; 118 fbinfo.alpha_offset = 24; 119 fbinfo.alpha_length = 0; 120 break; 121 case 3: /* RGB_888 */ 122 fbinfo.bpp = 24; 123 fbinfo.size = w * h * 3; 124 fbinfo.width = w; 125 fbinfo.height = h; 126 fbinfo.red_offset = 0; 127 fbinfo.red_length = 8; 128 fbinfo.green_offset = 8; 129 fbinfo.green_length = 8; 130 fbinfo.blue_offset = 16; 131 fbinfo.blue_length = 8; 132 fbinfo.alpha_offset = 24; 133 fbinfo.alpha_length = 0; 134 break; 135 case 4: /* RGB_565 */ 136 fbinfo.bpp = 16; 137 fbinfo.size = w * h * 2; 138 fbinfo.width = w; 139 fbinfo.height = h; 140 fbinfo.red_offset = 11; 141 fbinfo.red_length = 5; 142 fbinfo.green_offset = 5; 143 fbinfo.green_length = 6; 144 fbinfo.blue_offset = 0; 145 fbinfo.blue_length = 5; 146 fbinfo.alpha_offset = 0; 147 fbinfo.alpha_length = 0; 148 break; 149 case 5: /* BGRA_8888 */ 150 fbinfo.bpp = 32; 151 fbinfo.size = w * h * 4; 152 fbinfo.width = w; 153 fbinfo.height = h; 154 fbinfo.red_offset = 16; 155 fbinfo.red_length = 8; 156 fbinfo.green_offset = 8; 157 fbinfo.green_length = 8; 158 fbinfo.blue_offset = 0; 159 fbinfo.blue_length = 8; 160 fbinfo.alpha_offset = 24; 161 fbinfo.alpha_length = 8; 162 break; 163 default: 164 goto done; 165 } 166 167 /* write header */ 168 if(!WriteFdExactly(fd, &fbinfo, sizeof(fbinfo))) goto done; 169 170 /* write data */ 171 for(i = 0; i < fbinfo.size; i += bsize) { 172 bsize = sizeof(buf); 173 if (i + bsize > fbinfo.size) 174 bsize = fbinfo.size - i; 175 if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; 176 if(!WriteFdExactly(fd, buf, bsize)) goto done; 177 } 178 179 done: 180 adb_close(fds[0]); 181 182 TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0)); 183 pipefail: 184 adb_close(fd); 185 } 186