USB: remove homegrown UTF conversion routine for gadgets
authorAlan Stern <stern@rowland.harvard.edu>
Thu, 17 Nov 2011 21:42:24 +0000 (16:42 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 18 Nov 2011 18:51:01 +0000 (10:51 -0800)
This patch (as1502) removes the UTF8-to-UTF16 conversion routine in
the USB gadget library and replaces it with a call to the equivalent
function in the NLS library.

The only downside worth noting is that the NLS library routine
requires the output buffer to be 16-bit aligned.  This is always true
in the gadget code, because the output buffer is always a
usb_request buffer being used to send a string descriptor.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/Kconfig
drivers/usb/gadget/usbstring.c

index b21cd376c11af5978095c97f49bdee67aa1ec6d0..a11dbc85d08b5a0585e5c154fc7e06f67f014b4c 100644 (file)
@@ -15,6 +15,7 @@
 
 menuconfig USB_GADGET
        tristate "USB Gadget Support"
+       select NLS
        help
           USB is a master/slave protocol, organized with one master
           host (such as a PC) controlling up to 127 peripheral devices.
index 58c4d37d312a4ce40e487abeb36e45c34c3002fc..4d25b9009edf4175d3a5e648c877fad6d2890925 100644 (file)
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/nls.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
-#include <asm/unaligned.h>
-
-
-static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
-{
-       int     count = 0;
-       u8      c;
-       u16     uchar;
-
-       /* this insists on correct encodings, though not minimal ones.
-        * BUT it currently rejects legit 4-byte UTF-8 code points,
-        * which need surrogate pairs.  (Unicode 3.1 can use them.)
-        */
-       while (len != 0 && (c = (u8) *s++) != 0) {
-               if (unlikely(c & 0x80)) {
-                       // 2-byte sequence:
-                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
-                       if ((c & 0xe0) == 0xc0) {
-                               uchar = (c & 0x1f) << 6;
-
-                               c = (u8) *s++;
-                               if ((c & 0xc0) != 0x80)
-                                       goto fail;
-                               c &= 0x3f;
-                               uchar |= c;
-
-                       // 3-byte sequence (most CJKV characters):
-                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
-                       } else if ((c & 0xf0) == 0xe0) {
-                               uchar = (c & 0x0f) << 12;
-
-                               c = (u8) *s++;
-                               if ((c & 0xc0) != 0x80)
-                                       goto fail;
-                               c &= 0x3f;
-                               uchar |= c << 6;
-
-                               c = (u8) *s++;
-                               if ((c & 0xc0) != 0x80)
-                                       goto fail;
-                               c &= 0x3f;
-                               uchar |= c;
-
-                               /* no bogus surrogates */
-                               if (0xd800 <= uchar && uchar <= 0xdfff)
-                                       goto fail;
-
-                       // 4-byte sequence (surrogate pairs, currently rare):
-                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
-                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
-                       // (uuuuu = wwww + 1)
-                       // FIXME accept the surrogate code points (only)
-
-                       } else
-                               goto fail;
-               } else
-                       uchar = c;
-               put_unaligned_le16(uchar, cp++);
-               count++;
-               len--;
-       }
-       return count;
-fail:
-       return -1;
-}
-
 
 /**
  * usb_gadget_get_string - fill out a string descriptor 
  * @table: of c strings encoded using UTF-8
  * @id: string id, from low byte of wValue in get string descriptor
- * @buf: at least 256 bytes
+ * @buf: at least 256 bytes, must be 16-bit aligned
  *
  * Finds the UTF-8 string matching the ID, and converts it into a
  * string descriptor in utf16-le.
@@ -125,8 +60,8 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
 
        /* string descriptors have length, tag, then UTF16-LE text */
        len = min ((size_t) 126, strlen (s->s));
-       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
-       len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
+       len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
+                       (wchar_t *) &buf[2], 126);
        if (len < 0)
                return -EINVAL;
        buf [0] = (len + 1) * 2;