1 /* Copyright (C) 2010 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 /* 14 * Contains UI-side framebuffer client that receives framebuffer updates 15 * from the core. 16 */ 17 18 #include "android/utils/system.h" 19 #include "android/utils/debug.h" 20 #include "android/utils/panic.h" 21 #include "android/sync-utils.h" 22 #include "android/protocol/core-connection.h" 23 #include "android/protocol/fb-updates.h" 24 #include "android/protocol/fb-updates-impl.h" 25 26 /*Enumerates states for the client framebuffer update reader. */ 27 typedef enum FbImplState { 28 /* The reader is waiting on update header. */ 29 EXPECTS_HEADER, 30 31 /* The reader is waiting on pixels. */ 32 EXPECTS_PIXELS, 33 } FbImplState; 34 35 /* Descriptor for the UI-side implementation of the "framebufer" service. 36 */ 37 typedef struct FrameBufferImpl { 38 /* Framebuffer for this client. */ 39 QFrameBuffer* fb; 40 41 /* Core connection instance for the framebuffer client. */ 42 CoreConnection* core_connection; 43 44 /* Current update header. */ 45 FBUpdateMessage update_header; 46 47 /* Reader's buffer. */ 48 uint8_t* reader_buffer; 49 50 /* Offset in the reader's buffer where to read next chunk of data. */ 51 size_t reader_offset; 52 53 /* Total number of bytes the reader expects to read. */ 54 size_t reader_bytes; 55 56 /* Current state of the update reader. */ 57 FbImplState fb_state; 58 59 /* Socket descriptor for the framebuffer client. */ 60 int sock; 61 62 /* Custom i/o handler */ 63 LoopIo io[1]; 64 65 /* Number of bits used to encode single pixel. */ 66 int bits_per_pixel; 67 } FrameBufferImpl; 68 69 /* One and the only FrameBufferImpl instance. */ 70 static FrameBufferImpl _fbImpl; 71 72 /* 73 * Updates a display rectangle. 74 * Param 75 * fb - Framebuffer where to update the rectangle. 76 * x, y, w, and h define rectangle to update. 77 * bits_per_pixel define number of bits used to encode a single pixel. 78 * pixels contains pixels for the rectangle. Buffer addressed by this parameter 79 * must be eventually freed with free() 80 */ 81 static void 82 _update_rect(QFrameBuffer* fb, uint16_t x, uint16_t y, uint16_t w, uint16_t h, 83 uint8_t bits_per_pixel, uint8_t* pixels) 84 { 85 if (fb != NULL) { 86 uint16_t n; 87 const uint8_t* src = pixels; 88 const uint16_t src_line_size = w * ((bits_per_pixel + 7) / 8); 89 uint8_t* dst = (uint8_t*)fb->pixels + y * fb->pitch + x * 90 fb->bytes_per_pixel; 91 for (n = 0; n < h; n++) { 92 memcpy(dst, src, src_line_size); 93 src += src_line_size; 94 dst += fb->pitch; 95 } 96 qframebuffer_update(fb, x, y, w, h); 97 } 98 free(pixels); 99 } 100 101 /* 102 * Asynchronous I/O callback launched when framebuffer notifications are ready 103 * to be read. 104 * Param: 105 * opaque - FrameBufferImpl instance. 106 */ 107 static void 108 _fbUpdatesImpl_io_callback(void* opaque, int fd, unsigned events) 109 { 110 FrameBufferImpl* fbi = opaque; 111 int ret; 112 113 // Read updates while they are immediately available. 114 for (;;) { 115 // Read next chunk of data. 116 ret = socket_recv(fbi->sock, fbi->reader_buffer + fbi->reader_offset, 117 fbi->reader_bytes - fbi->reader_offset); 118 if (ret == 0) { 119 /* disconnection ! */ 120 fbUpdatesImpl_destroy(); 121 return; 122 } 123 if (ret < 0) { 124 if (errno == EINTR) { 125 /* loop on EINTR */ 126 continue; 127 } else if (errno == EWOULDBLOCK || errno == EAGAIN) { 128 // Chunk is not avalable at this point. Come back later. 129 return; 130 } 131 } 132 133 fbi->reader_offset += ret; 134 if (fbi->reader_offset != fbi->reader_bytes) { 135 // There are still some data left in the pipe. 136 continue; 137 } 138 139 // All expected data has been read. Time to change the state. 140 if (fbi->fb_state == EXPECTS_HEADER) { 141 // Update header has been read. Prepare for the pixels. 142 fbi->fb_state = EXPECTS_PIXELS; 143 fbi->reader_offset = 0; 144 fbi->reader_bytes = fbi->update_header.w * 145 fbi->update_header.h * 146 (fbi->bits_per_pixel / 8); 147 fbi->reader_buffer = malloc(fbi->reader_bytes); 148 if (fbi->reader_buffer == NULL) { 149 APANIC("Unable to allocate memory for framebuffer update\n"); 150 } 151 } else { 152 // Pixels have been read. Prepare for the header. 153 uint8_t* pixels = fbi->reader_buffer; 154 155 fbi->fb_state = EXPECTS_HEADER; 156 fbi->reader_offset = 0; 157 fbi->reader_bytes = sizeof(FBUpdateMessage); 158 fbi->reader_buffer = (uint8_t*)&fbi->update_header; 159 160 // Perform the update. Note that pixels buffer must be freed there. 161 _update_rect(fbi->fb, fbi->update_header.x, 162 fbi->update_header.y, fbi->update_header.w, 163 fbi->update_header.h, fbi->bits_per_pixel, 164 pixels); 165 } 166 } 167 } 168 169 int 170 fbUpdatesImpl_create(SockAddress* console_socket, 171 const char* protocol, 172 QFrameBuffer* fb, 173 Looper* looper) 174 { 175 FrameBufferImpl* fbi = &_fbImpl; 176 char* handshake = NULL; 177 char switch_cmd[256]; 178 179 // Initialize descriptor. 180 fbi->fb = fb; 181 fbi->reader_buffer = (uint8_t*)&fbi->update_header; 182 fbi->reader_offset = 0; 183 fbi->reader_bytes = sizeof(FBUpdateMessage); 184 185 // Connect to the framebuffer service. 186 snprintf(switch_cmd, sizeof(switch_cmd), "framebuffer %s", protocol); 187 fbi->core_connection = 188 core_connection_create_and_switch(console_socket, switch_cmd, &handshake); 189 if (fbi->core_connection == NULL) { 190 derror("Unable to connect to the framebuffer service: %s\n", 191 errno_str); 192 return -1; 193 } 194 195 // We expect core framebuffer to return us bits per pixel property in 196 // the handshake message. 197 fbi->bits_per_pixel = 0; 198 if (handshake != NULL) { 199 char* bpp = strstr(handshake, "bitsperpixel="); 200 if (bpp != NULL) { 201 char* end; 202 bpp += strlen("bitsperpixel="); 203 end = strchr(bpp, ' '); 204 if (end == NULL) { 205 end = bpp + strlen(bpp); 206 } 207 fbi->bits_per_pixel = strtol(bpp, &end, 0); 208 } 209 } 210 if (!fbi->bits_per_pixel) { 211 derror("Unexpected core framebuffer reply: %s\n" 212 "Bits per pixel property is not there, or is invalid\n", 213 handshake); 214 fbUpdatesImpl_destroy(); 215 return -1; 216 } 217 218 fbi->sock = core_connection_get_socket(fbi->core_connection); 219 220 // At last setup read callback, and start receiving the updates. 221 loopIo_init(fbi->io, looper, fbi->sock, 222 _fbUpdatesImpl_io_callback, &_fbImpl); 223 loopIo_wantRead(fbi->io); 224 { 225 // Force the core to send us entire framebuffer now, when we're prepared 226 // to receive it. 227 FBRequestHeader hd; 228 SyncSocket* sk = syncsocket_init(fbi->sock); 229 230 hd.request_type = AFB_REQUEST_REFRESH; 231 syncsocket_start_write(sk); 232 syncsocket_write(sk, &hd, sizeof(hd), 5000); 233 syncsocket_stop_write(sk); 234 syncsocket_free(sk); 235 } 236 237 fprintf(stdout, "framebuffer is now connected to the core at %s.", 238 sock_address_to_string(console_socket)); 239 if (handshake != NULL) { 240 if (handshake[0] != '\0') { 241 fprintf(stdout, " Handshake: %s", handshake); 242 } 243 free(handshake); 244 } 245 fprintf(stdout, "\n"); 246 247 return 0; 248 } 249 250 void 251 fbUpdatesImpl_destroy(void) 252 { 253 FrameBufferImpl* fbi = &_fbImpl; 254 255 if (fbi->core_connection != NULL) { 256 // Disable the reader callback. 257 loopIo_done(fbi->io); 258 259 // Close framebuffer connection. 260 core_connection_close(fbi->core_connection); 261 core_connection_free(fbi->core_connection); 262 fbi->core_connection = NULL; 263 } 264 265 fbi->fb = NULL; 266 if (fbi->reader_buffer != NULL && 267 fbi->reader_buffer != (uint8_t*)&fbi->update_header) { 268 free(fbi->reader_buffer); 269 fbi->reader_buffer = (uint8_t*)&fbi->update_header; 270 } 271 } 272