[Spice-devel] [usbredir PATCH v5 1/2] usbredirhost: new callback for iso streams
Victor Toso
victortoso at redhat.com
Thu Oct 22 07:15:13 PDT 2015
Hi,
there is a leftover (mentioned bellow). Fixed locally.
On Thu, Oct 22, 2015 at 04:07:18PM +0200, Victor Toso wrote:
> For streaming devices it might be necessary from application to drop
> data for different reasons. This patch provides a new callback that it
> is called before queueing the most recent iso packages.
>
> Related: https://bugzilla.redhat.com/show_bug.cgi?id=1264156
> ---
> usbredirhost/usbredirhost.c | 63 +++++++++++++++++++++++++++++++++++++++++++--
> usbredirhost/usbredirhost.h | 12 +++++++++
> 2 files changed, 73 insertions(+), 2 deletions(-)
>
> diff --git a/usbredirhost/usbredirhost.c b/usbredirhost/usbredirhost.c
> index ad30722..4c20bff 100644
> --- a/usbredirhost/usbredirhost.c
> +++ b/usbredirhost/usbredirhost.c
> @@ -23,6 +23,7 @@
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdarg.h>
> +#include <stdbool.h>
> #include <string.h>
> #include <errno.h>
> #include <unistd.h>
> @@ -109,6 +110,7 @@ struct usbredirhost {
> usbredirparser_read read_func;
> usbredirparser_write write_func;
> usbredirhost_flush_writes flush_writes_func;
> + usbredirhost_can_write_iso can_write_iso_func;
> void *func_priv;
> int verbose;
> libusb_context *ctx;
> @@ -130,6 +132,11 @@ struct usbredirhost {
> struct usbredirtransfer transfers_head;
> struct usbredirfilter_rule *filter_rules;
> int filter_rules_count;
> + struct {
> + uint64_t higher;
> + uint64_t lower;
> + bool dropping;
> + } iso_threshold;
> };
>
> struct usbredirhost_dev_ids {
> @@ -1003,6 +1010,31 @@ static void usbredirhost_send_stream_status(struct usbredirhost *host,
> }
> }
>
> +static int usbredirhost_can_write_iso_package(struct usbredirhost *host,
> + uint8_t ep)
ep is not used. removed.
> +{
> + uint64_t size;
> +
> + if (!host->can_write_iso_func)
> + return true;
> +
> + size = host->can_write_iso_func(host->func_priv);
> + if (size >= host->iso_threshold.higher) {
> + if (!host->iso_threshold.dropping)
> + DEBUG("START dropping isoc packets %lu buffer > %lu hi threshold",
> + size, host->iso_threshold.higher);
> + host->iso_threshold.dropping = true;
> + } else if (size < host->iso_threshold.lower) {
> + if (host->iso_threshold.dropping)
> + DEBUG("STOP dropping isoc packets %lu buffer < %lu low threshold",
> + size, host->iso_threshold.lower);
> +
> + host->iso_threshold.dropping = false;
> + }
> +
> + return !host->iso_threshold.dropping;
> +}
> +
> static void usbredirhost_send_stream_data(struct usbredirhost *host,
> uint64_t id, uint8_t ep, uint8_t status, uint8_t *data, int len)
> {
> @@ -1028,8 +1060,10 @@ static void usbredirhost_send_stream_data(struct usbredirhost *host,
> .status = status,
> .length = len,
> };
> - usbredirparser_send_iso_packet(host->parser, id, &iso_packet,
> - data, len);
> +
> + if (usbredirhost_can_write_iso_package(host, ep))
> + usbredirparser_send_iso_packet(host->parser, id, &iso_packet,
> + data, len);
> break;
> }
> case usb_redir_type_bulk: {
> @@ -1120,6 +1154,16 @@ static void usbredirhost_stop_stream(struct usbredirhost *host,
> FLUSH(host);
> }
>
> +static void usbredirhost_set_iso_threshold(struct usbredirhost *host,
> + uint8_t pkts_per_transfer, uint8_t transfer_count, uint16_t max_packetsize)
> +{
> + uint64_t reference = pkts_per_transfer * transfer_count * max_packetsize;
> + host->iso_threshold.lower = reference / 2;
> + host->iso_threshold.higher = reference * 2;
> + DEBUG("higher threshold is %lu bytes | lower threshold is %lu bytes",
> + host->iso_threshold.higher, host->iso_threshold.lower);
> +}
> +
> /* Called from both parser read and packet complete callbacks */
> static void usbredirhost_alloc_stream_unlocked(struct usbredirhost *host,
> uint64_t id, uint8_t ep, uint8_t type, uint8_t pkts_per_transfer,
> @@ -1178,6 +1222,10 @@ static void usbredirhost_alloc_stream_unlocked(struct usbredirhost *host,
> host->endpoint[EP2I(ep)].transfer[i], ISO_TIMEOUT);
> libusb_set_iso_packet_lengths(
> host->endpoint[EP2I(ep)].transfer[i]->transfer, pkt_size);
> +
> + usbredirhost_set_iso_threshold(
> + host, pkts_per_transfer, transfer_count,
> + host->endpoint[EP2I(ep)].max_packetsize);
> break;
> case usb_redir_type_bulk:
> libusb_fill_bulk_transfer(
> @@ -1358,6 +1406,17 @@ static void usbredirhost_log_data(struct usbredirhost *host, const char *desc,
>
> /**************************************************************************/
>
> +void usbredirhost_set_cb_can_write_iso(struct usbredirhost *host,
> + usbredirhost_can_write_iso can_write_iso_func)
> +{
> + if (!host) {
> + ERROR("invalid usbredirhost");
> + return;
> + }
> +
> + host->can_write_iso_func = can_write_iso_func;
> +}
> +
> /* Return value:
> 0 All ok
> 1 Packet borked, continue with next packet / urb
> diff --git a/usbredirhost/usbredirhost.h b/usbredirhost/usbredirhost.h
> index c0042c9..a03b10b 100644
> --- a/usbredirhost/usbredirhost.h
> +++ b/usbredirhost/usbredirhost.h
> @@ -33,6 +33,8 @@ struct usbredirhost;
>
> typedef void (*usbredirhost_flush_writes)(void *priv);
>
> +typedef uint64_t (*usbredirhost_can_write_iso)(void *priv);
> +
> /* This function creates an usbredirhost instance, including its embedded
> libusbredirparser instance and sends the initial usb_redir_hello packet to
> the usb-guest.
> @@ -114,6 +116,16 @@ void usbredirhost_close(struct usbredirhost *host);
> int usbredirhost_set_device(struct usbredirhost *host,
> libusb_device_handle *usb_dev_handle);
>
> +/* Call this function to set a callback in usbredirhost.
> + The usbredirhost_can_write_iso callback should return the application's
> + buffer size (in bytes) that are handling the isochronous data.
> + usbredirhost set two levels of threshold based in the information provided
> + by the device; if buffer size is higher then the higher threshold, usbredir
> + will drop isochronous packages till it reaches lower threshold.
> +*/
> +void usbredirhost_set_cb_can_write_iso(struct usbredirhost *host,
> + usbredirhost_can_write_iso can_write_iso_func);
> +
> /* Call this whenever there is data ready for the usbredirhost to read from
> the usb-guest
> returns 0 on success, or an error code from the below enum on error.
> --
> 2.5.0
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list