diff options
author | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-25 21:23:52 +0000 |
---|---|---|
committer | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-25 21:23:52 +0000 |
commit | 5872753e2dbdca5b252470c5210cdf54ee1788dd (patch) | |
tree | 4ef919205c8cf5a1864a9fe24a3a6783cb563e2e /firmware/scripts/usbstring.c | |
parent | 6b13ecdab08a28deadb4e947cbab740d02352617 (diff) |
- Include tool for Converting ASCII to UTF-16LE in C-Header
- Build UTF-16LE USB String descriptors from ASCII File
- Introduce USB String Descriptor to DFU and runtime firmware
git-svn-id: https://svn.openpcd.org:2342/trunk@227 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware/scripts/usbstring.c')
-rw-r--r-- | firmware/scripts/usbstring.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/firmware/scripts/usbstring.c b/firmware/scripts/usbstring.c new file mode 100644 index 0000000..5348e66 --- /dev/null +++ b/firmware/scripts/usbstring.c @@ -0,0 +1,197 @@ +/* AT91SAM7 USB string descriptor builder + * (C) 2006 by Harald Welte <laforge@gnumonks.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Based on existing utf8_to_utf16le() function, + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> + +static int utf8_to_utf16le(const char *s, u_int16_t *cp, unsigned len) +{ + int count = 0; + u_int8_t c; + u_int16_t 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 = (u_int8_t) *s++) != 0) { + if (c & 0x80) { + // 2-byte sequence: + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx + if ((c & 0xe0) == 0xc0) { + uchar = (c & 0x1f) << 6; + + c = (u_int8_t) *s++; + if ((c & 0xc0) != 0xc0) + 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 = (u_int8_t) *s++; + if ((c & 0xc0) != 0xc0) + goto fail; + c &= 0x3f; + uchar |= c << 6; + + c = (u_int8_t) *s++; + if ((c & 0xc0) != 0xc0) + 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; + + *cp++ = uchar; + count++; + len--; + } + return count; +fail: + return -1; +} + +#define COLUMNS 6 +static int print_array16(u_int16_t *buf, int len) +{ + int i; + for (i = 0; i < len; i++) { + int mod = i % COLUMNS; + char *suffix; + char *prefix; + + switch (mod) { + case 0: + if (i == 0) + prefix = "\t"; + else + prefix= "\t\t\t"; + suffix = ", "; + break; + case COLUMNS-1: + prefix = ""; + suffix = ",\n"; + break; + default: + prefix = ""; + suffix = ", "; + break; + } + + printf("%s0x%04x%s", prefix, buf[i], suffix); + } +} + +static void print_structhdr(int i, int size) +{ + printf( "static const struct {\n" + "\tstruct usb_descriptor_header hdr;\n" + "\tu_int16_t wData[];\n" + "} __attribute__((packed)) string%d = {\n" + "\t.hdr = {\n" + "\t\t.bLength = sizeof(struct usb_descriptor_header) + %u * sizeof(u_int16_t),\n" + "\t\t.bDescriptorType = USB_DT_STRING,\n" + "\t},\n" + "\t.wData = {", i, size); +} +static void print_structftr(void) +{ + printf("},\n};\n\n"); +} + +int main(int argc, char **argv) +{ + char asciibuf[512+1]; + u_int16_t utf16buf[1024+1]; + int len; + int j, i = 1; + + printf("#ifndef _USB_STRINGS_H\n#define _USB_STRINGS_H\n\n"); + printf("/* THIS FILE IS AUTOGENERATED, DO NOT MODIFY MANUALLY */\n\n"); + printf("#include <usb_ch9.h>\n"); + printf("#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))\n\n"); + + print_structhdr(0, 1); + printf("0x0409 /* English */ "); + print_structftr(); +#if 0 + printf("static const struct usb_string_descriptor string0 = {\n" + "\t.bLength = sizeof(string0) + 1 * sizeof(u_int16_t),\n" + "\t.bDescriptorType = USB_DT_STRING,\n" + "\t.wData[0] = 0x0409, /* English */\n" + "};\n\n"); +#endif + + while (scanf("%512[^\n]\n", asciibuf) != EOF) { + len = strlen(asciibuf); + printf("/* String %u \"%s\" */\n", i, asciibuf); + + /* FIXME: check return value */ + utf8_to_utf16le(asciibuf, utf16buf, len); + + print_structhdr(i, len); +#if 0 + printf("static const struct usb_string_descriptor string%d = {\n" + "\t.bLength = sizeof(string%d) + %d * sizeof(u_int16_t),\n" + "\t.bDescriptorType = USB_DT_STRING,\n" + "\t.wData = {", i, i, len); +#endif + + print_array16(utf16buf, len); + + print_structftr(); +#if 0 + printf("},\n};\n\n"); +#endif + + i++; + } + + printf("static const struct usb_descriptor_header *usb_strings[] = {\n"); + for (j = 0; j < i; j++) + printf("\t(struct usb_descriptor_header *) &string%d,\n", j); + printf("};\n\n"); + printf("#endif /* _USB_STRINGS_H */\n"); +} |