@@ -89,6 +89,9 @@ Adafruit_USBD_Device::Adafruit_USBD_Device(void)
8989 _desc_cfglen = sizeof (tusb_desc_configuration_t );
9090 _itf_count = 0 ;
9191 _epin_count = _epout_count = 1 ;
92+
93+ _manufacturer = USB_MANUFACTURER;
94+ _product = USB_PRODUCT;
9295}
9396
9497// Add interface descriptor
@@ -149,6 +152,16 @@ void Adafruit_USBD_Device::setVersion(uint16_t bcd)
149152 _desc_device.bcdUSB = bcd;
150153}
151154
155+ void Adafruit_USBD_Device::setManufacturer (const char *s)
156+ {
157+ _manufacturer = s;
158+ }
159+
160+ void Adafruit_USBD_Device::setProduct (const char *s)
161+ {
162+ _product = s;
163+ }
164+
152165bool Adafruit_USBD_Device::begin (void )
153166{
154167 return true ;
@@ -172,6 +185,85 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
172185 return USBDevice._desc_cfg ;
173186}
174187
188+
189+ static int utf8_to_unichar (const char *str8, int *unicharp)
190+ {
191+ int unichar;
192+ int len;
193+
194+ if (str8[0 ] < 0x80 )
195+ len = 1 ;
196+ else if ((str8[0 ] & 0xe0 ) == 0xc0 )
197+ len = 2 ;
198+ else if ((str8[0 ] & 0xf0 ) == 0xe0 )
199+ len = 3 ;
200+ else if ((str8[0 ] & 0xf8 ) == 0xf0 )
201+ len = 4 ;
202+ else if ((str8[0 ] & 0xfc ) == 0xf8 )
203+ len = 5 ;
204+ else if ((str8[0 ] & 0xfe ) == 0xfc )
205+ len = 6 ;
206+ else
207+ return -1 ;
208+
209+ switch (len) {
210+ case 1 :
211+ unichar = str8[0 ];
212+ break ;
213+ case 2 :
214+ unichar = str8[0 ] & 0x1f ;
215+ break ;
216+ case 3 :
217+ unichar = str8[0 ] & 0x0f ;
218+ break ;
219+ case 4 :
220+ unichar = str8[0 ] & 0x07 ;
221+ break ;
222+ case 5 :
223+ unichar = str8[0 ] & 0x03 ;
224+ break ;
225+ case 6 :
226+ unichar = str8[0 ] & 0x01 ;
227+ break ;
228+ }
229+
230+ for (int i = 1 ; i < len; i++) {
231+ if ((str8[i] & 0xc0 ) != 0x80 )
232+ return -1 ;
233+ unichar <<= 6 ;
234+ unichar |= str8[i] & 0x3f ;
235+ }
236+
237+ *unicharp = unichar;
238+ return len;
239+ }
240+
241+ // Simple UCS-2/16-bit coversion, which handles the Basic Multilingual Plane
242+ static int strcpy_uni16 (const char *s, uint16_t *buf, int bufsize) {
243+ int i = 0 ;
244+ int buflen = 0 ;
245+
246+ while (i < bufsize) {
247+ int unichar;
248+ int utf8len = utf8_to_unichar (s + i, &unichar);
249+
250+ if (utf8len < 0 ) {
251+ // Invalid utf8 sequence, skip it
252+ i++;
253+ continue ;
254+ }
255+
256+ i += utf8len;
257+
258+ // If the codepoint is larger than 16 bit, skip it
259+ if (unichar <= 0xffff )
260+ buf[buflen++] = unichar;
261+ }
262+
263+ buf[buflen] = ' \0 ' ;
264+ return buflen;
265+ }
266+
175267// up to 32 unicode characters (header make it 33)
176268static uint16_t _desc_str[33 ];
177269
@@ -189,20 +281,12 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
189281 chr_count = 1 ;
190282 break ;
191283
192- case 1 : // Manufacturer
193- case 2 : // Product
194- {
195- char const * str = (index == 1 ) ? USB_MANUFACTURER : USB_PRODUCT;
196-
197- // cap at max char
198- chr_count = strlen (str);
199- if ( chr_count > 32 ) chr_count = 32 ;
284+ case 1 :
285+ chr_count = strcpy_uni16 (USBDevice.getManufacturer (), _desc_str + 1 , 32 );
286+ break ;
200287
201- for (uint8_t i=0 ; i<chr_count; i++)
202- {
203- _desc_str[1 +i] = str[i];
204- }
205- }
288+ case 2 :
289+ chr_count = strcpy_uni16 (USBDevice.getProduct (), _desc_str + 1 , 32 );
206290 break ;
207291
208292 case 3 :
0 commit comments