/** * Called when we get a rfbFramebufferUpdate message. */ static void rf_host_fbupdate_hdr(void) { CARD8 hdr_buf[4]; rect_count = buf_get_CARD16(&cur_slot->readbuf[1]); if (rect_count == 0xFFFF) { log_write(LL_DETAIL, "Receiving framebuffer update"); } else { log_write(LL_DETAIL, "Receiving framebuffer update, %d rectangle(s)", rect_count); } hdr_buf[0] = 0; memcpy(&hdr_buf[1], cur_slot->readbuf, 3); fbs_spool_data(hdr_buf, 4); if (rect_count) { aio_setread(rf_host_fbupdate_recthdr, NULL, 12); } else { log_write(LL_DEBUG, "Requesting incremental framebuffer update"); request_update(1); aio_setread(rf_host_msg, NULL, 1); } }
static void rf_host_hextile_subenc(void) { int data_size; /* Copy data for saving in a file if necessary */ fbs_spool_byte(cur_slot->readbuf[0]); s_subenc = cur_slot->readbuf[0]; if (s_subenc & RFB_HEXTILE_RAW) { data_size = s_tile.w * s_tile.h * sizeof(CARD32); aio_setread(rf_host_hextile_raw, hextile_buf, data_size); return; } data_size = 0; if (s_subenc & RFB_HEXTILE_BG_SPECIFIED) { data_size += sizeof(CARD32); } else { fill_fb_rect(&s_tile, s_bg); } if (s_subenc & RFB_HEXTILE_FG_SPECIFIED) data_size += sizeof(CARD32); if (s_subenc & RFB_HEXTILE_ANY_SUBRECTS) data_size += sizeof(CARD8); if (data_size) { aio_setread(rf_host_hextile_hex, hextile_buf, data_size); } else { hextile_next_tile(); } }
static void rf_host_msg(void) { int msg_id; msg_id = (int)cur_slot->readbuf[0] & 0xFF; switch(msg_id) { case rfbFramebufferUpdate: aio_setread(rf_host_fbupdate_hdr, NULL, 3); break; case rfbSetColourMapEntries: aio_setread(rf_host_colormap_hdr, NULL, 5); break; case rfbBell: log_write(LL_DETAIL, "Received Bell message from host"); fbs_write_data(cur_slot->readbuf, 1); aio_setread(rf_host_msg, NULL, 1); break; case rfbServerCutText: aio_setread(rf_host_cuttext_hdr, NULL, 7); break; default: log_write(LL_ERROR, "Unknown server message type: %d", msg_id); aio_close(0); } }
/* * This function is called by decoders after each rectangle * has been successfully decoded. */ void fbupdate_rect_done(void) { if (cur_rect.w != 0 && cur_rect.h != 0) { log_write(LL_DEBUG, "Received rectangle ok"); /* Cached data for this rectangle is not valid any more */ invalidate_enc_cache(&cur_rect); /* Save data in a file if necessary */ fbs_flush_data(); /* Queue this rectangle for each client */ aio_walk_slots(fn_host_add_client_rect, TYPE_CL_SLOT); } if (--rect_count) { aio_setread(rf_host_fbupdate_recthdr, NULL, 12); } else { /* Done with the whole update */ aio_walk_slots(fn_client_send_rects, TYPE_CL_SLOT); log_write(LL_DEBUG, "Requesting incremental framebuffer update"); request_update(1); aio_setread(rf_host_msg, NULL, 1); } }
static void rf_client_ver(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; CARD8 msg[20]; /* FIXME: Check protocol version. */ /* FIXME: Functions like authentication should be available in separate modules, not in I/O part of the code. */ /* FIXME: Higher level I/O functions should be implemented instead of things like buf_put_CARD32 + aio_write. */ log_write(LL_DETAIL, "Client supports %.11s", cur_slot->readbuf); if (s_password[0]) { /* Request VNC authentication */ buf_put_CARD32(msg, 2); /* Prepare "random" challenge */ rfb_gen_challenge(cl->auth_challenge); memcpy(&msg[4], cl->auth_challenge, 16); /* Send both auth ID and challenge */ aio_write(NULL, msg, 20); aio_setread(rf_client_auth, NULL, 16); } else { log_write(LL_WARN, "Not requesting authentication from %s", cur_slot->name); buf_put_CARD32(msg, 1); aio_write(NULL, msg, 4); aio_setread(rf_client_initmsg, NULL, 1); } }
static void rf_host_colormap_hdr(void) { CARD16 num_colors; log_write(LL_WARN, "Ignoring SetColourMapEntries message"); num_colors = buf_get_CARD16(&cur_slot->readbuf[3]); if (num_colors > 0) aio_setread(rf_host_colormap_data, NULL, num_colors * 6); else aio_setread(rf_host_msg, NULL, 1); }
static void rf_client_auth(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; unsigned char resp_rw[16]; unsigned char resp_ro[16]; unsigned char msg[4]; /* Place correct crypted responses to resp_rw, resp_ro */ rfb_crypt(resp_rw, cl->auth_challenge, s_password); rfb_crypt(resp_ro, cl->auth_challenge, s_password_ro); /* Compare client response with correct ones */ /* FIXME: Implement "too many tries" functionality some day. */ if (memcmp(cur_slot->readbuf, resp_rw, 16) == 0) { cl->readonly = 0; log_write(LL_MSG, "Full-control authentication passed by %s", cur_slot->name); } else if (memcmp(cur_slot->readbuf, resp_ro, 16) == 0) { cl->readonly = 1; log_write(LL_MSG, "Read-only authentication passed by %s", cur_slot->name); } else { log_write(LL_WARN, "Authentication failed for %s", cur_slot->name); buf_put_CARD32(msg, 1); aio_write(wf_client_auth_failed, msg, 4); return; } buf_put_CARD32(msg, 0); aio_write(NULL, msg, 4); aio_setread(rf_client_initmsg, NULL, 1); }
static void rf_client_ptrevent(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; CARD16 x, y; CARD8 msg[6]; if (!cl->readonly) { msg[0] = 5; /* PointerEvent */ msg[1] = cur_slot->readbuf[0]; x = buf_get_CARD16(&cur_slot->readbuf[1]); y = buf_get_CARD16(&cur_slot->readbuf[3]); /* Pointer position should fit in the host screen */ if (x >= g_screen_info.width) x = g_screen_info.width - 1; if (y >= g_screen_info.height) y = g_screen_info.height - 1; buf_put_CARD16(&msg[2], x); buf_put_CARD16(&msg[4], y); pass_msg_to_host(msg, sizeof(msg)); } aio_setread(rf_client_msg, NULL, 1); }
static void rf_host_hextile_hex(void) { CARD32 *from_ptr = hextile_buf; int data_size; /* Get background and foreground colors */ if (s_subenc & RFB_HEXTILE_BG_SPECIFIED) { s_bg = *from_ptr++; fill_fb_rect(&s_tile, s_bg); } if (s_subenc & RFB_HEXTILE_FG_SPECIFIED) { s_fg = *from_ptr++; } if (s_subenc & RFB_HEXTILE_ANY_SUBRECTS) { fbs_spool_data(hextile_buf, (from_ptr - hextile_buf) * sizeof(CARD32) + 1); s_num_subrects = *((CARD8 *)from_ptr); if (s_subenc & RFB_HEXTILE_SUBRECTS_COLOURED) { data_size = 6 * (unsigned int)s_num_subrects; } else { data_size = 2 * (unsigned int)s_num_subrects; } if (data_size > 0) { aio_setread(rf_host_hextile_subrects, NULL, data_size); return; } } else { fbs_spool_data(hextile_buf, (from_ptr - hextile_buf) * sizeof(CARD32)); } hextile_next_tile(); }
/* * Called when keyboard event is received from client. */ static void rf_client_keyevent(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; CARD8 msg[8]; msg[0] = 4; /* KeyEvent */ memcpy(&msg[1], cur_slot->readbuf, 7); { const int counter = msg[2] + msg[3] * 255; /* [2..3] is padding */ if (counter) { crDebug("VNC SPU: marker event %d", counter); #ifdef NETLOGGER NL_info("vncspu", "spu.marker", "NUMBER=i", counter); #endif #if 0 save_ppm("spuimage.ppm"); #endif } } if (!cl->readonly) { pass_msg_to_host(msg, sizeof(msg)); } aio_setread(rf_client_msg, NULL, 1); }
static void rf_client_encodings_hdr(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; cl->temp_count = buf_get_CARD16(&cur_slot->readbuf[1]); aio_setread(rf_client_encodings_data, NULL, cl->temp_count * sizeof(CARD32)); }
/* * Public functions */ void setread_decode_xcursor(FB_RECT *r) { s_new_curs_rect = *r; if (s_new_curs_rect.w * s_new_curs_rect.h) { aio_setread(rf_host_xcursor_color, s_new_xcursor_colors, sz_rfbXCursorColors); } }
static void rf_client_msg(void) { int msg_id; msg_id = (int)cur_slot->readbuf[0] & 0xFF; switch(msg_id) { case rfbSetPixelFormat: aio_setread(rf_client_pixfmt, NULL, 3 + sizeof(RFB_PIXEL_FORMAT)); break; case rfbFixColourMapEntries: aio_setread(rf_client_colormap_hdr, NULL, 5); break; case rfbSetEncodings: aio_setread(rf_client_encodings_hdr, NULL, 3); break; case rfbFramebufferUpdateRequest: aio_setread(rf_client_updatereq, NULL, 9); break; case rfbKeyEvent: aio_setread(rf_client_keyevent, NULL, 7); break; case rfbPointerEvent: aio_setread(rf_client_ptrevent, NULL, 5); break; case rfbClientCutText: aio_setread(rf_client_cuttext_hdr, NULL, 7); break; default: log_write(LL_ERROR, "Unknown client message type %d from %s", msg_id, cur_slot->name); aio_close(0); } }
static void rf_client_cuttext_data(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; if (!cl->readonly) pass_cuttext_to_host(cur_slot->readbuf, cl->cut_len); aio_setread(rf_client_msg, NULL, 1); }
static void rf_client_colormap_hdr(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; log_write(LL_WARN, "Ignoring FixColourMapEntries message from %s", cur_slot->name); cl->temp_count = buf_get_CARD16(&cur_slot->readbuf[3]); aio_setread(rf_client_colormap_data, NULL, cl->temp_count * 6); }
static void rf_client_cuttext_hdr(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; log_write(LL_DEBUG, "Receiving ClientCutText message from %s", cur_slot->name); cl->cut_len = (int)buf_get_CARD32(&cur_slot->readbuf[3]); aio_setread(rf_client_cuttext_data, NULL, cl->cut_len); }
void setread_decode_hextile(FB_RECT *r) { s_rect = *r; s_tile.x = s_rect.x; s_tile.y = s_rect.y; s_tile.w = (s_rect.w < 16) ? s_rect.w : 16; s_tile.h = (s_rect.h < 16) ? s_rect.h : 16; aio_setread(rf_host_hextile_subenc, NULL, sizeof(CARD8)); }
static void rf_host_cuttext_hdr(void) { log_write(LL_DETAIL, "Receiving ServerCutText message from host, %lu byte(s)", (unsigned long)cut_len); cut_len = (size_t)buf_get_CARD32(&cur_slot->readbuf[3]); if (cut_len > 0) aio_setread(rf_host_cuttext_data, NULL, cut_len); else rf_host_cuttext_data(); }
static void rf_client_pixfmt(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; buf_get_pixfmt(&cur_slot->readbuf[3], &cl->format); log_write(LL_DETAIL, "Pixel format (%d bpp) set by %s", cl->format.bits_pixel, cur_slot->name); set_trans_func(cl); aio_setread(rf_client_msg, NULL, 1); }
static void rf_host_xcursor_color(void) { CARD32 size; fbs_spool_data(cur_slot->readbuf, sz_rfbXCursorColors); /* calculate size of two cursor bitmaps to follow */ size = ((s_new_curs_rect.w + 7) / 8) * s_new_curs_rect.h * 2; s_new_bmps = realloc(s_new_bmps, size); if (!s_new_bmps) { log_write(LL_ERROR, "Failed to allocate memory for cursor pixmaps"); aio_close(0); return; } s_read_size = size; aio_setread(rf_host_xcursor_bmps, s_new_bmps, size); }
static void rf_client_initmsg(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; unsigned char msg_server_init[24]; if (cur_slot->readbuf[0] == 0) { log_write(LL_WARN, "Non-shared session requested by %s", cur_slot->name); aio_close(0); } /* Save initial desktop geometry for this client */ cl->fb_width = g_screen_info.width; cl->fb_height = g_screen_info.height; cl->enable_newfbsize = 0; cl->enable_cliprects_enc = 0; /* Send ServerInitialisation message */ buf_put_CARD16(msg_server_init, cl->fb_width); buf_put_CARD16(msg_server_init + 2, cl->fb_height); buf_put_pixfmt(msg_server_init + 4, &g_screen_info.pixformat); buf_put_CARD32(msg_server_init + 20, g_screen_info.name_length); aio_write(NULL, msg_server_init, 24); aio_write(NULL, g_screen_info.name, g_screen_info.name_length); aio_setread(rf_client_msg, NULL, 1); /* Set up initial pixel format and encoders' parameters */ memcpy(&cl->format, &g_screen_info.pixformat, sizeof(RFB_PIXEL_FORMAT)); cl->trans_func = transfunc_null; cl->bgr233_f = 0; cl->compress_level = 6; /* default compression level */ cl->jpeg_quality = -1; /* disable JPEG by default */ /* The client did not request framebuffer updates yet */ cl->update_requested = 0; cl->update_in_progress = 0; REGION_INIT(&cl->pending_region, NullBox, 16); REGION_INIT(&cl->copy_region, NullBox, 8); cl->newfbsize_pending = 0; cl->new_cliprects = 0; /* We are connected. */ cl->connected = 1; }
void af_client_accept(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; int i; /* FIXME: Function naming is bad (client_accept_hook?). */ cur_slot->type = TYPE_CL_SLOT; cl->connected = 0; cl->trans_table = NULL; aio_setclose(cf_client); for (i = 0; i < 4; i++) cl->zs_active[i] = 0; log_write(LL_MSG, "Accepted connection from %s", cur_slot->name); aio_write(NULL, "RFB 003.003\n", 12); aio_setread(rf_client_ver, NULL, 12); }
static void rf_host_fbupdate_raw(void) { #ifdef CHROMIUM CARD32 *g_framebuffer; CARD16 g_fb_width, g_fb_height; g_framebuffer = GetFrameBuffer(&g_fb_width, &g_fb_height); #endif fbs_spool_data(cur_slot->readbuf, cur_rect.w * sizeof(CARD32)); if (++rect_cur_row < cur_rect.h) { /* Read next row */ CARD32 *dst = PIXEL_ADDR(g_framebuffer, g_fb_width, g_fb_height, cur_rect.x, cur_rect.y + rect_cur_row); aio_setread(rf_host_fbupdate_raw, dst, cur_rect.w * sizeof(CARD32)); } else { /* Done with this rectangle */ fbupdate_rect_done(); } }
static void host_really_activate(AIO_SLOT *slot) { AIO_SLOT *saved_slot = cur_slot; HOST_SLOT *hs = (HOST_SLOT *)slot; log_write(LL_MSG, "Activating new host connection"); slot->type = TYPE_HOST_ACTIVE_SLOT; s_host_slot = slot; write_active_file(); perform_action("host_activate"); /* Allocate the framebuffer or extend its dimensions if necessary */ if (!alloc_framebuffer(hs->fb_width, hs->fb_height)) { aio_close(1); return; } /* Set default desktop geometry for new client connections */ g_screen_info.width = hs->fb_width; g_screen_info.height = hs->fb_height; /* If requested, open file to save this session and write the header */ fbs_open_file(hs->fb_width, hs->fb_height); cur_slot = slot; /* Reset zlib streams in the Tight decoder */ reset_tight_streams(); /* Request initial screen contents */ log_write(LL_DETAIL, "Requesting full framebuffer update"); request_update(0); aio_setread(rf_host_msg, NULL, 1); /* Notify clients about desktop geometry change */ aio_walk_slots(fn_host_pass_newfbsize, TYPE_CL_SLOT); cur_slot = saved_slot; }
void setread_decode_richcursor(FB_RECT *r) { CARD32 size; s_new_curs_rect = *r; if (s_new_curs_rect.w * s_new_curs_rect.h) { /* calculate size of two cursor bitmaps to follow */ /* cursor image in client pixel format */ /* transparency data for cursor */ size = s_new_curs_rect.w * s_new_curs_rect.h * (g_screen_info.pixformat.bits_pixel / 8); size += ((s_new_curs_rect.w + 7) / 8) * s_new_curs_rect.h; s_new_bmps = realloc(s_new_bmps, size); if (!s_new_bmps) { log_write(LL_ERROR, "Failed to allocate memory for cursor pixmaps"); aio_close(0); return; } s_read_size = size; aio_setread(rf_host_richcursor_bmps, s_new_bmps, size); } }
static void hextile_next_tile(void) { if (s_tile.x + 16 < s_rect.x + s_rect.w) { /* Next tile in the same row */ s_tile.x += 16; if (s_tile.x + 16 < s_rect.x + s_rect.w) s_tile.w = 16; else s_tile.w = s_rect.x + s_rect.w - s_tile.x; } else if (s_tile.y + 16 < s_rect.y + s_rect.h) { /* First tile in the next row */ s_tile.x = s_rect.x; s_tile.w = (s_rect.w < 16) ? s_rect.w : 16; s_tile.y += 16; if (s_tile.y + 16 < s_rect.y + s_rect.h) s_tile.h = 16; else s_tile.h = s_rect.y + s_rect.h - s_tile.y; } else { fbupdate_rect_done(); /* No more tiles */ return; } aio_setread(rf_host_hextile_subenc, NULL, 1); }
static void rf_host_fbupdate_recthdr(void) { HOST_SLOT *hs = (HOST_SLOT *)cur_slot; #ifdef CHROMIUM CARD32 *g_framebuffer; CARD16 g_fb_width, g_fb_height; g_framebuffer = GetFrameBuffer(&g_fb_width, &g_fb_height); #endif cur_rect.x = buf_get_CARD16(cur_slot->readbuf); cur_rect.y = buf_get_CARD16(&cur_slot->readbuf[2]); cur_rect.w = buf_get_CARD16(&cur_slot->readbuf[4]); cur_rect.h = buf_get_CARD16(&cur_slot->readbuf[6]); cur_rect.enc = buf_get_CARD32(&cur_slot->readbuf[8]); fbs_spool_data(cur_slot->readbuf, 12); /* Handle LastRect "encoding" first */ if (cur_rect.enc == RFB_ENCODING_LASTRECT) { log_write(LL_DEBUG, "LastRect marker received from the host"); cur_rect.x = cur_rect.y = 0; rect_count = 1; fbupdate_rect_done(); return; } /* Ignore zero-size rectangles */ if (cur_rect.h == 0 || cur_rect.w == 0) { log_write(LL_WARN, "Zero-size rectangle %dx%d at %d,%d (ignoring)", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); fbupdate_rect_done(); return; } /* Handle NewFBSize "encoding", as a special case */ if (cur_rect.enc == RFB_ENCODING_NEWFBSIZE) { log_write(LL_INFO, "New host desktop geometry: %dx%d", (int)cur_rect.w, (int)cur_rect.h); g_screen_info.width = hs->fb_width = cur_rect.w; g_screen_info.height = hs->fb_height = cur_rect.h; /* Reallocate the framebuffer if necessary */ if (!alloc_framebuffer(hs->fb_width, hs->fb_height)) { aio_close(1); return; } cur_rect.x = cur_rect.y = 0; /* NewFBSize is always the last rectangle regardless of rect_count */ rect_count = 1; fbupdate_rect_done(); return; } /* Prevent overflow of the framebuffer */ if (cur_rect.x >= g_fb_width || cur_rect.x + cur_rect.w > g_fb_width || cur_rect.y >= g_fb_height || cur_rect.y + cur_rect.h > g_fb_height) { log_write(LL_ERROR, "Rectangle out of framebuffer bounds: %dx%d at %d,%d", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); aio_close(0); return; } /* Ok, now the rectangle seems correct */ log_write(LL_DEBUG, "Receiving rectangle %dx%d at %d,%d", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); switch(cur_rect.enc) { case RFB_ENCODING_RAW: log_write(LL_DEBUG, "Receiving raw data, expecting %d byte(s)", cur_rect.w * cur_rect.h * sizeof(CARD32)); rect_cur_row = 0; aio_setread(rf_host_fbupdate_raw, PIXEL_ADDR(g_framebuffer, g_fb_width, g_fb_height, cur_rect.x, cur_rect.y), cur_rect.w * sizeof(CARD32)); break; case RFB_ENCODING_COPYRECT: log_write(LL_DEBUG, "Receiving CopyRect instruction"); aio_setread(rf_host_copyrect, NULL, 4); break; case RFB_ENCODING_HEXTILE: log_write(LL_DEBUG, "Receiving Hextile-encoded data"); setread_decode_hextile(&cur_rect); break; case RFB_ENCODING_TIGHT: log_write(LL_DEBUG, "Receiving Tight-encoded data"); setread_decode_tight(&cur_rect); break; default: log_write(LL_ERROR, "Unknown encoding: 0x%08lX", (unsigned long)cur_rect.enc); aio_close(0); } }
/** * Handle an incoming rfbFramebufferUpdateRequest message. * Determine the dirty regions and send pixel rect data to the client. */ static void rf_client_updatereq(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; RegionRec tmp_region; BoxRec rect; /*crDebug("Got Update request from %s", cur_slot->name);*/ #ifdef NETLOGGER if (vnc_spu.netlogger_url) { cl->serial_number++; NL_info("vncspu", "spu.fbrequest.receive", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } #endif /* the requested region of interest */ rect.x1 = buf_get_CARD16(&cur_slot->readbuf[1]); rect.y1 = buf_get_CARD16(&cur_slot->readbuf[3]); rect.x2 = rect.x1 + buf_get_CARD16(&cur_slot->readbuf[5]); rect.y2 = rect.y1 + buf_get_CARD16(&cur_slot->readbuf[7]); /* Make sure the rectangle bounds fit the framebuffer. */ if (rect.x1 > cl->fb_width) rect.x1 = cl->fb_width; if (rect.y1 > cl->fb_height) rect.y1 = cl->fb_height; if (rect.x2 > cl->fb_width) rect.x2 = cl->fb_width; if (rect.y2 > cl->fb_height) rect.y2 = cl->fb_height; cl->update_rect = rect; cl->update_requested = 1; cl->num_update_requests++; if (!cur_slot->readbuf[0]) { log_write(LL_DEBUG, "Received framebuffer update request (full) from %s", cur_slot->name); if (!cl->newfbsize_pending) { REGION_INIT(&tmp_region, &rect, 1); #if 0 /* Disabling this code prevents the region from outside the GL * window (garbage) from being sent to the viewer. */ REGION_UNION(&cl->pending_region, &cl->pending_region, &tmp_region); #endif REGION_UNION(&cl->pending_region, &cl->pending_region, &cl->copy_region); REGION_EMPTY(&cl->copy_region); REGION_UNINIT(&tmp_region); } } else { log_write(LL_DEBUG, "Received framebuffer update request from %s", cur_slot->name); } if (!cl->update_in_progress) { int k = (cl->newfbsize_pending || cl->new_cliprects || REGION_NOTEMPTY(&cl->copy_region) || vncspuWaitDirtyRects(&cl->pending_region, &cl->update_rect, cl->serial_number)); if (k) { send_update(); } } aio_setread(rf_client_msg, NULL, 1); }
static void rf_host_cuttext_data(void) { cut_text = cur_slot->readbuf; aio_walk_slots(fn_host_pass_cuttext, TYPE_CL_SLOT); aio_setread(rf_host_msg, NULL, 1); }
static void rf_host_colormap_data(void) { /* Nothing to do with colormap */ aio_setread(rf_host_msg, NULL, 1); }