Browse Source

[usb] Use non-zero language ID to retrieve strings

We currently use a zero language ID to retrieve strings such as the
ECM/NCM MAC address.  This works on most hardware devices, but is
known to fail on some software emulated CDC-NCM devices.

Fix by using the first supported language ID, falling back to English
(0x0409) if any error occurs when fetching the list of supported
languages.  This matches the behaviour of the Linux kernel.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
8e48d0df6b
2 changed files with 42 additions and 1 deletions
  1. 36
    1
      src/drivers/bus/usb.c
  2. 6
    0
      src/include/ipxe/usb.h

+ 36
- 1
src/drivers/bus/usb.c View File

843
 	return rc;
843
 	return rc;
844
 }
844
 }
845
 
845
 
846
+/**
847
+ * Get default language ID
848
+ *
849
+ * @v usb		USB device
850
+ * @ret language	Language ID
851
+ */
852
+static unsigned int usb_get_default_language ( struct usb_device *usb ) {
853
+	struct {
854
+		struct usb_descriptor_header header;
855
+		uint16_t language[1];
856
+	} __attribute__ (( packed )) desc;
857
+	unsigned int language;
858
+	int rc;
859
+
860
+	/* Get descriptor */
861
+	if ( ( rc = usb_get_descriptor ( usb, 0, USB_STRING_DESCRIPTOR, 0, 0,
862
+					 &desc.header, sizeof ( desc ) ) ) !=0){
863
+		DBGC ( usb, "USB %s has no default language: %s\n",
864
+		       usb->name, strerror ( rc ) );
865
+		return USB_LANG_ENGLISH;
866
+	}
867
+
868
+	/* Use first language ID */
869
+	language = le16_to_cpu ( desc.language[0] );
870
+	DBGC2 ( usb, "USB %s default language %#04x\n", usb->name, language );
871
+	return language;
872
+}
873
+
846
 /**
874
 /**
847
  * Get USB string descriptor
875
  * Get USB string descriptor
848
  *
876
  *
849
  * @v usb		USB device
877
  * @v usb		USB device
850
  * @v index		String index
878
  * @v index		String index
851
- * @v language		Language ID
879
+ * @v language		Language ID, or 0 to use default
852
  * @v buf		Data buffer
880
  * @v buf		Data buffer
853
  * @v len		Length of buffer
881
  * @v len		Length of buffer
854
  * @ret len		String length (excluding NUL), or negative error
882
  * @ret len		String length (excluding NUL), or negative error
864
 	unsigned int i;
892
 	unsigned int i;
865
 	int rc;
893
 	int rc;
866
 
894
 
895
+	/* Use default language ID, if applicable */
896
+	if ( ( language == 0 ) && ( index != 0 ) ) {
897
+		if ( ! usb->language )
898
+			usb->language = usb_get_default_language ( usb );
899
+		language = usb->language;
900
+	}
901
+
867
 	/* Allocate buffer for string */
902
 	/* Allocate buffer for string */
868
 	desc = malloc ( sizeof ( *desc ) );
903
 	desc = malloc ( sizeof ( *desc ) );
869
 	if ( ! desc ) {
904
 	if ( ! desc ) {

+ 6
- 0
src/include/ipxe/usb.h View File

223
 /** A USB string descriptor */
223
 /** A USB string descriptor */
224
 #define USB_STRING_DESCRIPTOR 3
224
 #define USB_STRING_DESCRIPTOR 3
225
 
225
 
226
+/** Language ID for English */
227
+#define USB_LANG_ENGLISH 0x0409
228
+
226
 /** A USB interface descriptor */
229
 /** A USB interface descriptor */
227
 struct usb_interface_descriptor {
230
 struct usb_interface_descriptor {
228
 	/** Descriptor header */
231
 	/** Descriptor header */
728
 	struct usb_endpoint control;
731
 	struct usb_endpoint control;
729
 	/** Completed control transfers */
732
 	/** Completed control transfers */
730
 	struct list_head complete;
733
 	struct list_head complete;
734
+
735
+	/** Default language ID (if known) */
736
+	unsigned int language;
731
 };
737
 };
732
 
738
 
733
 /** USB device host controller operations */
739
 /** USB device host controller operations */

Loading…
Cancel
Save