diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2009-04-24 04:12:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:43 -0400 |
commit | a853a3d4eb2edb066248a39f0634f6f5858816a0 (patch) | |
tree | eeba17105c89d532335a4577cec912763100beae /drivers/usb/core | |
parent | 905c02acbd89f427c87a6d0a50fed757f6b3001c (diff) |
usb: return device strings in UTF-8
Change the encoding of strings returned by usb_string() from ISO 8859-1
to UTF-8.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/message.c | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b62628377654..e98f928c08ea 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/timer.h> | 11 | #include <linux/timer.h> |
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/nls.h> | ||
13 | #include <linux/device.h> | 14 | #include <linux/device.h> |
14 | #include <linux/scatterlist.h> | 15 | #include <linux/scatterlist.h> |
15 | #include <linux/usb/quirks.h> | 16 | #include <linux/usb/quirks.h> |
@@ -759,7 +760,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
759 | } | 760 | } |
760 | 761 | ||
761 | /** | 762 | /** |
762 | * usb_string - returns ISO 8859-1 version of a string descriptor | 763 | * usb_string - returns UTF-8 version of a string descriptor |
763 | * @dev: the device whose string descriptor is being retrieved | 764 | * @dev: the device whose string descriptor is being retrieved |
764 | * @index: the number of the descriptor | 765 | * @index: the number of the descriptor |
765 | * @buf: where to put the string | 766 | * @buf: where to put the string |
@@ -767,17 +768,10 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
767 | * Context: !in_interrupt () | 768 | * Context: !in_interrupt () |
768 | * | 769 | * |
769 | * This converts the UTF-16LE encoded strings returned by devices, from | 770 | * This converts the UTF-16LE encoded strings returned by devices, from |
770 | * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones | 771 | * usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones |
771 | * that are more usable in most kernel contexts. Note that all characters | 772 | * that are more usable in most kernel contexts. Note that this function |
772 | * in the chosen descriptor that can't be encoded using ISO-8859-1 | ||
773 | * are converted to the question mark ("?") character, and this function | ||
774 | * chooses strings in the first language supported by the device. | 773 | * chooses strings in the first language supported by the device. |
775 | * | 774 | * |
776 | * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit | ||
777 | * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, | ||
778 | * and is appropriate for use many uses of English and several other | ||
779 | * Western European languages. (But it doesn't include the "Euro" symbol.) | ||
780 | * | ||
781 | * This call is synchronous, and may not be used in an interrupt context. | 775 | * This call is synchronous, and may not be used in an interrupt context. |
782 | * | 776 | * |
783 | * Returns length of the string (>= 0) or usb_control_msg status (< 0). | 777 | * Returns length of the string (>= 0) or usb_control_msg status (< 0). |
@@ -786,14 +780,14 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
786 | { | 780 | { |
787 | unsigned char *tbuf; | 781 | unsigned char *tbuf; |
788 | int err; | 782 | int err; |
789 | unsigned int u, idx; | 783 | unsigned int u; |
790 | 784 | ||
791 | if (dev->state == USB_STATE_SUSPENDED) | 785 | if (dev->state == USB_STATE_SUSPENDED) |
792 | return -EHOSTUNREACH; | 786 | return -EHOSTUNREACH; |
793 | if (size <= 0 || !buf || !index) | 787 | if (size <= 0 || !buf || !index) |
794 | return -EINVAL; | 788 | return -EINVAL; |
795 | buf[0] = 0; | 789 | buf[0] = 0; |
796 | tbuf = kmalloc(256, GFP_NOIO); | 790 | tbuf = kmalloc(256 + 2, GFP_NOIO); |
797 | if (!tbuf) | 791 | if (!tbuf) |
798 | return -ENOMEM; | 792 | return -ENOMEM; |
799 | 793 | ||
@@ -820,17 +814,13 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
820 | if (err < 0) | 814 | if (err < 0) |
821 | goto errout; | 815 | goto errout; |
822 | 816 | ||
817 | for (u = 2; u < err; u += 2) | ||
818 | le16_to_cpus((u16 *)&tbuf[u]); | ||
819 | tbuf[u] = 0; | ||
820 | tbuf[u + 1] = 0; | ||
823 | size--; /* leave room for trailing NULL char in output buffer */ | 821 | size--; /* leave room for trailing NULL char in output buffer */ |
824 | for (idx = 0, u = 2; u < err; u += 2) { | 822 | err = utf8_wcstombs(buf, (u16 *)&tbuf[2], size); |
825 | if (idx >= size) | 823 | buf[err] = 0; |
826 | break; | ||
827 | if (tbuf[u+1]) /* high byte */ | ||
828 | buf[idx++] = '?'; /* non ISO-8859-1 character */ | ||
829 | else | ||
830 | buf[idx++] = tbuf[u]; | ||
831 | } | ||
832 | buf[idx] = 0; | ||
833 | err = idx; | ||
834 | 824 | ||
835 | if (tbuf[1] != USB_DT_STRING) | 825 | if (tbuf[1] != USB_DT_STRING) |
836 | dev_dbg(&dev->dev, | 826 | dev_dbg(&dev->dev, |
@@ -843,6 +833,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
843 | } | 833 | } |
844 | EXPORT_SYMBOL_GPL(usb_string); | 834 | EXPORT_SYMBOL_GPL(usb_string); |
845 | 835 | ||
836 | /* one UTF-8-encoded 16-bit character has at most three bytes */ | ||
837 | #define MAX_USB_STRING_SIZE (127 * 3 + 1) | ||
838 | |||
846 | /** | 839 | /** |
847 | * usb_cache_string - read a string descriptor and cache it for later use | 840 | * usb_cache_string - read a string descriptor and cache it for later use |
848 | * @udev: the device whose string descriptor is being read | 841 | * @udev: the device whose string descriptor is being read |
@@ -860,9 +853,9 @@ char *usb_cache_string(struct usb_device *udev, int index) | |||
860 | if (index <= 0) | 853 | if (index <= 0) |
861 | return NULL; | 854 | return NULL; |
862 | 855 | ||
863 | buf = kmalloc(256, GFP_KERNEL); | 856 | buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); |
864 | if (buf) { | 857 | if (buf) { |
865 | len = usb_string(udev, index, buf, 256); | 858 | len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE); |
866 | if (len > 0) { | 859 | if (len > 0) { |
867 | smallbuf = kmalloc(++len, GFP_KERNEL); | 860 | smallbuf = kmalloc(++len, GFP_KERNEL); |
868 | if (!smallbuf) | 861 | if (!smallbuf) |