| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 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 |  | 
| Yuriy Zabroda | 5a536ef | 2012-07-17 14:52:47 +0300 | [diff] [blame] | 17 | #include <errno.h> | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 18 | #include <fcntl.h> | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 19 | #include <linux/fb.h> | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 20 | #include <stdio.h> | 
 | 21 | #include <stdlib.h> | 
 | 22 | #include <string.h> | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 23 | #include <sys/ioctl.h> | 
 | 24 | #include <sys/mman.h> | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 25 | #include <sys/types.h> | 
 | 26 | #include <sys/wait.h> | 
 | 27 | #include <unistd.h> | 
 | 28 |  | 
 | 29 | #include "sysdeps.h" | 
 | 30 |  | 
 | 31 | #include "adb.h" | 
| Dan Albert | cc731cc | 2015-02-24 21:26:58 -0800 | [diff] [blame] | 32 | #include "adb_io.h" | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 33 | #include "fdevent.h" | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 34 |  | 
 | 35 | /* TODO: | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 36 | ** - sync with vsync to avoid tearing | 
 | 37 | */ | 
| Rebecca Schultz Zavin | 154b7d7 | 2009-09-15 21:06:12 -0700 | [diff] [blame] | 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)); | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 56 |  | 
 | 57 | void framebuffer_service(int fd, void *cookie) | 
 | 58 | { | 
| Rebecca Schultz Zavin | 154b7d7 | 2009-09-15 21:06:12 -0700 | [diff] [blame] | 59 |     struct fbinfo fbinfo; | 
| Chris Dearman | 85373f4 | 2013-09-25 02:19:40 -0700 | [diff] [blame] | 60 |     unsigned int i, bsize; | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 61 |     char buf[640]; | 
 | 62 |     int fd_screencap; | 
 | 63 |     int w, h, f; | 
 | 64 |     int fds[2]; | 
| Dan Albert | bac3474 | 2015-02-25 17:51:28 -0800 | [diff] [blame] | 65 |     pid_t pid; | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 66 |  | 
| Nick Kralevich | 8fcb631 | 2014-06-05 20:26:25 -0700 | [diff] [blame] | 67 |     if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail; | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 68 |  | 
| Dan Albert | bac3474 | 2015-02-25 17:51:28 -0800 | [diff] [blame] | 69 |     pid = fork(); | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 70 |     if (pid < 0) goto done; | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 71 |  | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 72 |     if (pid == 0) { | 
 | 73 |         dup2(fds[1], STDOUT_FILENO); | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 74 |         adb_close(fds[0]); | 
 | 75 |         adb_close(fds[1]); | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 76 |         const char* command = "screencap"; | 
 | 77 |         const char *args[2] = {command, NULL}; | 
 | 78 |         execvp(command, (char**)args); | 
 | 79 |         exit(1); | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 80 |     } | 
 | 81 |  | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 82 |     adb_close(fds[1]); | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 83 |     fd_screencap = fds[0]; | 
 | 84 |  | 
 | 85 |     /* read w, h & format */ | 
| Dan Albert | cc731cc | 2015-02-24 21:26:58 -0800 | [diff] [blame] | 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; | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 89 |  | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 90 |     fbinfo.version = DDMS_RAWIMAGE_VERSION; | 
| Mathias Agopian | c1fbf7c | 2011-02-08 20:11:33 -0800 | [diff] [blame] | 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 |     } | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 166 |  | 
 | 167 |     /* write header */ | 
| Dan Albert | cc731cc | 2015-02-24 21:26:58 -0800 | [diff] [blame] | 168 |     if(!WriteFdExactly(fd, &fbinfo, sizeof(fbinfo))) goto done; | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 169 |  | 
 | 170 |     /* write data */ | 
| Chris Dearman | 85373f4 | 2013-09-25 02:19:40 -0700 | [diff] [blame] | 171 |     for(i = 0; i < fbinfo.size; i += bsize) { | 
 | 172 |       bsize = sizeof(buf); | 
 | 173 |       if (i + bsize > fbinfo.size) | 
 | 174 |         bsize = fbinfo.size - i; | 
| Dan Albert | cc731cc | 2015-02-24 21:26:58 -0800 | [diff] [blame] | 175 |       if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; | 
 | 176 |       if(!WriteFdExactly(fd, buf, bsize)) goto done; | 
| Mathias Agopian | 0715f91 | 2010-09-26 18:44:28 -0700 | [diff] [blame] | 177 |     } | 
| Rebecca Schultz Zavin | 04bee29 | 2009-09-09 21:39:41 -0700 | [diff] [blame] | 178 |  | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 179 | done: | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 180 |     adb_close(fds[0]); | 
| Bao Haojun | cdb1b1b | 2014-05-14 21:03:48 +0800 | [diff] [blame] | 181 |  | 
 | 182 |     TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0)); | 
| Chris Dearman | 85373f4 | 2013-09-25 02:19:40 -0700 | [diff] [blame] | 183 | pipefail: | 
| Dan Albert | 7664901 | 2015-02-24 15:51:19 -0800 | [diff] [blame] | 184 |     adb_close(fd); | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 185 | } |