From owner-svn-src-all@FreeBSD.ORG Sat Dec 3 13:54:55 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3A7B8106564A; Sat, 3 Dec 2011 13:54:55 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 28D428FC08; Sat, 3 Dec 2011 13:54:55 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pB3Dst6d041954; Sat, 3 Dec 2011 13:54:55 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pB3Dssua041947; Sat, 3 Dec 2011 13:54:54 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201112031354.pB3Dssua041947@svn.freebsd.org> From: Hans Petter Selasky Date: Sat, 3 Dec 2011 13:54:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r228223 - stable/8/lib/libusb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Dec 2011 13:54:55 -0000 Author: hselasky Date: Sat Dec 3 13:54:54 2011 New Revision: 228223 URL: http://svn.freebsd.org/changeset/base/228223 Log: MFC r227404: Add USB 3.0 descriptor support. Modified: stable/8/lib/libusb/Makefile stable/8/lib/libusb/libusb.3 stable/8/lib/libusb/libusb.h stable/8/lib/libusb/libusb10_desc.c stable/8/lib/libusb/libusb20_desc.c stable/8/lib/libusb/libusb20_desc.h Directory Properties: stable/8/lib/libusb/ (props changed) stable/8/lib/libusb/usb.h (props changed) Modified: stable/8/lib/libusb/Makefile ============================================================================== --- stable/8/lib/libusb/Makefile Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/Makefile Sat Dec 3 13:54:54 2011 (r228223) @@ -72,6 +72,10 @@ MLINKS += libusb.3 libusb_get_config_des MLINKS += libusb.3 libusb_get_config_descriptor_by_value.3 MLINKS += libusb.3 libusb_free_config_descriptor.3 MLINKS += libusb.3 libusb_get_string_descriptor_ascii.3 +MLINKS += libusb.3 libusb_parse_ss_endpoint_comp.3 +MLINKS += libusb.3 libusb_free_ss_endpoint_comp.3 +MLINKS += libusb.3 libusb_parse_bos_descriptor.3 +MLINKS += libusb.3 libusb_free_bos_descriptor.3 MLINKS += libusb.3 libusb_alloc_transfer.3 MLINKS += libusb.3 libusb_free_transfer.3 MLINKS += libusb.3 libusb_submit_transfer.3 Modified: stable/8/lib/libusb/libusb.3 ============================================================================== --- stable/8/lib/libusb/libusb.3 Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/libusb.3 Sat Dec 3 13:54:54 2011 (r228223) @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 16, 2011 +.Dd November 9, 2011 .Dt LIBUSB 3 .Os .Sh NAME @@ -316,6 +316,40 @@ Retrieve a string descriptor in C style Returns the positive number of bytes in the resulting ASCII string on success and a LIBUSB_ERROR code on failure. .Pp +.Ft int +.Fn libusb_parse_ss_endpoint_comp "const void *buf" "int len" "libusb_ss_endpoint_companion_descriptor **ep_comp" +This function parses the USB 3.0 endpoint companion descriptor in host endian format pointed to by +.Fa buf +and having a length of +.Fa len. +Typically these arguments are the extra and extra_length fields of the +endpoint descriptor. +On success the pointer to resulting descriptor is stored at the location given by +.Fa ep_comp. +Returns zero on success and a LIBUSB_ERROR code on failure. +On success the parsed USB 3.0 endpoint companion descriptor must be +freed using the libusb_free_ss_endpoint_comp function. +.Pp +.Ft void +.Fn libusb_free_ss_endpoint_comp "libusb_ss_endpoint_companion_descriptor *ep_comp" +This function is NULL safe and frees a parsed USB 3.0 endpoint companion descriptor. +.Pp +.Ft int +.Fn libusb_parse_bos_descriptor "const void *buf" "int len" "libusb_bos_descriptor **bos" +This function parses a Binary Object Store, BOS, descriptor into host endian format pointed to by +.Fa buf +and having a length of +.Fa len. +On success the pointer to resulting descriptor is stored at the location given by +.Fa bos. +Returns zero on success and a LIBUSB_ERROR code on failure. +On success the parsed BOS descriptor must be freed using the +libusb_free_bos_descriptor function. +.Pp +.Ft void +.Fn libusb_free_bos_descriptor "libusb_bos_descriptor *bos" +This function is NULL safe and frees a parsed BOS descriptor. +.Pp .Sh USB ASYNCHRONOUS I/O .Pp .Ft struct libusb_transfer * Modified: stable/8/lib/libusb/libusb.h ============================================================================== --- stable/8/lib/libusb/libusb.h Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/libusb.h Sat Dec 3 13:54:54 2011 (r228223) @@ -63,6 +63,16 @@ enum libusb_descriptor_type { LIBUSB_DT_REPORT = 0x22, LIBUSB_DT_PHYSICAL = 0x23, LIBUSB_DT_HUB = 0x29, + LIBUSB_DT_BOS = 0x0f, + LIBUSB_DT_DEVICE_CAPABILITY = 0x10, + LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30, +}; + +enum libusb_device_capability_type { + LIBUSB_WIRELESS_USB_DEVICE_CAPABILITY = 0x1, + LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY = 0x2, + LIBUSB_SS_USB_DEVICE_CAPABILITY = 0x3, + LIBUSB_CONTAINER_ID_DEVICE_CAPABILITY = 0x4, }; #define LIBUSB_DT_DEVICE_SIZE 18 @@ -71,6 +81,10 @@ enum libusb_descriptor_type { #define LIBUSB_DT_ENDPOINT_SIZE 7 #define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 #define LIBUSB_DT_HUB_NONVAR_SIZE 7 +#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 +#define LIBUSB_DT_BOS_SIZE 5 +#define LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE 7 +#define LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE 10 #define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f #define LIBUSB_ENDPOINT_DIR_MASK 0x80 @@ -230,6 +244,14 @@ typedef struct libusb_endpoint_descripto int extra_length; } libusb_endpoint_descriptor __aligned(sizeof(void *)); +typedef struct libusb_ss_endpoint_companion_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bMaxBurst; + uint8_t bmAttributes; + uint16_t wBytesPerInterval; +} libusb_ss_endpoint_companion_descriptor __aligned(sizeof(void *)); + typedef struct libusb_interface_descriptor { uint8_t bLength; uint8_t bDescriptorType; @@ -264,6 +286,39 @@ typedef struct libusb_config_descriptor int extra_length; } libusb_config_descriptor __aligned(sizeof(void *)); +typedef struct libusb_usb_2_0_device_capability_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint32_t bmAttributes; +#define LIBUSB_USB_2_0_CAPABILITY_LPM_SUPPORT (1 << 1) +} libusb_usb_2_0_device_capability_descriptor __aligned(sizeof(void *)); + +typedef struct libusb_ss_usb_device_capability_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bmAttributes; +#define LIBUSB_SS_USB_CAPABILITY_LPM_SUPPORT (1 << 1) + uint16_t wSpeedSupported; +#define LIBUSB_CAPABILITY_LOW_SPEED_OPERATION (1) +#define LIBUSB_CAPABILITY_FULL_SPEED_OPERATION (1 << 1) +#define LIBUSB_CAPABILITY_HIGH_SPEED_OPERATION (1 << 2) +#define LIBUSB_CAPABILITY_5GBPS_OPERATION (1 << 3) + uint8_t bFunctionalitySupport; + uint8_t bU1DevExitLat; + uint16_t wU2DevExitLat; +} libusb_ss_usb_device_capability_descriptor __aligned(sizeof(void *)); + +typedef struct libusb_bos_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCapabilities; + struct libusb_usb_2_0_device_capability_descriptor *usb_2_0_ext_cap; + struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap; +} libusb_bos_descriptor __aligned(sizeof(void *)); + typedef struct libusb_control_setup { uint8_t bmRequestType; uint8_t bRequest; @@ -345,6 +400,10 @@ int libusb_get_config_descriptor_by_valu void libusb_free_config_descriptor(struct libusb_config_descriptor *config); int libusb_get_string_descriptor_ascii(libusb_device_handle * devh, uint8_t desc_index, uint8_t *data, int length); int libusb_get_descriptor(libusb_device_handle * devh, uint8_t desc_type, uint8_t desc_index, uint8_t *data, int length); +int libusb_parse_ss_endpoint_comp(const void *buf, int len, struct libusb_ss_endpoint_companion_descriptor **ep_comp); +void libusb_free_ss_endpoint_comp(struct libusb_ss_endpoint_companion_descriptor *ep_comp); +int libusb_parse_bos_descriptor(const void *buf, int len, struct libusb_bos_descriptor **bos); +void libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); /* Asynchronous device I/O */ Modified: stable/8/lib/libusb/libusb10_desc.c ============================================================================== --- stable/8/lib/libusb/libusb10_desc.c Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/libusb10_desc.c Sat Dec 3 13:54:54 2011 (r228223) @@ -298,7 +298,7 @@ libusb_get_string_descriptor_ascii(libus uint8_t desc_index, unsigned char *data, int length) { if (pdev == NULL || data == NULL || length < 1) - return (LIBUSB20_ERROR_INVALID_PARAM); + return (LIBUSB_ERROR_INVALID_PARAM); if (length > 65535) length = 65535; @@ -318,7 +318,7 @@ libusb_get_descriptor(libusb_device_hand uint8_t desc_index, uint8_t *data, int length) { if (devh == NULL || data == NULL || length < 1) - return (LIBUSB20_ERROR_INVALID_PARAM); + return (LIBUSB_ERROR_INVALID_PARAM); if (length > 65535) length = 65535; @@ -327,3 +327,172 @@ libusb_get_descriptor(libusb_device_hand LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, length, 1000)); } + +int +libusb_parse_ss_endpoint_comp(const void *buf, int len, + struct libusb_ss_endpoint_companion_descriptor **ep_comp) +{ + if (buf == NULL || ep_comp == NULL || len < 1) + return (LIBUSB_ERROR_INVALID_PARAM); + + if (len > 65535) + len = 65535; + + *ep_comp = NULL; + + while (len != 0) { + uint8_t dlen; + uint8_t dtype; + + dlen = ((const uint8_t *)buf)[0]; + dtype = ((const uint8_t *)buf)[1]; + + if (dlen < 2 || dlen > len) + break; + + if (dlen >= LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE && + dtype == LIBUSB_DT_SS_ENDPOINT_COMPANION) { + struct libusb_ss_endpoint_companion_descriptor *ptr; + + ptr = malloc(sizeof(*ptr)); + if (ptr == NULL) + return (LIBUSB_ERROR_NO_MEM); + + ptr->bLength = LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE; + ptr->bDescriptorType = dtype; + ptr->bMaxBurst = ((const uint8_t *)buf)[2]; + ptr->bmAttributes = ((const uint8_t *)buf)[3]; + ptr->wBytesPerInterval = ((const uint8_t *)buf)[4] | + (((const uint8_t *)buf)[5] << 8); + + *ep_comp = ptr; + + return (0); /* success */ + } + + buf = ((const uint8_t *)buf) + dlen; + len -= dlen; + } + return (LIBUSB_ERROR_IO); +} + +void +libusb_free_ss_endpoint_comp(struct libusb_ss_endpoint_companion_descriptor *ep_comp) +{ + if (ep_comp == NULL) + return; + + free(ep_comp); +} + +int +libusb_parse_bos_descriptor(const void *buf, int len, + struct libusb_bos_descriptor **bos) +{ + struct libusb_bos_descriptor *ptr; + struct libusb_usb_2_0_device_capability_descriptor *dcap_20; + struct libusb_ss_usb_device_capability_descriptor *ss_cap; + + if (buf == NULL || bos == NULL || len < 1) + return (LIBUSB_ERROR_INVALID_PARAM); + + if (len > 65535) + len = 65535; + + *bos = ptr = NULL; + + while (len != 0) { + uint8_t dlen; + uint8_t dtype; + + dlen = ((const uint8_t *)buf)[0]; + dtype = ((const uint8_t *)buf)[1]; + + if (dlen < 2 || dlen > len) + break; + + if (dlen >= LIBUSB_DT_BOS_SIZE && + dtype == LIBUSB_DT_BOS) { + + ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + + sizeof(*ss_cap)); + + if (ptr == NULL) + return (LIBUSB_ERROR_NO_MEM); + + *bos = ptr; + + ptr->bLength = LIBUSB_DT_BOS_SIZE; + ptr->bDescriptorType = dtype; + ptr->wTotalLength = ((const uint8_t *)buf)[2] | + (((const uint8_t *)buf)[3] << 8); + ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; + ptr->usb_2_0_ext_cap = NULL; + ptr->ss_usb_cap = NULL; + + dcap_20 = (void *)(ptr + 1); + ss_cap = (void *)(dcap_20 + 1); + } + if (dlen >= 3 && + ptr != NULL && + dtype == LIBUSB_DT_DEVICE_CAPABILITY) { + switch (((const uint8_t *)buf)[2]) { + case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: + if (ptr->usb_2_0_ext_cap != NULL) + break; + if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) + break; + + ptr->usb_2_0_ext_cap = dcap_20; + + dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; + dcap_20->bDescriptorType = dtype; + dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; + dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | + (((const uint8_t *)buf)[4] << 8) | + (((const uint8_t *)buf)[5] << 16) | + (((const uint8_t *)buf)[6] << 24); + break; + + case LIBUSB_SS_USB_DEVICE_CAPABILITY: + if (ptr->ss_usb_cap != NULL) + break; + if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) + break; + + ptr->ss_usb_cap = ss_cap; + + ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; + ss_cap->bDescriptorType = dtype; + ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; + ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; + ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | + (((const uint8_t *)buf)[5] << 8); + ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; + ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; + ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | + (((const uint8_t *)buf)[9] << 8); + break; + + default: + break; + } + } + + buf = ((const uint8_t *)buf) + dlen; + len -= dlen; + } + if (ptr != NULL) + return (0); /* success */ + + return (LIBUSB_ERROR_IO); +} + +void +libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) +{ + if (bos == NULL) + return; + + free(bos); +} Modified: stable/8/lib/libusb/libusb20_desc.c ============================================================================== --- stable/8/lib/libusb/libusb20_desc.c Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/libusb20_desc.c Sat Dec 3 13:54:54 2011 (r228223) @@ -41,6 +41,10 @@ LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_END LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_INTERFACE_DESC); LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONFIG_DESC); LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONTROL_SETUP); +LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_SS_ENDPT_COMP_DESC); +LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_USB_20_DEVCAP_DESC); +LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_SS_USB_DEVCAP_DESC); +LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_BOS_DESCRIPTOR); /*------------------------------------------------------------------------* * libusb20_parse_config_desc Modified: stable/8/lib/libusb/libusb20_desc.h ============================================================================== --- stable/8/lib/libusb/libusb20_desc.h Sat Dec 3 13:51:57 2011 (r228222) +++ stable/8/lib/libusb/libusb20_desc.h Sat Dec 3 13:54:54 2011 (r228223) @@ -264,6 +264,43 @@ LIBUSB20_MAKE_STRUCT(LIBUSB20_CONFIG_DES LIBUSB20_MAKE_STRUCT(LIBUSB20_CONTROL_SETUP); +#define LIBUSB20_SS_ENDPT_COMP_DESC(m,n) \ + m(n, UINT8_T, bLength, ) \ + m(n, UINT8_T, bDescriptorType, ) \ + m(n, UINT8_T, bMaxBurst, ) \ + m(n, UINT8_T, bmAttributes, ) \ + m(n, UINT16_T, wBytesPerInterval, ) \ + +LIBUSB20_MAKE_STRUCT(LIBUSB20_SS_ENDPT_COMP_DESC); + +#define LIBUSB20_USB_20_DEVCAP_DESC(m,n) \ + m(n, UINT8_T, bLength, ) \ + m(n, UINT8_T, bDescriptorType, ) \ + m(n, UINT8_T, bDevCapabilityType, ) \ + m(n, UINT32_T, bmAttributes, ) \ + +LIBUSB20_MAKE_STRUCT(LIBUSB20_USB_20_DEVCAP_DESC); + +#define LIBUSB20_SS_USB_DEVCAP_DESC(m,n) \ + m(n, UINT8_T, bLength, ) \ + m(n, UINT8_T, bDescriptorType, ) \ + m(n, UINT8_T, bDevCapabilityType, ) \ + m(n, UINT8_T, bmAttributes, ) \ + m(n, UINT16_T, wSpeedSupported, ) \ + m(n, UINT8_T, bFunctionalitySupport, ) \ + m(n, UINT8_T, bU1DevExitLat, ) \ + m(n, UINT16_T, wU2DevExitLat, ) \ + +LIBUSB20_MAKE_STRUCT(LIBUSB20_SS_USB_DEVCAP_DESC); + +#define LIBUSB20_BOS_DESCRIPTOR(m,n) \ + m(n, UINT8_T, bLength, ) \ + m(n, UINT8_T, bDescriptorType, ) \ + m(n, UINT16_T, wTotalLength, ) \ + m(n, UINT8_T, bNumDeviceCapabilities, ) \ + +LIBUSB20_MAKE_STRUCT(LIBUSB20_BOS_DESCRIPTOR); + /* standard USB stuff */ /** \ingroup desc @@ -333,6 +370,24 @@ enum libusb20_descriptor_type { /** Hub descriptor */ LIBUSB20_DT_HUB = 0x29, + + /** Binary Object Store, BOS */ + LIBUSB20_DT_BOS = 0x0f, + + /** Device Capability */ + LIBUSB20_DT_DEVICE_CAPABILITY = 0x10, + + /** SuperSpeed endpoint companion */ + LIBUSB20_DT_SS_ENDPOINT_COMPANION = 0x30, +}; + +/** \ingroup desc + * Device capability types as defined by the USB specification. */ +enum libusb20_device_capability_type { + LIBUSB20_WIRELESS_USB_DEVICE_CAPABILITY = 0x1, + LIBUSB20_USB_2_0_EXTENSION_DEVICE_CAPABILITY = 0x2, + LIBUSB20_SS_USB_DEVICE_CAPABILITY = 0x3, + LIBUSB20_CONTAINER_ID_DEVICE_CAPABILITY = 0x4, }; /* Descriptor sizes per descriptor type */ @@ -342,6 +397,10 @@ enum libusb20_descriptor_type { #define LIBUSB20_DT_ENDPOINT_SIZE 7 #define LIBUSB20_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ #define LIBUSB20_DT_HUB_NONVAR_SIZE 7 +#define LIBUSB20_DT_SS_ENDPOINT_COMPANION_SIZE 6 +#define LIBUSB20_DT_BOS_SIZE 5 +#define LIBUSB20_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE 7 +#define LIBUSB20_SS_USB_DEVICE_CAPABILITY_SIZE 10 #define LIBUSB20_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ #define LIBUSB20_ENDPOINT_DIR_MASK 0x80