1 /* 2 * Copyright (C) 2003 David Brownell 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published 6 * by the Free Software Foundation; either version 2.1 of the License, or 7 * (at your option) any later version. 8 */ 9 10 #include <linux/errno.h> 11 #include <linux/kernel.h> 12 #include <linux/list.h> 13 #include <linux/string.h> 14 #include <linux/device.h> 15 #include <linux/init.h> 16 17 #include <linux/usb/ch9.h> 18 #include <linux/usb/gadget.h> 19 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) != 0xc0) 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) != 0xc0) 53 goto fail; 54 c &= 0x3f; 55 uchar |= c << 6; 56 57 c = (u8) *s++; 58 if ((c & 0xc0) != 0xc0) 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 87 /** 88 * usb_gadget_get_string - fill out a string descriptor 89 * @table: of c strings encoded using UTF-8 90 * @id: string id, from low byte of wValue in get string descriptor 91 * @buf: at least 256 bytes 92 * 93 * Finds the UTF-8 string matching the ID, and converts it into a 94 * string descriptor in utf16-le. 95 * Returns length of descriptor (always even) or negative errno 96 * 97 * If your driver needs stings in multiple languages, you'll probably 98 * "switch (wIndex) { ... }" in your ep0 string descriptor logic, 99 * using this routine after choosing which set of UTF-8 strings to use. 100 * Note that US-ASCII is a strict subset of UTF-8; any string bytes with 101 * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 102 * characters (which are also widely used in C strings). 103 */ 104 int 105 usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) 106 { 107 struct usb_string *s; 108 int len; 109 110 /* descriptor 0 has the language id */ 111 if (id == 0) { 112 buf [0] = 4; 113 buf [1] = USB_DT_STRING; 114 buf [2] = (u8) table->language; 115 buf [3] = (u8) (table->language >> 8); 116 return 4; 117 } 118 for (s = table->strings; s && s->s; s++) 119 if (s->id == id) 120 break; 121 122 /* unrecognized: stall. */ 123 if (!s || !s->s) 124 return -EINVAL; 125 126 /* string descriptors have length, tag, then UTF16-LE text */ 127 len = min ((size_t) 126, strlen (s->s)); 128 memset (buf + 2, 0, 2 * len); /* zero all the bytes */ 129 len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len); 130 if (len < 0) 131 return -EINVAL; 132 buf [0] = (len + 1) * 2; 133 buf [1] = USB_DT_STRING; 134 return buf [0]; 135 } 136 137