aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-04-24 04:12:18 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:43 -0400
commita853a3d4eb2edb066248a39f0634f6f5858816a0 (patch)
treeeeba17105c89d532335a4577cec912763100beae /drivers/usb/core
parent905c02acbd89f427c87a6d0a50fed757f6b3001c (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.c41
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}
844EXPORT_SYMBOL_GPL(usb_string); 834EXPORT_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)