static void smartcard_init(void) { ChannelCbs channel_cbs = { NULL, }; ClientCbs client_cbs = { NULL, }; uint32_t migration_flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER; spice_assert(!g_smartcard_channel); channel_cbs.config_socket = smartcard_channel_client_config_socket; channel_cbs.on_disconnect = smartcard_channel_on_disconnect; channel_cbs.send_item = smartcard_channel_send_item; channel_cbs.hold_item = smartcard_channel_hold_pipe_item; channel_cbs.release_item = smartcard_channel_release_pipe_item; channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark; channel_cbs.handle_migrate_data = smartcard_channel_client_handle_migrate_data; g_smartcard_channel = (SmartCardChannel*)red_channel_create(sizeof(SmartCardChannel), core, SPICE_CHANNEL_SMARTCARD, 0, FALSE /* handle_acks */, smartcard_channel_handle_message, &channel_cbs, migration_flags); if (!g_smartcard_channel) { spice_error("failed to allocate Smartcard Channel"); } client_cbs.connect = smartcard_connect_client; red_channel_register_client_cbs(&g_smartcard_channel->base, &client_cbs); reds_register_channel(&g_smartcard_channel->base); }
SpiceCharDeviceState *spicevmc_device_connect(SpiceCharDeviceInstance *sin, uint8_t channel_type) { static uint8_t id[256] = { 0, }; SpiceVmcState *state; ChannelCbs channel_cbs = { NULL, }; ClientCbs client_cbs = { NULL, }; SpiceCharDeviceCallbacks char_dev_cbs = {NULL, }; channel_cbs.config_socket = spicevmc_red_channel_client_config_socket; channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect; channel_cbs.send_item = spicevmc_red_channel_send_item; channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item; channel_cbs.release_item = spicevmc_red_channel_release_pipe_item; channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark; channel_cbs.handle_migrate_data = spicevmc_channel_client_handle_migrate_data; state = (SpiceVmcState*)red_channel_create(sizeof(SpiceVmcState), core, channel_type, id[channel_type]++, FALSE /* handle_acks */, spicevmc_red_channel_client_handle_message, &channel_cbs, SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER); red_channel_init_outgoing_messages_window(&state->channel); client_cbs.connect = spicevmc_connect; red_channel_register_client_cbs(&state->channel, &client_cbs); char_dev_cbs.read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev; char_dev_cbs.ref_msg_to_client = spicevmc_chardev_ref_msg_to_client; char_dev_cbs.unref_msg_to_client = spicevmc_chardev_unref_msg_to_client; char_dev_cbs.send_msg_to_client = spicevmc_chardev_send_msg_to_client; char_dev_cbs.send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client; char_dev_cbs.remove_client = spicevmc_char_dev_remove_client; state->chardev_st = spice_char_device_state_create(sin, 0, /* tokens interval */ ~0, /* self tokens */ &char_dev_cbs, state); state->chardev_sin = sin; reds_register_channel(&state->channel); return state->chardev_st; }
RedDispatcher *red_dispatcher_init(QXLInstance *qxl) { RedDispatcher *red_dispatcher; RedWorkerMessage message; WorkerInitData init_data; QXLDevInitInfo init_info; int r; RedChannel *display_channel; RedChannel *cursor_channel; sigset_t thread_sig_mask; sigset_t curr_sig_mask; ClientCbs client_cbs = { NULL, }; quic_init(); sw_canvas_init(); #ifdef USE_OPENGL gl_canvas_init(); #endif // USE_OPENGL red_dispatcher = spice_new0(RedDispatcher, 1); ring_init(&red_dispatcher->async_commands); spice_debug("red_dispatcher->async_commands.next %p", red_dispatcher->async_commands.next); dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL); init_data.qxl = red_dispatcher->qxl = qxl; init_data.id = qxl->id; init_data.red_dispatcher = red_dispatcher; init_data.pending = &red_dispatcher->pending; init_data.num_renderers = num_renderers; memcpy(init_data.renderers, renderers, sizeof(init_data.renderers)); pthread_mutex_init(&red_dispatcher->async_lock, NULL); init_data.image_compression = image_compression; init_data.jpeg_state = jpeg_state; init_data.zlib_glz_state = zlib_glz_state; init_data.streaming_video = streaming_video; red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR; red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR; red_dispatcher->base.wakeup = qxl_worker_wakeup; red_dispatcher->base.oom = qxl_worker_oom; red_dispatcher->base.start = qxl_worker_start; red_dispatcher->base.stop = qxl_worker_stop; red_dispatcher->base.update_area = qxl_worker_update_area; red_dispatcher->base.add_memslot = qxl_worker_add_memslot; red_dispatcher->base.del_memslot = qxl_worker_del_memslot; red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots; red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces; red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface; red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface; red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache; red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor; red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; qxl->st->qif->get_init_info(qxl, &init_info); init_data.memslot_id_bits = init_info.memslot_id_bits; init_data.memslot_gen_bits = init_info.memslot_gen_bits; init_data.num_memslots = init_info.num_memslots; init_data.num_memslots_groups = init_info.num_memslots_groups; init_data.internal_groupslot_id = init_info.internal_groupslot_id; init_data.n_surfaces = init_info.n_surfaces; num_active_workers = 1; sigfillset(&thread_sig_mask); sigdelset(&thread_sig_mask, SIGILL); sigdelset(&thread_sig_mask, SIGFPE); sigdelset(&thread_sig_mask, SIGSEGV); pthread_sigmask(SIG_SETMASK, &thread_sig_mask, &curr_sig_mask); if ((r = pthread_create(&red_dispatcher->worker_thread, NULL, red_worker_main, &init_data))) { spice_error("create thread failed %d", r); } pthread_sigmask(SIG_SETMASK, &curr_sig_mask, NULL); read_message(red_dispatcher->dispatcher.send_fd, &message); spice_assert(message == RED_WORKER_MESSAGE_READY); display_channel = red_dispatcher_display_channel_create(red_dispatcher); if (display_channel) { client_cbs.connect = red_dispatcher_set_display_peer; client_cbs.disconnect = red_dispatcher_disconnect_display_peer; client_cbs.migrate = red_dispatcher_display_migrate; red_channel_register_client_cbs(display_channel, &client_cbs); red_channel_set_data(display_channel, red_dispatcher); red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); reds_register_channel(display_channel); } cursor_channel = red_dispatcher_cursor_channel_create(red_dispatcher); if (cursor_channel) { client_cbs.connect = red_dispatcher_set_cursor_peer; client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer; client_cbs.migrate = red_dispatcher_cursor_migrate; red_channel_register_client_cbs(cursor_channel, &client_cbs); red_channel_set_data(cursor_channel, red_dispatcher); reds_register_channel(cursor_channel); } qxl->st->qif->attache_worker(qxl, &red_dispatcher->base); qxl->st->qif->set_compression_level(qxl, calc_compression_level()); red_dispatcher->next = dispatchers; dispatchers = red_dispatcher; return red_dispatcher; }