diff options
| -rw-r--r-- | drivers/usb/core/message.c | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2bed83caacb1..9720e699f472 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
| 806 | return rc; | 806 | return rc; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf) | ||
| 810 | { | ||
| 811 | int err; | ||
| 812 | |||
| 813 | if (dev->have_langid) | ||
| 814 | return 0; | ||
| 815 | |||
| 816 | if (dev->string_langid < 0) | ||
| 817 | return -EPIPE; | ||
| 818 | |||
| 819 | err = usb_string_sub(dev, 0, 0, tbuf); | ||
| 820 | |||
| 821 | /* If the string was reported but is malformed, default to english | ||
| 822 | * (0x0409) */ | ||
| 823 | if (err == -ENODATA || (err > 0 && err < 4)) { | ||
| 824 | dev->string_langid = 0x0409; | ||
| 825 | dev->have_langid = 1; | ||
| 826 | dev_err(&dev->dev, | ||
| 827 | "string descriptor 0 malformed (err = %d), " | ||
| 828 | "defaulting to 0x%04x\n", | ||
| 829 | err, dev->string_langid); | ||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* In case of all other errors, we assume the device is not able to | ||
| 834 | * deal with strings at all. Set string_langid to -1 in order to | ||
| 835 | * prevent any string to be retrieved from the device */ | ||
| 836 | if (err < 0) { | ||
| 837 | dev_err(&dev->dev, "string descriptor 0 read error: %d\n", | ||
| 838 | err); | ||
| 839 | dev->string_langid = -1; | ||
| 840 | return -EPIPE; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* always use the first langid listed */ | ||
| 844 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
| 845 | dev->have_langid = 1; | ||
| 846 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
| 847 | dev->string_langid); | ||
| 848 | return 0; | ||
| 849 | } | ||
| 850 | |||
| 809 | /** | 851 | /** |
| 810 | * usb_string - returns UTF-8 version of a string descriptor | 852 | * usb_string - returns UTF-8 version of a string descriptor |
| 811 | * @dev: the device whose string descriptor is being retrieved | 853 | * @dev: the device whose string descriptor is being retrieved |
| @@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
| 837 | if (!tbuf) | 879 | if (!tbuf) |
| 838 | return -ENOMEM; | 880 | return -ENOMEM; |
| 839 | 881 | ||
| 840 | /* get langid for strings if it's not yet known */ | 882 | err = usb_get_langid(dev, tbuf); |
| 841 | if (!dev->have_langid) { | 883 | if (err < 0) |
| 842 | err = usb_string_sub(dev, 0, 0, tbuf); | 884 | goto errout; |
| 843 | if (err < 0) { | ||
| 844 | dev_err(&dev->dev, | ||
| 845 | "string descriptor 0 read error: %d\n", | ||
| 846 | err); | ||
| 847 | } else if (err < 4) { | ||
| 848 | dev_err(&dev->dev, "string descriptor 0 too short\n"); | ||
| 849 | } else { | ||
| 850 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
| 851 | /* always use the first langid listed */ | ||
| 852 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
| 853 | dev->string_langid); | ||
| 854 | } | ||
| 855 | |||
| 856 | dev->have_langid = 1; | ||
| 857 | } | ||
| 858 | 885 | ||
| 859 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); | 886 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); |
| 860 | if (err < 0) | 887 | if (err < 0) |
