diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-02-10 12:29:46 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-02-10 13:51:17 +0100 |
commit | 1795a4b53f401aebc952edeaf63759678fd6c313 (patch) | |
tree | ca18da78772995ff7d56858486b8fe76c18bd409 | |
parent | 440adcb58724c652dcd91a1ed1a3da7d798ee3fd (diff) |
Add an usb_redir_device_reject packet
Add an usb_redir_device_reject packet to allow notifying the usb-host when
an usb-guest rejects a device because of usb-guest side device filtering.
Also bump the version to 0.3.4 so that apps can check if libusbredirparser /
libusbredirhost knows about usb_redir_device_reject by checking the version
number.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | usb-redirection-protocol.txt | 32 | ||||
-rw-r--r-- | usbredirhost/usbredirhost.c | 17 | ||||
-rw-r--r-- | usbredirhost/usbredirhost.h | 17 | ||||
-rw-r--r-- | usbredirparser/usbredirparser.c | 31 | ||||
-rw-r--r-- | usbredirparser/usbredirparser.h | 18 | ||||
-rw-r--r-- | usbredirparser/usbredirproto.h | 4 |
7 files changed, 107 insertions, 14 deletions
diff --git a/configure.ac b/configure.ac index 9655966..5ab298c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.63) -AC_INIT([usbredir], [0.3.3]) +AC_INIT([usbredir], [0.3.4]) AC_CONFIG_SRCDIR([configure.ac]) AM_CONFIG_HEADER([config.h]) diff --git a/usb-redirection-protocol.txt b/usb-redirection-protocol.txt index 7d1bd86..e7b54d2 100644 --- a/usb-redirection-protocol.txt +++ b/usb-redirection-protocol.txt @@ -42,11 +42,17 @@ Version 0.3, released 14 July 2011 -Drop usb_redir_reset_status, instead if reconnecting to the device fails after reset the usb-host will send a usb_redir_device_disconnect packet -Version 0.3.2, released 24 December 2011 +Version 0.3.2, released 3 January 2012 -The usb_redir_device_connect_header has been extended with a device_version_bcd field. This is only send / received if both sides have the usb_redir_cap_connect_device_version capability +Version 0.3.3, released 12 January 2012 +- No protocol changes + +Version 0.3.4, released FIXME 2012 +- Add an usb_redir_device_reject packet to allow notifying the usb-host when + an usb-guest rejects a device because of usb-guest side device filtering USB redirerection protocol version 0.3 -------------------------------------- @@ -140,6 +146,7 @@ usb_redir_alloc_bulk_streams usb_redir_free_bulk_streams usb_redir_bulk_streams_status usb_redir_cancel_data_packet +usb_redir_device_reject data packets: usb_redir_control_packet @@ -195,7 +202,12 @@ etc. the value is 64 + capabilities-array-size * sizeof(uint32_t). Currently the following capabilities are defined: enum { - usb_redir_cap_bulk_streams, /* USB 3 bulk streams are supported */ + /* USB 3 bulk streams are supported ? */ + usb_redir_cap_bulk_streams, + /* The device_connect packet has the device_version_bcd field ? */ + usb_redir_cap_connect_device_version, + /* Knows how to handle the usb_redir_device_reject packet ? */ + usb_redir_cap_reject_device, }; usb_redir_device_connect @@ -251,6 +263,22 @@ This packet may be send by the usb-host to indicate that the device has been disconnect (unplugged). Note on some platforms the usb-host may not become aware of the disconnection until a usb packet is send to the device. +usb_redir_device_reject +----------------------- + +usb_redir_header.type: usb_redir_device_reject +usb_redir_header.length: 0 +usb_redir_header.id: 0 (always as this is an unsolicited packet) + +No packet type specific header. + +No packet type specific additional data. + +This packet may be send by the usb-guest to indicate to the usb-host that the +device has been rejected. Usually the usb-guest will send this after receiving +a usb_redir_device_connect or usb_redir_interface_info packet which fails +to match an usb-guest side device filter. + usb_redir_reset --------------- diff --git a/usbredirhost/usbredirhost.c b/usbredirhost/usbredirhost.c index 39c115f..00682fd 100644 --- a/usbredirhost/usbredirhost.c +++ b/usbredirhost/usbredirhost.c @@ -111,6 +111,7 @@ struct usbredirhost { int active_config; int claimed; int disconnected; + int rejected; struct usbredirhost_ep endpoint[MAX_ENDPOINTS]; uint8_t driver_detached[MAX_INTERFACES]; uint8_t alt_setting[MAX_INTERFACES]; @@ -145,6 +146,7 @@ static void va_log(struct usbredirhost *host, int level, "usbredirhost: " __VA_ARGS__) static void usbredirhost_hello(void *priv, struct usb_redir_hello_header *h); +static void usbredirhost_device_reject(void *priv); static void usbredirhost_reset(void *priv); static void usbredirhost_set_configuration(void *priv, uint32_t id, struct usb_redir_set_configuration_header *set_configuration); @@ -198,6 +200,11 @@ static int usbredirhost_read(void *priv, uint8_t *data, int count) { struct usbredirhost *host = priv; + if (host->rejected) { + host->rejected = 0; + return usbredirhost_read_device_rejected; + } + return host->read_func(host->func_priv, data, count); } @@ -508,6 +515,7 @@ struct usbredirhost *usbredirhost_open_full( host->parser->read_func = usbredirhost_read; host->parser->write_func = usbredirhost_write; host->parser->hello_func = usbredirhost_hello; + host->parser->device_reject_func = usbredirhost_device_reject; host->parser->reset_func = usbredirhost_reset; host->parser->set_configuration_func = usbredirhost_set_configuration; host->parser->get_configuration_func = usbredirhost_get_configuration; @@ -541,6 +549,7 @@ struct usbredirhost *usbredirhost_open_full( } usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); + usbredirparser_caps_set_cap(caps, usb_redir_cap_reject_device); usbredirparser_init(host->parser, version, caps, USB_REDIR_CAPS_SIZE, parser_flags); @@ -1297,6 +1306,14 @@ static void usbredirhost_hello(void *priv, struct usb_redir_hello_header *h) FLUSH(host); } +static void usbredirhost_device_reject(void *priv) +{ + struct usbredirhost *host = priv; + + INFO("device rejected"); + host->rejected = 1; +} + static void usbredirhost_reset(void *priv) { struct usbredirhost *host = priv; diff --git a/usbredirhost/usbredirhost.h b/usbredirhost/usbredirhost.h index f82d44f..9e32ab2 100644 --- a/usbredirhost/usbredirhost.h +++ b/usbredirhost/usbredirhost.h @@ -94,11 +94,17 @@ void usbredirhost_close(struct usbredirhost *host); /* Call this whenever there is data ready for the usbredirhost to read from the usb-guest - returns 0 on success, -1 if a read error happened, -2 if a parse error - happened. If a read error happened this function will continue where it - left of the last time on the next call. If a parse error happened it will - skip to the next packet (*) on the next call. + returns 0 on success, or an error code from the below enum on error. + On an usbredirhost_read_io_error this function will continue where it + left of the last time on the next call. On an usbredirhost_read_parse_error + it will skip to the next packet (*). On an usbredirhost_read_device_rejected + error, you are expected to call usbredirhost_close(). *) As determined by the faulty's package headers length field */ +enum { + usbredirhost_read_io_error = -1, + usbredirhost_read_parse_error = -2, + usbredirhost_read_device_rejected = -3, +}; int usbredirhost_read_guest_data(struct usbredirhost *host); /* If this returns true there is data queued to write to the usb-guest */ @@ -108,6 +114,9 @@ int usbredirhost_has_data_to_write(struct usbredirhost *host); returns 0 on success, -1 if a write error happened. If a write error happened, this function will retry writing any queued data on the next call, and will continue doing so until it has succeeded! */ +enum { + usbredirhost_write_io_error = -1, +}; int usbredirhost_write_guest_data(struct usbredirhost *host); /* When passing the usbredirhost_fl_write_cb_owns_buffer flag to diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c index 1061393..159603e 100644 --- a/usbredirparser/usbredirparser.c +++ b/usbredirparser/usbredirparser.c @@ -232,6 +232,12 @@ static int usbredirparser_get_type_header_len( } else { return -1; } + case usb_redir_device_reject: + if (command_for_host) { + return 0; + } else { + return -1; + } case usb_redir_reset: if (command_for_host) { return 0; /* No packet type specific header */ @@ -377,9 +383,11 @@ static int usbredirparser_expect_extra_data(struct usbredirparser_priv *parser) } static int usbredirparser_verify_type_header( - struct usbredirparser_priv *parser, + struct usbredirparser *parser_pub, int32_t type, void *header, uint8_t *data, int data_len, int send) { + struct usbredirparser_priv *parser = + (struct usbredirparser_priv *)parser_pub; int command_for_host = 0, expect_extra_data = 0; int length = 0, ep = -1; @@ -400,6 +408,15 @@ static int usbredirparser_verify_type_header( } break; } + case usb_redir_device_reject: + if ((send && !usbredirparser_peer_has_cap(parser_pub, + usb_redir_cap_reject_device)) || + (!send && !usbredirparser_have_cap(parser_pub, + usb_redir_cap_reject_device))) { + ERROR("device_reject without cap_reject_device"); + return 0; + } + break; case usb_redir_control_packet: length = ((struct usb_redir_control_packet_header *)header)->length; ep = ((struct usb_redir_control_packet_header *)header)->endpoint; @@ -466,6 +483,9 @@ static void usbredirparser_call_type_func(struct usbredirparser_priv *parser) case usb_redir_device_disconnect: parser->callb.device_disconnect_func(parser->callb.priv); break; + case usb_redir_device_reject: + parser->callb.device_reject_func(parser->callb.priv); + break; case usb_redir_reset: parser->callb.reset_func(parser->callb.priv); break; @@ -663,7 +683,7 @@ int usbredirparser_do_read(struct usbredirparser *parser_pub) } else if (parser->type_header_read < parser->type_header_len) { parser->type_header_read += r; if (parser->type_header_read == parser->type_header_len) { - if (!usbredirparser_verify_type_header(parser, + if (!usbredirparser_verify_type_header(parser_pub, parser->header.type, parser->type_header, parser->data, parser->data_len, 0)) { parser->to_skip = parser->data_len; @@ -759,7 +779,7 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub, return; } - if (!usbredirparser_verify_type_header(parser, type, type_header_in, + if (!usbredirparser_verify_type_header(parser_pub, type, type_header_in, data_in, data_len, 1)) { ERROR("usbredirparser_send_* call invalid params, please report!!"); return; @@ -813,6 +833,11 @@ void usbredirparser_send_device_disconnect(struct usbredirparser *parser) NULL, 0); } +void usbredirparser_send_device_reject(struct usbredirparser *parser) +{ + usbredirparser_queue(parser, usb_redir_device_reject, 0, NULL, NULL, 0); +} + void usbredirparser_send_reset(struct usbredirparser *parser) { usbredirparser_queue(parser, usb_redir_reset, 0, NULL, NULL, 0); diff --git a/usbredirparser/usbredirparser.h b/usbredirparser/usbredirparser.h index 287890a..adf7919 100644 --- a/usbredirparser/usbredirparser.h +++ b/usbredirparser/usbredirparser.h @@ -64,6 +64,7 @@ typedef void (*usbredirparser_hello)(void *priv, typedef void (*usbredirparser_device_connect)(void *priv, struct usb_redir_device_connect_header *device_connect); typedef void (*usbredirparser_device_disconnect)(void *priv); +typedef void (*usbredirparser_device_reject)(void *priv); typedef void (*usbredirparser_reset)(void *priv); typedef void (*usbredirparser_interface_info)(void *priv, struct usb_redir_interface_info_header *interface_info); @@ -165,6 +166,8 @@ struct usbredirparser { usbredirparser_free_lock free_lock_func; /* usbredir 0.3.2 new control packet complete callbacks */ usbredirparser_hello hello_func; + /* usbredir 0.3.4 new control packet complete callbacks */ + usbredirparser_device_reject device_reject_func; }; /* Allocate a usbredirparser, after this the app should set the callback app @@ -198,11 +201,14 @@ int usbredirparser_have_cap(struct usbredirparser *parser, int cap); int usbredirparser_peer_has_cap(struct usbredirparser *parser, int cap); /* Call this whenever there is data ready from the otherside to parse - returns 0 on success, -1 if a read error happened, -2 if a parse error - happened. If a read error happened this function will continue where it - left of the last time on the next call. If a parse error happened it will - skip to the next packet (*) on the next call. + On an usbredirparser_read_io_error this function will continue where it + left of the last time on the next call. On an + usbredirparser_read_parse_error it will skip to the next packet (*). *) As determined by the faulty's package headers length field */ +enum { + usbredirparser_read_io_error = -1, + usbredirparser_read_parse_error = -2, +}; int usbredirparser_do_read(struct usbredirparser *parser); /* If this returns true the parser has data queued to write to its peer */ @@ -212,6 +218,9 @@ int usbredirparser_has_data_to_write(struct usbredirparser *parser); returns 0 on success, -1 if a write error happened. If a write error happened, this function will retry writing any queued data on the next call, and will continue doing so until it has succeeded! */ +enum { + usbredirparser_write_io_error = -1, +}; int usbredirparser_do_write(struct usbredirparser *parser); /* See usbredirparser_write documentation */ @@ -236,6 +245,7 @@ uint32_t *usbredirparser_get_peer_caps(int *caps_len_ret); void usbredirparser_send_device_connect(struct usbredirparser *parser, struct usb_redir_device_connect_header *device_connect); void usbredirparser_send_device_disconnect(struct usbredirparser *parser); +void usbredirparser_send_device_reject(struct usbredirparser *parser); void usbredirparser_send_reset(struct usbredirparser *parser); void usbredirparser_send_interface_info(struct usbredirparser *parser, struct usb_redir_interface_info_header *interface_info); diff --git a/usbredirparser/usbredirproto.h b/usbredirparser/usbredirproto.h index e8ae212..83d7932 100644 --- a/usbredirparser/usbredirproto.h +++ b/usbredirparser/usbredirproto.h @@ -92,6 +92,8 @@ enum { usb_redir_free_bulk_streams, usb_redir_bulk_streams_status, usb_redir_cancel_data_packet, + usb_redir_device_reject, + /* Data packets */ usb_redir_control_packet = 100, usb_redir_bulk_packet, @@ -104,6 +106,8 @@ enum { usb_redir_cap_bulk_streams, /* The device_connect packet has the device_version_bcd field ? */ usb_redir_cap_connect_device_version, + /* Knows how to handle the usb_redir_device_reject packet ? */ + usb_redir_cap_reject_device, }; /* Number of uint32_t-s needed to hold all (known) capabilities */ #define USB_REDIR_CAPS_SIZE 1 |