summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-02-10 12:29:46 +0100
committerHans de Goede <hdegoede@redhat.com>2012-02-10 13:51:17 +0100
commit1795a4b53f401aebc952edeaf63759678fd6c313 (patch)
treeca18da78772995ff7d56858486b8fe76c18bd409
parent440adcb58724c652dcd91a1ed1a3da7d798ee3fd (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.ac2
-rw-r--r--usb-redirection-protocol.txt32
-rw-r--r--usbredirhost/usbredirhost.c17
-rw-r--r--usbredirhost/usbredirhost.h17
-rw-r--r--usbredirparser/usbredirparser.c31
-rw-r--r--usbredirparser/usbredirparser.h18
-rw-r--r--usbredirparser/usbredirproto.h4
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