@ -18,6 +18,12 @@ typedef struct SpiceChardev {
QLIST_ENTRY ( SpiceChardev ) next ;
} SpiceChardev ;
# define TYPE_CHARDEV_SPICE "chardev-spice"
# define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
# define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
# define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
typedef struct SpiceCharSource {
GSource source ;
SpiceChardev * scd ;
@ -29,7 +35,7 @@ static QLIST_HEAD(, SpiceChardev) spice_chars =
static int vmc_write ( SpiceCharDeviceInstance * sin , const uint8_t * buf , int len )
{
SpiceChardev * scd = container_of ( sin , SpiceChardev , sin ) ;
Chardev * chr = ( Chardev * ) scd ;
Chardev * chr = CHARDEV ( scd ) ;
ssize_t out = 0 ;
ssize_t last_out ;
uint8_t * p = ( uint8_t * ) buf ;
@ -73,7 +79,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
static void vmc_event ( SpiceCharDeviceInstance * sin , uint8_t event )
{
SpiceChardev * scd = container_of ( sin , SpiceChardev , sin ) ;
Chardev * chr = ( Chardev * ) scd ;
Chardev * chr = CHARDEV ( scd ) ;
int chr_event ;
switch ( event ) {
@ -92,7 +98,7 @@ static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
static void vmc_state ( SpiceCharDeviceInstance * sin , int connected )
{
SpiceChardev * scd = container_of ( sin , SpiceChardev , sin ) ;
Chardev * chr = ( Chardev * ) scd ;
Chardev * chr = CHARDEV ( scd ) ;
if ( ( chr - > be_open & & connected ) | |
( ! chr - > be_open & & ! connected ) ) {
@ -173,7 +179,7 @@ static GSourceFuncs SpiceCharSourceFuncs = {
static GSource * spice_chr_add_watch ( Chardev * chr , GIOCondition cond )
{
SpiceChardev * scd = ( SpiceChardev * ) chr ;
SpiceChardev * scd = SPICE_CHARDEV ( chr ) ;
SpiceCharSource * src ;
assert ( cond & G_IO_OUT ) ;
@ -187,7 +193,7 @@ static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond)
static int spice_chr_write ( Chardev * chr , const uint8_t * buf , int len )
{
SpiceChardev * s = ( SpiceChardev * ) chr ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
int read_bytes ;
assert ( s - > datalen = = 0 ) ;
@ -206,7 +212,7 @@ static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len)
static void spice_chr_free ( struct Chardev * chr )
{
SpiceChardev * s = ( SpiceChardev * ) chr ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
vmc_unregister_interface ( s ) ;
QLIST_REMOVE ( s , next ) ;
@ -219,7 +225,7 @@ static void spice_chr_free(struct Chardev *chr)
static void spice_vmc_set_fe_open ( struct Chardev * chr , int fe_open )
{
SpiceChardev * s = ( SpiceChardev * ) chr ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
if ( fe_open ) {
vmc_register_interface ( s ) ;
} else {
@ -230,7 +236,7 @@ static void spice_vmc_set_fe_open(struct Chardev *chr, int fe_open)
static void spice_port_set_fe_open ( struct Chardev * chr , int fe_open )
{
# if SPICE_SERVER_VERSION >= 0x000c02
SpiceChardev * s = ( SpiceChardev * ) chr ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
if ( fe_open ) {
spice_server_port_event ( & s - > sin , SPICE_PORT_EVENT_OPENED ) ;
@ -242,43 +248,29 @@ static void spice_port_set_fe_open(struct Chardev *chr, int fe_open)
static void spice_chr_accept_input ( struct Chardev * chr )
{
SpiceChardev * s = ( SpiceChardev * ) chr ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
spice_server_char_device_wakeup ( & s - > sin ) ;
}
static Chardev * chr_open ( const CharDriver * driver ,
const char * subtype ,
ChardevCommon * backend ,
Error * * errp )
static void chr_open ( Chardev * chr , const char * subtype )
{
Chardev * chr ;
SpiceChardev * s ;
SpiceChardev * s = SPICE_CHARDEV ( chr ) ;
chr = qemu_chr_alloc ( driver , backend , errp ) ;
if ( ! chr ) {
return NULL ;
}
s = ( SpiceChardev * ) chr ;
s - > active = false ;
s - > sin . subtype = g_strdup ( subtype ) ;
QLIST_INSERT_HEAD ( & spice_chars , s , next ) ;
return chr ;
}
static Chardev * qemu_chr_open_spice_vmc ( const CharDriver * driver ,
const char * id ,
ChardevBackend * backend ,
ChardevReturn * ret ,
bool * be_opened ,
Error * * errp )
static void qemu_chr_open_spice_vmc ( Chardev * chr ,
ChardevBackend * backend ,
bool * be_opened ,
Error * * errp )
{
ChardevSpiceChannel * spicevmc = backend - > u . spicevmc . data ;
const char * type = spicevmc - > type ;
const char * * psubtype = spice_server_char_device_recognized_subtypes ( ) ;
ChardevCommon * common = qapi_ChardevSpiceChannel_base ( spicevmc ) ;
for ( ; * psubtype ! = NULL ; + + psubtype ) {
if ( strcmp ( type , * psubtype ) = = 0 ) {
@ -294,41 +286,33 @@ static Chardev *qemu_chr_open_spice_vmc(const CharDriver *driver,
subtypes ) ;
g_free ( subtypes ) ;
return NULL ;
return ;
}
* be_opened = false ;
return chr_open ( drive r, type , common , errp ) ;
chr_open ( ch r, type ) ;
}
# if SPICE_SERVER_VERSION >= 0x000c02
static Chardev * qemu_chr_open_spice_port ( const CharDriver * driver ,
const char * id ,
ChardevBackend * backend ,
ChardevReturn * ret ,
bool * be_opened ,
Error * * errp )
static void qemu_chr_open_spice_port ( Chardev * chr ,
ChardevBackend * backend ,
bool * be_opened ,
Error * * errp )
{
ChardevSpicePort * spiceport = backend - > u . spiceport . data ;
const char * name = spiceport - > fqdn ;
ChardevCommon * common = qapi_ChardevSpicePort_base ( spiceport ) ;
Chardev * chr ;
SpiceChardev * s ;
if ( name = = NULL ) {
error_setg ( errp , " missing name parameter " ) ;
return NULL ;
return ;
}
chr = chr_open ( driver , " port " , common , errp ) ;
if ( ! chr ) {
return NULL ;
}
chr_open ( chr , " port " ) ;
* be_opened = false ;
s = ( SpiceChardev * ) chr ;
s = SPICE_CHARDEV ( chr ) ;
s - > sin . portname = g_strdup ( name ) ;
return chr ;
}
void qemu_spice_register_ports ( void )
@ -374,32 +358,68 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
spiceport - > fqdn = g_strdup ( name ) ;
}
static void char_spice_class_init ( ObjectClass * oc , void * data )
{
ChardevClass * cc = CHARDEV_CLASS ( oc ) ;
cc - > chr_write = spice_chr_write ;
cc - > chr_add_watch = spice_chr_add_watch ;
cc - > chr_accept_input = spice_chr_accept_input ;
cc - > chr_free = spice_chr_free ;
}
static const TypeInfo char_spice_type_info = {
. name = TYPE_CHARDEV_SPICE ,
. parent = TYPE_CHARDEV ,
. instance_size = sizeof ( SpiceChardev ) ,
. class_init = char_spice_class_init ,
. abstract = true ,
} ;
static void char_spicevmc_class_init ( ObjectClass * oc , void * data )
{
ChardevClass * cc = CHARDEV_CLASS ( oc ) ;
cc - > open = qemu_chr_open_spice_vmc ;
cc - > chr_set_fe_open = spice_vmc_set_fe_open ;
}
static const TypeInfo char_spicevmc_type_info = {
. name = TYPE_CHARDEV_SPICEVMC ,
. parent = TYPE_CHARDEV_SPICE ,
. class_init = char_spicevmc_class_init ,
} ;
static void char_spiceport_class_init ( ObjectClass * oc , void * data )
{
ChardevClass * cc = CHARDEV_CLASS ( oc ) ;
cc - > open = qemu_chr_open_spice_port ;
cc - > chr_set_fe_open = spice_port_set_fe_open ;
}
static const TypeInfo char_spiceport_type_info = {
. name = TYPE_CHARDEV_SPICEPORT ,
. parent = TYPE_CHARDEV_SPICE ,
. class_init = char_spiceport_class_init ,
} ;
static void register_types ( void )
{
static const CharDriver vmc_driver = {
. instance_size = sizeof ( SpiceChardev ) ,
. kind = CHARDEV_BACKEND_KIND_SPICEVMC ,
. parse = qemu_chr_parse_spice_vmc ,
. create = qemu_chr_open_spice_vmc ,
. chr_write = spice_chr_write ,
. chr_add_watch = spice_chr_add_watch ,
. chr_set_fe_open = spice_vmc_set_fe_open ,
. chr_accept_input = spice_chr_accept_input ,
. chr_free = spice_chr_free ,
} ;
static const CharDriver port_driver = {
. instance_size = sizeof ( SpiceChardev ) ,
. kind = CHARDEV_BACKEND_KIND_SPICEPORT ,
. parse = qemu_chr_parse_spice_port ,
. create = qemu_chr_open_spice_port ,
. chr_write = spice_chr_write ,
. chr_add_watch = spice_chr_add_watch ,
. chr_set_fe_open = spice_port_set_fe_open ,
. chr_accept_input = spice_chr_accept_input ,
. chr_free = spice_chr_free ,
} ;
register_char_driver ( & vmc_driver ) ;
register_char_driver ( & port_driver ) ;
type_register_static ( & char_spice_type_info ) ;
type_register_static ( & char_spicevmc_type_info ) ;
type_register_static ( & char_spiceport_type_info ) ;
}
type_init ( register_types ) ;