Skip to content

Commit 55b4d3c

Browse files
committed
added Adafruit_USBDevice based on tinyusb
- added Adafruit_USBInterface - remove setLoopStacksize - move usb code around
1 parent 85eb9a5 commit 55b4d3c

File tree

20 files changed

+354
-220
lines changed

20 files changed

+354
-220
lines changed

cores/nRF5/Arduino.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ void setup( void ) ;
3636
void loop( void ) ;
3737

3838
void suspendLoop(void);
39-
uint32_t setLoopStacksize(void);
4039

4140
#include "WVariant.h"
4241

@@ -70,11 +69,10 @@ uint32_t setLoopStacksize(void);
7069

7170
#ifdef NRF52840_XXAA
7271
#include "tusb.h"
73-
7472
#ifdef __cplusplus
73+
#include "Adafruit_USBDevice.h"
7574
#include "USBSerial.h"
7675
#endif
77-
7876
#endif
7977

8078
// Include board variant

cores/nRF5/main.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616
#define ARDUINO_MAIN
1717
#include "Arduino.h"
1818

19+
#include "usb.h"
20+
21+
/* USB VID/PID if not defined, tinyusb to use default value
22+
* Note: different class combination e.g CDC and (CDC + MSC) should have different
23+
* PID since Host OS will "remembered" device driver after the first plug */
24+
#define USB_VID 0x239A
25+
#define USB_PID 0x8029
26+
1927
// DEBUG Level 1
2028
#if CFG_DEBUG
2129
// weak function to avoid compilation error with
@@ -37,9 +45,8 @@ static TaskHandle_t _loopHandle;
3745
void initVariant() __attribute__((weak));
3846
void initVariant() { }
3947

40-
uint32_t _loopStacksize = 512*3;
41-
42-
uint32_t setLoopStacksize(void) __attribute__ ((weak));
48+
#define LOOP_STACK_SZ (512*3)
49+
#define USBD_STACK_SZ (150)
4350

4451
static void loop_task(void* arg)
4552
{
@@ -68,25 +75,41 @@ static void loop_task(void* arg)
6875
}
6976
}
7077

71-
/*
72-
* \brief Main entry point of Arduino application
73-
*/
78+
// USB Device Driver task
79+
// This top level thread process all usb events and invoke callbacks
80+
static void usb_device_task(void* param)
81+
{
82+
(void) param;
83+
84+
// RTOS forever loop
85+
while (1)
86+
{
87+
// tinyusb device task
88+
tud_task();
89+
}
90+
}
91+
92+
// \brief Main entry point of Arduino application
7493
int main( void )
7594
{
7695
init();
7796
initVariant();
7897

79-
if (setLoopStacksize)
80-
{
81-
_loopStacksize = setLoopStacksize();
82-
}
98+
#ifdef NRF52840_XXAA
99+
USBDevice.addInterface( (Adafruit_USBInterface&) Serial);
100+
USBDevice.begin(USB_VID, USB_PID);
101+
usb_init();
102+
103+
// Create a task for tinyusb device stack
104+
xTaskCreate( usb_device_task, "usbd", USBD_STACK_SZ, NULL, TASK_PRIO_HIGH, NULL);
105+
#endif
83106

84107
#if CFG_DEBUG >= 3
85108
SEGGER_SYSVIEW_Conf();
86109
#endif
87110

88111
// Create a task for loop()
89-
xTaskCreate( loop_task, "loop", _loopStacksize, NULL, TASK_PRIO_LOW, &_loopHandle);
112+
xTaskCreate( loop_task, "loop", LOOP_STACK_SZ, NULL, TASK_PRIO_LOW, &_loopHandle);
90113

91114
// Initialize callback task
92115
ada_callback_init();

cores/nRF5/usb/Adafruit_USBDevice.cpp

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2019 hathach for Adafruit Industries
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#ifdef NRF52840_XXAA
26+
27+
#include "Adafruit_USBDevice.h"
28+
29+
extern "C"
30+
{
31+
extern uint16_t usb_desc_str_serial[1+16];
32+
33+
// array of pointer to string descriptors
34+
uint16_t const * const string_desc_arr [] =
35+
{
36+
// 0: is supported language = English
37+
TUD_DESC_STRCONV(0x0409),
38+
39+
// 1: Manufacturer
40+
TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'),
41+
42+
// 2: Product
43+
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','n','R','F','5','2','8','4','0'),
44+
45+
// 3: Serials
46+
usb_desc_str_serial,
47+
48+
// // 4: CDC Interface
49+
// TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'),
50+
//
51+
// // 5: MSC Interface
52+
// TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','U','F','2'),
53+
};
54+
55+
// tud_desc_set is required by tinyusb stack
56+
// since CFG_TUD_DESC_AUTO is enabled, we only need to set string_arr
57+
tud_desc_set_t tud_desc_set =
58+
{
59+
.device = NULL,
60+
.config = NULL,
61+
.string_arr = (uint8_t const **) string_desc_arr,
62+
.string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
63+
64+
.hid_report =
65+
{
66+
.generic = NULL,
67+
.boot_keyboard = NULL,
68+
.boot_mouse = NULL
69+
}
70+
};
71+
72+
} // extern C
73+
74+
Adafruit_USBDevice USBDevice;
75+
76+
Adafruit_USBDevice::Adafruit_USBDevice(void)
77+
{
78+
tusb_desc_device_t desc_dev =
79+
{
80+
.bLength = sizeof(tusb_desc_device_t),
81+
.bDescriptorType = TUSB_DESC_DEVICE,
82+
.bcdUSB = 0x0200,
83+
84+
#if CFG_TUD_CDC
85+
// Use Interface Association Descriptor (IAD) for CDC
86+
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
87+
.bDeviceClass = TUSB_CLASS_MISC,
88+
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
89+
.bDeviceProtocol = MISC_PROTOCOL_IAD,
90+
#else
91+
.bDeviceClass = 0x00,
92+
.bDeviceSubClass = 0x00,
93+
.bDeviceProtocol = 0x00,
94+
#endif
95+
96+
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
97+
98+
.idVendor = 0,
99+
.idProduct = 0,
100+
.bcdDevice = 0x0100,
101+
102+
.iManufacturer = 0x01,
103+
.iProduct = 0x02,
104+
.iSerialNumber = 0x03,
105+
106+
.bNumConfigurations = 0x01
107+
};
108+
109+
_desc_device = desc_dev;
110+
111+
tusb_desc_configuration_t dev_cfg =
112+
{
113+
.bLength = sizeof(tusb_desc_configuration_t),
114+
.bDescriptorType = TUSB_DESC_CONFIGURATION,
115+
116+
// Total Length & Interface Number will be updated later
117+
.wTotalLength = 0,
118+
.bNumInterfaces = 0,
119+
120+
.bConfigurationValue = 1,
121+
.iConfiguration = 0x00,
122+
.bmAttributes = TU_BIT(7) | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP,
123+
.bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100)
124+
};
125+
126+
memcpy(_desc_cfg, &dev_cfg, sizeof(tusb_desc_configuration_t));
127+
128+
_desc_cfglen = sizeof(tusb_desc_configuration_t);
129+
_itf_count = 0;
130+
131+
tud_desc_set.config = _desc_cfg;
132+
tud_desc_set.device = &_desc_device;
133+
}
134+
135+
// Add interface descriptor, interface number will be updated to match current count
136+
bool Adafruit_USBDevice::addInterface(Adafruit_USBInterface& itf)
137+
{
138+
uint8_t* desc = _desc_cfg+_desc_cfglen;
139+
uint16_t len = itf.getDescriptor(desc, sizeof(_desc_cfg)-_desc_cfglen);
140+
141+
uint8_t* desc_end = desc+len;
142+
143+
// Handle IAD
144+
if ( desc[1] == TUSB_DESC_INTERFACE_ASSOCIATION )
145+
{
146+
// update starting interface
147+
((tusb_desc_interface_assoc_t*) desc)->bFirstInterface = _itf_count;
148+
149+
desc += desc[0]; // next
150+
}
151+
152+
while (desc < desc_end)
153+
{
154+
if (desc[1] == TUSB_DESC_INTERFACE)
155+
{
156+
// No alternate interface support
157+
((tusb_desc_interface_t*) desc)->bInterfaceNumber = _itf_count++;
158+
}
159+
160+
if (desc[0] == 0) return false;
161+
desc += desc[0]; // next
162+
}
163+
164+
_desc_cfglen += len;
165+
166+
// Update config descriptor
167+
tusb_desc_configuration_t* config = (tusb_desc_configuration_t*)_desc_cfg;
168+
config->wTotalLength = _desc_cfglen;
169+
config->bNumInterfaces = _itf_count;
170+
171+
return true;
172+
}
173+
174+
bool Adafruit_USBDevice::begin(uint16_t vid, uint16_t pid)
175+
{
176+
_desc_device.idVendor = vid;
177+
_desc_device.idProduct = pid;
178+
}
179+
180+
#endif

cores/nRF5/usb/Adafruit_USBDevice.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2019 hathach for Adafruit Industries
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#ifndef ADAFRUIT_USBDEVICE_H_
26+
#define ADAFRUIT_USBDEVICE_H_
27+
28+
#include "tusb.h"
29+
30+
class Adafruit_USBInterface
31+
{
32+
public:
33+
virtual uint16_t getDescriptor(uint8_t* buf, uint16_t bufsize) = 0;
34+
};
35+
36+
class Adafruit_USBDevice
37+
{
38+
private:
39+
tusb_desc_device_t _desc_device;
40+
41+
uint8_t _desc_cfg[256];
42+
uint16_t _desc_cfglen;
43+
44+
uint8_t _itf_count;
45+
46+
public:
47+
Adafruit_USBDevice(void);
48+
49+
bool addInterface(Adafruit_USBInterface& itf);
50+
51+
bool begin(uint16_t vid, uint16_t pid);
52+
};
53+
54+
extern Adafruit_USBDevice USBDevice;
55+
56+
#endif /* ADAFRUIT_USBDEVICE_H_ */

cores/nRF5/usb/USBSerial.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,26 @@
2727
#include "Arduino.h"
2828
#include "tusb.h"
2929

30-
3130
USBSerial Serial;
3231

3332
USBSerial::USBSerial(void)
3433
{
3534

3635
}
3736

37+
uint16_t USBSerial::getDescriptor(uint8_t* buf, uint16_t bufsize)
38+
{
39+
// CDC is mostly always existed for DFU
40+
// Let's pick EP 1 & 2 for it
41+
uint8_t desc[] = { TUD_CDC_DESCRIPTOR(0, 0, 0x81, 8, 0x02, 0x82, 64) };
42+
uint16_t const len = sizeof(desc);
43+
44+
if ( bufsize < len ) return 0;
45+
46+
memcpy(buf, desc, len);
47+
return len;
48+
}
49+
3850
// Baud and config is ignore in CDC
3951
void USBSerial::begin (uint32_t baud)
4052
{

cores/nRF5/usb/USBSerial.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@
2727

2828
#ifdef NRF52840_XXAA
2929

30+
#include "Adafruit_USBDevice.h"
3031
#include "Stream.h"
3132

32-
class USBSerial : public Stream
33+
class USBSerial : public Stream, Adafruit_USBInterface
3334
{
3435
public:
3536
USBSerial(void);
3637

38+
// fron Adafruit_USBInterface
39+
virtual uint16_t getDescriptor(uint8_t* buf, uint16_t bufsize);
40+
3741
void setPins(uint8_t pin_rx, uint8_t pin_tx) { (void) pin_rx; (void) pin_tx; }
3842
void begin(uint32_t baud_count);
3943
void begin(uint32_t baud, uint8_t config);

0 commit comments

Comments
 (0)