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