On Fri, 2017-08-25 at 10:54 +0100, Frediano Ziglio wrote: > When guest close the device the host device has to be reset too. > This make easier to restart the guest device which can happen in case > of reboot, agent issues or if we want to update the agent. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > server/stream-channel.c | 30 ++++++++++++++++++++++++++++++ > server/stream-channel.h | 7 ++++++- > server/stream-device.c | 49 > +++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/server/stream-channel.c b/server/stream-channel.c > index 6a6536aa..53a06f91 100644 > --- a/server/stream-channel.c > +++ b/server/stream-channel.c > @@ -483,3 +483,33 @@ stream_channel_register_start_cb(StreamChannel > *channel, > channel->start_cb = cb; > channel->start_opaque = opaque; > } > + > +void > +stream_channel_reset(StreamChannel *channel) > +{ > + RedChannel *red_channel = RED_CHANNEL(channel); > + > + // send destroy old stream > + red_channel_pipes_add_type(red_channel, > RED_PIPE_ITEM_TYPE_STREAM_DESTROY); > + > + // destroy display surface > + if (channel->width != 0 && channel->height != 0) { > + red_channel_pipes_add_type(red_channel, > RED_PIPE_ITEM_TYPE_SURFACE_DESTROY); > + } > + > + channel->stream_id = -1; > + channel->width = 0; > + channel->height = 0; > + > + if (!red_channel_is_connected(red_channel)) { > + return; > + } > + > + // try to ask new stream, this should start a new stream "ask" -> "request a" > + // if the guest connect to the device and a client is already "if the guest is connected" > connected > + StreamMsgStartStop* start = > stream_channel_get_supported_codecs(channel); > + // send in any case, even if list is not changed > + // notify device about changes > + request_new_stream(channel, start); > + free(start); > +} > diff --git a/server/stream-channel.h b/server/stream-channel.h > index ba098df4..bd075a95 100644 > --- a/server/stream-channel.h > +++ b/server/stream-channel.h > @@ -48,7 +48,12 @@ GType stream_channel_get_type(void) G_GNUC_CONST; > */ > StreamChannel* stream_channel_new(RedsState *server, uint32_t id); > > -struct StreamMsgFormat; > +/** > + * Reset channel at initial state > + */ > +void stream_channel_reset(StreamChannel *channel); > + > +struct StreamMsgStreamFormat; > struct StreamMsgStartStop; > > void stream_channel_change_format(StreamChannel *channel, > diff --git a/server/stream-device.c b/server/stream-device.c > index 8ab762a3..8909c9ba 100644 > --- a/server/stream-device.c > +++ b/server/stream-device.c > @@ -43,6 +43,7 @@ struct StreamDevice { > StreamDevHeader hdr; > uint8_t hdr_pos; > bool has_error; > + bool opened; > StreamChannel *stream_channel; > }; > > @@ -188,6 +189,35 @@ stream_device_remove_client(RedCharDevice *self, > RedClient *client) > { > } > > +static void > +stream_device_stream_start(void *opaque, StreamMsgStartStop *start, > + StreamChannel *stream_channel > G_GNUC_UNUSED) > +{ > + StreamDevice *dev = (StreamDevice *) opaque; > + > + if (!dev->opened) { > + return; > + } > + > + int msg_size = sizeof(*start) + sizeof(start->codecs[0]) * > start->num_codecs; > + int total_size = sizeof(StreamDevHeader) + msg_size; > + > + RedCharDevice *char_dev = RED_CHAR_DEVICE(dev); > + RedCharDeviceWriteBuffer *buf = > + red_char_device_write_buffer_get_server_no_token(char_dev, > total_size); > + buf->buf_used = total_size; > + > + StreamDevHeader *hdr = (StreamDevHeader *)buf->buf; > + hdr->protocol_version = STREAM_DEVICE_PROTOCOL; > + hdr->padding = 0; > + hdr->type = GUINT16_TO_LE(STREAM_TYPE_START_STOP); > + hdr->size = GUINT32_TO_LE(msg_size); > + > + memcpy(&hdr[1], start, msg_size); > + > + red_char_device_write_buffer_add(char_dev, buf); > +} > + > RedCharDevice * > stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin) > { > @@ -197,6 +227,7 @@ stream_device_connect(RedsState *reds, > SpiceCharDeviceInstance *sin) > > StreamDevice *dev = stream_device_new(sin, reds); > dev->stream_channel = stream_channel; > + stream_channel_register_start_cb(stream_channel, > stream_device_stream_start, dev); > > sif = spice_char_device_get_interface(sin); > if (sif->state) { > @@ -219,6 +250,23 @@ stream_device_dispose(GObject *object) > } > > static void > +stream_device_port_event(RedCharDevice *char_dev, uint8_t event) > +{ > + if (event != SPICE_PORT_EVENT_OPENED && event != > SPICE_PORT_EVENT_CLOSED) { > + return; > + } > + > + StreamDevice *device = STREAM_DEVICE(char_dev); > + > + // reset device and channel on close/open > + device->opened = (event == SPICE_PORT_EVENT_OPENED); > + device->hdr_pos = 0; > + device->has_error = false; > + red_char_device_reset(char_dev); > + stream_channel_reset(device->stream_channel); > +} > + > +static void > stream_device_class_init(StreamDeviceClass *klass) > { > GObjectClass *object_class = G_OBJECT_CLASS(klass); > @@ -230,6 +278,7 @@ stream_device_class_init(StreamDeviceClass > *klass) > char_dev_class->send_msg_to_client = > stream_device_send_msg_to_client; > char_dev_class->send_tokens_to_client = > stream_device_send_tokens_to_client; > char_dev_class->remove_client = stream_device_remove_client; > + char_dev_class->port_event = stream_device_port_event; > } > > static void Acked-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel