[Spice-devel] [RFC 1/2] spice, server: introduce SpiceCharDevice
Alon Levy
alevy at redhat.com
Wed Aug 25 03:53:14 PDT 2010
SpiceCharDevice{Interface,Instance} replaces SpiceVDIPort*.
This gives nothing right now, but lets us support smartcard and other
interfaces that rely on a char device without having to introduce further
patches to qemu.
The changes are:
* spice_server_add_interface delegates to spice_server_char_device_add_interface
* which uses (*subtype) to determine what to do on server side.
* (*wakeup) replaces spice_vdi_port_wakeup.
---
server/reds.c | 89 +++++++++++++++++++++++++++++--------------
server/spice-experimental.h | 35 ++++++++++-------
2 files changed, 80 insertions(+), 44 deletions(-)
diff --git a/server/reds.c b/server/reds.c
index 571013f..bb5b129 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -63,7 +63,7 @@ SpiceCoreInterface *core = NULL;
static SpiceKbdInstance *keyboard = NULL;
static SpiceMouseInstance *mouse = NULL;
static SpiceTabletInstance *tablet = NULL;
-static SpiceVDIPortInstance *vdagent = NULL;
+static SpiceCharDeviceInstance *vdagent = NULL;
#define MIGRATION_NOTIFY_SPICE_KEY "spice_mig_ext"
@@ -734,8 +734,8 @@ static void reds_disconnect()
reds_reset_outgoing();
if (reds->agent_state.connected) {
- SpiceVDIPortInterface *sif;
- sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+ SpiceCharDeviceInterface *sif;
+ sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
reds->agent_state.connected = 0;
if (sif->state) {
sif->state(vdagent, reds->agent_state.connected);
@@ -1085,8 +1085,8 @@ static void reds_send_agent_disconnected()
static void reds_agent_remove()
{
- SpiceVDIPortInstance *sin = vdagent;
- SpiceVDIPortInterface *sif;
+ SpiceCharDeviceInstance *sin = vdagent;
+ SpiceCharDeviceInterface *sif;
vdagent = NULL;
reds_update_mouse_mode();
@@ -1096,7 +1096,7 @@ static void reds_agent_remove()
}
ASSERT(reds->agent_state.connected)
- sif = SPICE_CONTAINEROF(sin->base.sif, SpiceVDIPortInterface, base);
+ sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
reds->agent_state.connected = 0;
if (sif->state) {
sif->state(sin, reds->agent_state.connected);
@@ -1151,7 +1151,7 @@ static void vdi_port_write_retry()
static int write_to_vdi_port()
{
VDIPortState *state = &reds->agent_state;
- SpiceVDIPortInterface *sif;
+ SpiceCharDeviceInterface *sif;
RingItem *ring_item;
VDIPortBuf *buf;
int total = 0;
@@ -1161,7 +1161,7 @@ static int write_to_vdi_port()
return 0;
}
- sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+ sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
while (reds->agent_state.connected) {
if (!(ring_item = ring_get_tail(&state->write_queue))) {
break;
@@ -1227,7 +1227,7 @@ static int read_from_vdi_port(void)
static int inside_call = 0;
int quit_loop = 0;
VDIPortState *state = &reds->agent_state;
- SpiceVDIPortInterface *sif;
+ SpiceCharDeviceInterface *sif;
VDIReadBuf *dispatch_buf;
int total = 0;
int n;
@@ -1241,7 +1241,7 @@ static int read_from_vdi_port(void)
return 0;
}
- sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+ sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
while (!quit_loop && reds->agent_state.connected) {
switch (state->read_state) {
case VDI_PORT_READ_STATE_READ_HADER:
@@ -1310,7 +1310,7 @@ static int read_from_vdi_port(void)
return total;
}
-__visible__ void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin)
+__visible__ void spice_server_vdi_port_wakeup(SpiceCharDeviceInstance *sin)
{
while (read_from_vdi_port());
}
@@ -2042,8 +2042,8 @@ static void reds_handle_main_link(RedLinkInfo *link)
reds_show_new_channel(link);
__reds_release_link(link);
if (vdagent) {
- SpiceVDIPortInterface *sif;
- sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+ SpiceCharDeviceInterface *sif;
+ sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
reds->agent_state.connected = 1;
if (sif->state) {
sif->state(vdagent, reds->agent_state.connected);
@@ -3391,17 +3391,17 @@ static void mm_timer_proc(void *opaque)
core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
}
-static void attach_to_red_agent(SpiceVDIPortInstance *sin)
+static void attach_to_red_agent(SpiceCharDeviceInstance *sin)
{
VDIPortState *state = &reds->agent_state;
- SpiceVDIPortInterface *sif;
+ SpiceCharDeviceInterface *sif;
vdagent = sin;
reds_update_mouse_mode();
if (!reds->peer) {
return;
}
- sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+ sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
state->connected = 1;
if (sif->state) {
sif->state(vdagent, state->connected);
@@ -3415,6 +3415,40 @@ static void attach_to_red_agent(SpiceVDIPortInstance *sin)
reds_send_agent_connected();
}
+__visible__ int spice_server_char_device_recognized_subtype(const char* subtype)
+{
+ return (strcmp(subtype, "vdagent") == 0 || strcmp(subtype, "smartcard") == 0);
+}
+
+__visible__ const char* spice_server_char_device_supported_subtypes(void)
+{
+ return "vdagent, smartcard";
+}
+
+int spice_server_char_device_add_interface(SpiceServer *s,
+ SpiceBaseInstance *sin)
+{
+ SpiceCharDeviceInstance* char_device =
+ SPICE_CONTAINEROF(sin, SpiceCharDeviceInstance, base);
+ SpiceCharDeviceInterface* sif;
+
+ sif = SPICE_CONTAINEROF(char_device->base.sif, SpiceCharDeviceInterface, base);
+ const char* subtype = sif->subtype(char_device);
+ if (strcmp(subtype, "vdagent") == 0) {
+ if (vdagent) {
+ red_printf("vdi port already attached");
+ return -1;
+ }
+ char_device->wakeup = &spice_server_vdi_port_wakeup;
+ attach_to_red_agent(char_device);
+ } else if (strcmp(subtype, "smartcard") == 0) {
+ red_printf("smart card not implemented");
+ return -1;
+ }
+
+ return 0;
+}
+
__visible__ int spice_server_add_interface(SpiceServer *s,
SpiceBaseInstance *sin)
{
@@ -3504,18 +3538,14 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
}
snd_attach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
- } else if (strcmp(interface->type, SPICE_INTERFACE_VDI_PORT) == 0) {
- red_printf("SPICE_INTERFACE_VDI_PORT");
- if (vdagent) {
- red_printf("vdi port already attached");
- return -1;
- }
- if (interface->major_version != SPICE_INTERFACE_VDI_PORT_MAJOR ||
- interface->minor_version < SPICE_INTERFACE_VDI_PORT_MINOR) {
- red_printf("unsupported vdi port interface");
+ } else if (strcmp(interface->type, SPICE_INTERFACE_CHAR_DEVICE) == 0) {
+ red_printf("SPICE_INTERFACE_CHAR_DEVICE");
+ if (interface->major_version != SPICE_INTERFACE_CHAR_DEVICE_MAJOR ||
+ interface->minor_version < SPICE_INTERFACE_CHAR_DEVICE_MINOR) {
+ red_printf("unsupported char device interface");
return -1;
}
- attach_to_red_agent(SPICE_CONTAINEROF(sin, SpiceVDIPortInstance, base));
+ spice_server_char_device_add_interface(s, sin);
} else if (strcmp(interface->type, SPICE_INTERFACE_NET_WIRE) == 0) {
#ifdef USE_TUNNEL
@@ -3561,11 +3591,12 @@ __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
red_printf("remove SPICE_INTERFACE_RECORD");
snd_detach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
- } else if (strcmp(interface->type, SPICE_INTERFACE_VDI_PORT) == 0) {
- red_printf("remove SPICE_INTERFACE_VDI_PORT");
- if (sin == &vdagent->base) {
+ } else if (strcmp(interface->type, SPICE_INTERFACE_CHAR_DEVICE) == 0) {
+ red_printf("remove SPICE_INTERFACE_CHAR_DEVICE");
+ if (vdagent && sin == &vdagent->base) {
reds_agent_remove();
}
+ // TODO - smartcard cleanup
} else {
red_error("VD_INTERFACE_REMOVING unsupported");
diff --git a/server/spice-experimental.h b/server/spice-experimental.h
index aede4ce..6c02afb 100644
--- a/server/spice-experimental.h
+++ b/server/spice-experimental.h
@@ -1,26 +1,31 @@
-/* vdi port interface */
+/* char device interfaces */
-#define SPICE_INTERFACE_VDI_PORT "vdi_port"
-#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
-#define SPICE_INTERFACE_VDI_PORT_MINOR 1
-typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
-typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
-typedef struct SpiceVDIPortState SpiceVDIPortState;
+#define SPICE_INTERFACE_CHAR_DEVICE "char_device"
+#define SPICE_INTERFACE_CHAR_DEVICE_MAJOR 1
+#define SPICE_INTERFACE_CHAR_DEVICE_MINOR 1
+typedef struct SpiceCharDeviceInterface SpiceCharDeviceInterface;
+typedef struct SpiceCharDeviceInstance SpiceCharDeviceInstance;
+typedef struct SpiceCharDeviceState SpiceCharDeviceState;
-struct SpiceVDIPortInterface {
+struct SpiceCharDeviceInterface {
SpiceBaseInterface base;
- void (*state)(SpiceVDIPortInstance *sin, int connected);
- int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
- int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
+ /* called by spice */
+ const char* (*subtype)(SpiceCharDeviceInstance *sin);
+ void (*state)(SpiceCharDeviceInstance *sin, int connected);
+ int (*write)(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len);
+ int (*read)(SpiceCharDeviceInstance *sin, uint8_t *buf, int len);
};
-struct SpiceVDIPortInstance {
- SpiceBaseInstance base;
- SpiceVDIPortState *st;
+struct SpiceCharDeviceInstance {
+ SpiceBaseInstance base;
+ SpiceCharDeviceState *st;
+ /* called by spice embedder */
+ void (*wakeup)(SpiceCharDeviceInstance *sin);
};
-void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
+int spice_server_char_device_recognized_subtype(const char* subtype);
+const char* spice_server_char_device_supported_subtypes(void);
/* tunnel interface */
--
1.7.2
More information about the Spice-devel
mailing list