diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2011-11-17 16:42:24 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-18 13:51:01 -0500 |
commit | 86dc243cb2ddecb6984401463ebb0963ceff3cdc (patch) | |
tree | b4d9e980c1c2333138b9d3a7b2285d19cf7c833d | |
parent | 0720a06a7518c9d0c0125bd5d1f3b6264c55c3dd (diff) |
USB: remove homegrown UTF conversion routine for gadgets
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>
-rw-r--r-- | drivers/usb/gadget/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/usbstring.c | 73 |
2 files changed, 5 insertions, 69 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b21cd376c11a..a11dbc85d08b 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | menuconfig USB_GADGET | 16 | menuconfig USB_GADGET |
17 | tristate "USB Gadget Support" | 17 | tristate "USB Gadget Support" |
18 | select NLS | ||
18 | help | 19 | help |
19 | USB is a master/slave protocol, organized with one master | 20 | USB is a master/slave protocol, organized with one master |
20 | host (such as a PC) controlling up to 127 peripheral devices. | 21 | host (such as a PC) controlling up to 127 peripheral devices. |
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 58c4d37d312a..4d25b9009edf 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c | |||
@@ -13,82 +13,17 @@ | |||
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/nls.h> | ||
16 | 17 | ||
17 | #include <linux/usb/ch9.h> | 18 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/gadget.h> | 19 | #include <linux/usb/gadget.h> |
19 | 20 | ||
20 | #include <asm/unaligned.h> | ||
21 | |||
22 | |||
23 | static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len) | ||
24 | { | ||
25 | int count = 0; | ||
26 | u8 c; | ||
27 | u16 uchar; | ||
28 | |||
29 | /* this insists on correct encodings, though not minimal ones. | ||
30 | * BUT it currently rejects legit 4-byte UTF-8 code points, | ||
31 | * which need surrogate pairs. (Unicode 3.1 can use them.) | ||
32 | */ | ||
33 | while (len != 0 && (c = (u8) *s++) != 0) { | ||
34 | if (unlikely(c & 0x80)) { | ||
35 | // 2-byte sequence: | ||
36 | // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx | ||
37 | if ((c & 0xe0) == 0xc0) { | ||
38 | uchar = (c & 0x1f) << 6; | ||
39 | |||
40 | c = (u8) *s++; | ||
41 | if ((c & 0xc0) != 0x80) | ||
42 | goto fail; | ||
43 | c &= 0x3f; | ||
44 | uchar |= c; | ||
45 | |||
46 | // 3-byte sequence (most CJKV characters): | ||
47 | // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx | ||
48 | } else if ((c & 0xf0) == 0xe0) { | ||
49 | uchar = (c & 0x0f) << 12; | ||
50 | |||
51 | c = (u8) *s++; | ||
52 | if ((c & 0xc0) != 0x80) | ||
53 | goto fail; | ||
54 | c &= 0x3f; | ||
55 | uchar |= c << 6; | ||
56 | |||
57 | c = (u8) *s++; | ||
58 | if ((c & 0xc0) != 0x80) | ||
59 | goto fail; | ||
60 | c &= 0x3f; | ||
61 | uchar |= c; | ||
62 | |||
63 | /* no bogus surrogates */ | ||
64 | if (0xd800 <= uchar && uchar <= 0xdfff) | ||
65 | goto fail; | ||
66 | |||
67 | // 4-byte sequence (surrogate pairs, currently rare): | ||
68 | // 11101110wwwwzzzzyy + 110111yyyyxxxxxx | ||
69 | // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx | ||
70 | // (uuuuu = wwww + 1) | ||
71 | // FIXME accept the surrogate code points (only) | ||
72 | |||
73 | } else | ||
74 | goto fail; | ||
75 | } else | ||
76 | uchar = c; | ||
77 | put_unaligned_le16(uchar, cp++); | ||
78 | count++; | ||
79 | len--; | ||
80 | } | ||
81 | return count; | ||
82 | fail: | ||
83 | return -1; | ||
84 | } | ||
85 | |||
86 | 21 | ||
87 | /** | 22 | /** |
88 | * usb_gadget_get_string - fill out a string descriptor | 23 | * usb_gadget_get_string - fill out a string descriptor |
89 | * @table: of c strings encoded using UTF-8 | 24 | * @table: of c strings encoded using UTF-8 |
90 | * @id: string id, from low byte of wValue in get string descriptor | 25 | * @id: string id, from low byte of wValue in get string descriptor |
91 | * @buf: at least 256 bytes | 26 | * @buf: at least 256 bytes, must be 16-bit aligned |
92 | * | 27 | * |
93 | * Finds the UTF-8 string matching the ID, and converts it into a | 28 | * Finds the UTF-8 string matching the ID, and converts it into a |
94 | * string descriptor in utf16-le. | 29 | * string descriptor in utf16-le. |
@@ -125,8 +60,8 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) | |||
125 | 60 | ||
126 | /* string descriptors have length, tag, then UTF16-LE text */ | 61 | /* string descriptors have length, tag, then UTF16-LE text */ |
127 | len = min ((size_t) 126, strlen (s->s)); | 62 | len = min ((size_t) 126, strlen (s->s)); |
128 | memset (buf + 2, 0, 2 * len); /* zero all the bytes */ | 63 | len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN, |
129 | len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len); | 64 | (wchar_t *) &buf[2], 126); |
130 | if (len < 0) | 65 | if (len < 0) |
131 | return -EINVAL; | 66 | return -EINVAL; |
132 | buf [0] = (len + 1) * 2; | 67 | buf [0] = (len + 1) * 2; |