Blame SOURCES/0007-lsusb-Add-support-for-descriptor-extensions.patch

67abd2
From 4f2a365e20831076816b8672735118f654ccfcd8 Mon Sep 17 00:00:00 2001
67abd2
From: Michael Drake <michael.drake@codethink.co.uk>
67abd2
Date: Thu, 7 Jun 2018 12:41:16 +0100
67abd2
Subject: [PATCH 7/9] lsusb: Add support for descriptor extensions.
67abd2
67abd2
These allow descriptors with common fields at the start, one of
67abd2
which common fields specifies a field whos value determines which
67abd2
of a set of descriptor extensions should be used to render the
67abd2
remainder of the descriptor.
67abd2
67abd2
Signed-off-by: Michael Drake <michael.drake@codethink.co.uk>
67abd2
---
67abd2
 desc-defs.c | 11 ++++++++++-
67abd2
 desc-defs.h | 39 ++++++++++++++++++++++++++++++++++++++-
67abd2
 desc-dump.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
67abd2
 3 files changed, 93 insertions(+), 9 deletions(-)
67abd2
67abd2
diff --git a/desc-defs.c b/desc-defs.c
67abd2
index 4c374e0..60cc603 100644
67abd2
--- a/desc-defs.c
67abd2
+++ b/desc-defs.c
67abd2
@@ -2,7 +2,7 @@
67abd2
 /*
67abd2
  * USB descriptor definitions
67abd2
  *
67abd2
- * Copyright (C) 2017 Michael Drake <michael.drake@codethink.co.uk>
67abd2
+ * Copyright (C) 2017-2018 Michael Drake <michael.drake@codethink.co.uk>
67abd2
  */
67abd2
 
67abd2
 #include "config.h"
67abd2
@@ -441,6 +441,15 @@ static const struct desc desc_audio_2_ac_processing_unit[] = {
67abd2
 	{ .field = NULL }
67abd2
 };
67abd2
 
67abd2
+/**
67abd2
+ * Undefined descriptor
67abd2
+ *
67abd2
+ * Ensures remaining data is dumped as garbage at end of descriptor.
67abd2
+ */
67abd2
+const struct desc desc_undefined[] = {
67abd2
+	{ .field = NULL }
67abd2
+};
67abd2
+
67abd2
 /** UAC3: 4.5.2.10 Processing Unit Descriptor; Table 4-38. */
67abd2
 static const struct desc desc_audio_3_ac_processing_unit[] = {
67abd2
 	{ .field = "bUnitID",             .size = 1, .type = DESC_NUMBER },
67abd2
diff --git a/desc-defs.h b/desc-defs.h
67abd2
index 99d5caa..aa695e4 100644
67abd2
--- a/desc-defs.h
67abd2
+++ b/desc-defs.h
67abd2
@@ -2,7 +2,7 @@
67abd2
 /*
67abd2
  * USB descriptor definitions
67abd2
  *
67abd2
- * Copyright (C) 2017 Michael Drake <michael.drake@codethink.co.uk>
67abd2
+ * Copyright (C) 2017-2018 Michael Drake <michael.drake@codethink.co.uk>
67abd2
  */
67abd2
 
67abd2
 #ifndef _DESC_DEFS_H
67abd2
@@ -33,6 +33,7 @@ enum desc_type {
67abd2
 	DESC_TERMINAL_STR,   /**< Audio terminal string. */
67abd2
 	DESC_BITMAP_STRINGS, /**< Bitfield with string per bit. */
67abd2
 	DESC_NUMBER_STRINGS, /**< Use for enum-style value to string. */
67abd2
+	DESC_EXTENSION,      /**< Various possible descriptor extensions. */
67abd2
 	DESC_SNOWFLAKE,  /**< Value with custom annotation callback function. */
67abd2
 };
67abd2
 
67abd2
@@ -95,6 +96,39 @@ struct desc {
67abd2
 		 * Must be a '\0' terminated string.
67abd2
 		 */
67abd2
 		const char *number_postfix;
67abd2
+		/**
67abd2
+		 * Corresponds to type DESC_EXTENSION.
67abd2
+		 *
67abd2
+		 * This allows the value of this field to be processed by
67abd2
+		 * another descriptor definition.  The definition used to
67abd2
+		 * process the value of this field can be controlled by
67abd2
+		 * the value of another field.
67abd2
+		 */
67abd2
+		struct {
67abd2
+			/**
67abd2
+			 * Name of field specifying descriptor type to select.
67abd2
+			 */
67abd2
+			const char *type_field;
67abd2
+			/**
67abd2
+			 * Array of descriptor definitions and their
67abd2
+			 * associated types values.  Array must be terminated
67abd2
+			 * by entry with NULL `desc` member.
67abd2
+			 */
67abd2
+			const struct desc_ext {
67abd2
+				/**
67abd2
+				 * Array of descriptor field definitions.
67abd2
+				 * Terminated by entry with NULL `field` member.
67abd2
+				 */
67abd2
+				const struct desc *desc;
67abd2
+				/**
67abd2
+				 * Type value for this descriptor definition.
67abd2
+				 * If it matches the type read from the
67abd2
+				 * field `type_field`, then this descriptor
67abd2
+				 * definition will be used to decode this value.
67abd2
+				 */
67abd2
+				unsigned int type;
67abd2
+			} *d;
67abd2
+		} extension;
67abd2
 		/**
67abd2
 		 * Corresponds to type DESC_SNOWFLAKE.
67abd2
 		 *
67abd2
@@ -116,6 +150,9 @@ struct desc {
67abd2
 
67abd2
 /* ---------------------------------------------------------------------- */
67abd2
 
67abd2
+/* Undefined descriptor */
67abd2
+extern const struct desc desc_undefined[];
67abd2
+
67abd2
 /* Audio Control (AC) descriptor definitions */
67abd2
 extern const struct desc * const desc_audio_ac_header[3];
67abd2
 extern const struct desc * const desc_audio_ac_effect_unit[3];
67abd2
diff --git a/desc-dump.c b/desc-dump.c
67abd2
index 2f92768..19d2cc7 100644
67abd2
--- a/desc-dump.c
67abd2
+++ b/desc-dump.c
67abd2
@@ -211,8 +211,10 @@ static void number_renderer(
67abd2
  *
67abd2
  * \param[in] dev           LibUSB device handle.
67abd2
  * \param[in] current       Descriptor definition field to render.
67abd2
- * \param[in] current_size  Descriptor definition field to render.
67abd2
+ * \param[in] current_size  Size of value to render.
67abd2
  * \param[in] buf           Byte array containing the descriptor date to dump.
67abd2
+ * \param[in] buf_len       Byte length of `buf`.
67abd2
+ * \param[in] desc          First field in the descriptor definition.
67abd2
  * \param[in] indent        Current indent level.
67abd2
  * \param[in] offset        Offset to current value in `buf`.
67abd2
  */
67abd2
@@ -221,6 +223,8 @@ static void value_renderer(
67abd2
 		const struct desc *current,
67abd2
 		unsigned int current_size,
67abd2
 		const unsigned char *buf,
67abd2
+		unsigned int buf_len,
67abd2
+		const struct desc *desc,
67abd2
 		unsigned int indent,
67abd2
 		size_t offset)
67abd2
 {
67abd2
@@ -312,6 +316,31 @@ static void value_renderer(
67abd2
 		printf(" %s\n", names_audioterminal(
67abd2
 				get_n_bytes_as_ull(buf, offset, current_size)));
67abd2
 		break;
67abd2
+	case DESC_EXTENSION: {
67abd2
+		unsigned int type = get_value_from_field(buf, desc,
67abd2
+				current->extension.type_field);
67abd2
+		const struct desc *ext_desc;
67abd2
+		const struct desc_ext *ext;
67abd2
+
67abd2
+		/* Lookup the extention descriptor definitions to use, */
67abd2
+		for (ext = current->extension.d; ext->desc != NULL; ext++) {
67abd2
+			if (ext->type == type) {
67abd2
+				ext_desc = ext->desc;
67abd2
+				break;
67abd2
+			}
67abd2
+		}
67abd2
+
67abd2
+		/* If the type didn't match a known type, use the
67abd2
+		 * undefined descriptor. */
67abd2
+		if (ext->desc == NULL) {
67abd2
+			ext_desc = desc_undefined;
67abd2
+		}
67abd2
+
67abd2
+		desc_dump(dev, ext_desc, buf + offset,
67abd2
+				buf_len - offset, indent);
67abd2
+
67abd2
+		break;
67abd2
+	}
67abd2
 	case DESC_SNOWFLAKE:
67abd2
 		number_renderer(buf, size_chars, offset, current_size);
67abd2
 		current->snowflake(
67abd2
@@ -537,14 +566,23 @@ void desc_dump(
67abd2
 			}
67abd2
 
67abd2
 			/* Dump the field name */
67abd2
-			field_render(entry, entries, field_len,
67abd2
-					current, indent);
67abd2
+			if (current->type != DESC_EXTENSION) {
67abd2
+				field_render(entry, entries, field_len,
67abd2
+						current, indent);
67abd2
+			}
67abd2
 
67abd2
 			/* Dump the value */
67abd2
-			value_renderer(dev, current, current_size, buf,
67abd2
-					indent, offset);
67abd2
-			/* Advance offset in buffer */
67abd2
-			offset += current_size;
67abd2
+			value_renderer(dev, current, current_size, buf, buf_len,
67abd2
+					desc, indent, offset);
67abd2
+
67abd2
+			if (current->type == DESC_EXTENSION) {
67abd2
+				/* A desc extension consumes all remaining
67abd2
+				 * value buffer. */
67abd2
+				offset = buf_len;
67abd2
+			} else {
67abd2
+				/* Advance offset in buffer */
67abd2
+				offset += current_size;
67abd2
+			}
67abd2
 		}
67abd2
 	}
67abd2
 
67abd2
-- 
67abd2
2.14.4
67abd2