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>
This commit is contained in:
parent
0720a06a75
commit
86dc243cb2
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
menuconfig USB_GADGET
|
menuconfig USB_GADGET
|
||||||
tristate "USB Gadget Support"
|
tristate "USB Gadget Support"
|
||||||
|
select NLS
|
||||||
help
|
help
|
||||||
USB is a master/slave protocol, organized with one master
|
USB is a master/slave protocol, organized with one master
|
||||||
host (such as a PC) controlling up to 127 peripheral devices.
|
host (such as a PC) controlling up to 127 peripheral devices.
|
||||||
|
|
|
@ -13,82 +13,17 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/nls.h>
|
||||||
|
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.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
|
* usb_gadget_get_string - fill out a string descriptor
|
||||||
* @table: of c strings encoded using UTF-8
|
* @table: of c strings encoded using UTF-8
|
||||||
* @id: string id, from low byte of wValue in get string descriptor
|
* @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
|
* Finds the UTF-8 string matching the ID, and converts it into a
|
||||||
* string descriptor in utf16-le.
|
* 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 */
|
/* string descriptors have length, tag, then UTF16-LE text */
|
||||||
len = min ((size_t) 126, strlen (s->s));
|
len = min ((size_t) 126, strlen (s->s));
|
||||||
memset (buf + 2, 0, 2 * len); /* zero all the bytes */
|
len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
|
||||||
len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
|
(wchar_t *) &buf[2], 126);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
buf [0] = (len + 1) * 2;
|
buf [0] = (len + 1) * 2;
|
||||||
|
|
Loading…
Reference in a new issue