diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index bd2a446b..d8db3849 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -843,12 +843,40 @@ int usb_control ( struct usb_device *usb, unsigned int request, return rc; } +/** + * Get default language ID + * + * @v usb USB device + * @ret language Language ID + */ +static unsigned int usb_get_default_language ( struct usb_device *usb ) { + struct { + struct usb_descriptor_header header; + uint16_t language[1]; + } __attribute__ (( packed )) desc; + unsigned int language; + int rc; + + /* Get descriptor */ + if ( ( rc = usb_get_descriptor ( usb, 0, USB_STRING_DESCRIPTOR, 0, 0, + &desc.header, sizeof ( desc ) ) ) !=0){ + DBGC ( usb, "USB %s has no default language: %s\n", + usb->name, strerror ( rc ) ); + return USB_LANG_ENGLISH; + } + + /* Use first language ID */ + language = le16_to_cpu ( desc.language[0] ); + DBGC2 ( usb, "USB %s default language %#04x\n", usb->name, language ); + return language; +} + /** * Get USB string descriptor * * @v usb USB device * @v index String index - * @v language Language ID + * @v language Language ID, or 0 to use default * @v buf Data buffer * @v len Length of buffer * @ret len String length (excluding NUL), or negative error @@ -864,6 +892,13 @@ int usb_get_string_descriptor ( struct usb_device *usb, unsigned int index, unsigned int i; int rc; + /* Use default language ID, if applicable */ + if ( ( language == 0 ) && ( index != 0 ) ) { + if ( ! usb->language ) + usb->language = usb_get_default_language ( usb ); + language = usb->language; + } + /* Allocate buffer for string */ desc = malloc ( sizeof ( *desc ) ); if ( ! desc ) { diff --git a/src/include/ipxe/usb.h b/src/include/ipxe/usb.h index e7909d30..68289d26 100644 --- a/src/include/ipxe/usb.h +++ b/src/include/ipxe/usb.h @@ -223,6 +223,9 @@ struct usb_string_descriptor { /** A USB string descriptor */ #define USB_STRING_DESCRIPTOR 3 +/** Language ID for English */ +#define USB_LANG_ENGLISH 0x0409 + /** A USB interface descriptor */ struct usb_interface_descriptor { /** Descriptor header */ @@ -728,6 +731,9 @@ struct usb_device { struct usb_endpoint control; /** Completed control transfers */ struct list_head complete; + + /** Default language ID (if known) */ + unsigned int language; }; /** USB device host controller operations */