From e873677b9196b191d6cdbdf9783c6d6a18379249 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Fri, 17 Apr 2020 13:22:34 -0700 Subject: descriptor: Minor improvements to the parse_descriptor() function Change the type of the source pointer to 'void' so that callers need not cast to 'unsigned char'. Also change working types to 'uint8_t' to make it explicit that we are dealing with 8-bit types. Refactor the parsing loop to avoid unnecessary stack variables. The generated assembly with this change is more efficient. Signed-off-by: Chris Dickens --- libusb/descriptor.c | 78 +++++++++++++++++++++++++++------------------------ libusb/version_nano.h | 2 +- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index e4f376f..b65557f 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -30,41 +30,47 @@ * for detected devices */ -static void parse_descriptor(const unsigned char *source, const char *descriptor, void *dest) +#define READ_LE16(p) ((uint16_t) \ + (((uint16_t)((p)[1]) << 8) | \ + ((uint16_t)((p)[0])))) + +#define READ_LE32(p) ((uint32_t) \ + (((uint32_t)((p)[3]) << 24) | \ + ((uint32_t)((p)[2]) << 16) | \ + ((uint32_t)((p)[1]) << 8) | \ + ((uint32_t)((p)[0])))) + +static void parse_descriptor(const void *source, const char *descriptor, void *dest) { - const unsigned char *sp = source; - unsigned char *dp = dest; - uint16_t w; - const char *cp; - uint32_t d; - - for (cp = descriptor; *cp; cp++) { - switch (*cp) { - case 'b': /* 8-bit byte */ - *dp++ = *sp++; - break; - case 'w': /* 16-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ + const uint8_t *sp = source; + uint8_t *dp = dest; + char field_type; + + while (*descriptor) { + field_type = *descriptor++; + switch (field_type) { + case 'b': /* 8-bit byte */ + *dp++ = *sp++; + break; + case 'w': /* 16-bit word, convert from little endian to CPU */ + dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - w = (uint16_t)((sp[1] << 8) | sp[0]); - *((uint16_t *)dp) = w; - sp += 2; - dp += 2; - break; - case 'd': /* 32-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - - d = (uint32_t)((sp[3] << 24) | (sp[2] << 16) | - (sp[1] << 8) | sp[0]); - *((uint32_t *)dp) = d; - sp += 4; - dp += 4; - break; - case 'u': /* 16 byte UUID */ - memcpy(dp, sp, 16); - sp += 16; - dp += 16; - break; + *((uint16_t *)dp) = READ_LE16(sp); + sp += 2; + dp += 2; + break; + case 'd': /* 32-bit word, convert from little endian to CPU */ + dp += ((uintptr_t)dp & 1); /* Align to word boundary */ + + *((uint32_t *)dp) = READ_LE32(sp); + sp += 4; + dp += 4; + break; + case 'u': /* 16 byte UUID */ + memcpy(dp, sp, 16); + sp += 16; + dp += 16; + break; } } } @@ -950,7 +956,7 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor( if (!_usb_2_0_extension) return LIBUSB_ERROR_NO_MEM; - parse_descriptor((unsigned char *)dev_cap, "bbbd", _usb_2_0_extension); + parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension); *usb_2_0_extension = _usb_2_0_extension; return LIBUSB_SUCCESS; @@ -1006,7 +1012,7 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( if (!_ss_usb_device_cap) return LIBUSB_ERROR_NO_MEM; - parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw", _ss_usb_device_cap); + parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap); *ss_usb_device_cap = _ss_usb_device_cap; return LIBUSB_SUCCESS; @@ -1062,7 +1068,7 @@ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, if (!_container_id) return LIBUSB_ERROR_NO_MEM; - parse_descriptor((unsigned char *)dev_cap, "bbbbu", _container_id); + parse_descriptor(dev_cap, "bbbbu", _container_id); *container_id = _container_id; return LIBUSB_SUCCESS; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f2e5eaa..49b7a05 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11506 +#define LIBUSB_NANO 11507 -- cgit v1.2.1