1 // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "esp_log.h"
16 #include "descriptors_control.h"
17 
18 static const char *TAG = "tusb_desc";
19 static tusb_desc_device_t s_descriptor;
20 static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
21 #define MAX_DESC_BUF_SIZE 32
22 
23 #if CFG_TUD_HID //HID Report Descriptor
24 uint8_t const desc_hid_report[] = {
25     TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
26     TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE), )
27 };
28 #endif
29 
30 uint8_t const desc_configuration[] = {
31     // interface count, string index, total length, attribute, power in mA
32     TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
33 
34 #   if CFG_TUD_CDC
35     // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
36     TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64),
37 #   endif
38 #   if CFG_TUD_MSC
39     // Interface number, string index, EP Out & EP In address, EP size
40     TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
41 #   endif
42 #   if CFG_TUD_HID
43     // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
44     TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10)
45 #   endif
46 };
47 
48 // =============================================================================
49 // CALLBACKS
50 // =============================================================================
51 
52 /**
53  * @brief Invoked when received GET DEVICE DESCRIPTOR.
54  * Application returns pointer to descriptor
55  *
56  * @return uint8_t const*
57  */
tud_descriptor_device_cb(void)58 uint8_t const *tud_descriptor_device_cb(void)
59 {
60     return (uint8_t const *)&s_descriptor;
61 }
62 
63 /**
64  * @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
65  * Descriptor contents must exist long enough for transfer to complete
66  *
67  * @param index
68  * @return uint8_t const* Application return pointer to descriptor
69  */
tud_descriptor_configuration_cb(uint8_t index)70 uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
71 {
72     (void)index; // for multiple configurations
73     return desc_configuration;
74 }
75 
76 static uint16_t _desc_str[MAX_DESC_BUF_SIZE];
77 
78 // Invoked when received GET STRING DESCRIPTOR request
79 // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
tud_descriptor_string_cb(uint8_t index,uint16_t langid)80 uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
81 {
82     (void) langid;
83 
84     uint8_t chr_count;
85 
86     if ( index == 0) {
87         memcpy(&_desc_str[1], s_str_descriptor[0], 2);
88         chr_count = 1;
89     } else {
90         // Convert ASCII string into UTF-16
91 
92         if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) {
93             return NULL;
94         }
95 
96         const char *str = s_str_descriptor[index];
97 
98         // Cap at max char
99         chr_count = strlen(str);
100         if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) {
101             chr_count = MAX_DESC_BUF_SIZE - 1;
102         }
103 
104         for (uint8_t i = 0; i < chr_count; i++) {
105             _desc_str[1 + i] = str[i];
106         }
107     }
108 
109     // first byte is length (including header), second byte is string type
110     _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2);
111 
112     return _desc_str;
113 }
114 
115 /**
116  * @brief Invoked when received GET HID REPORT DESCRIPTOR
117  * Application returns pointer to descriptor. Descriptor contents must exist
118  * long enough for transfer to complete
119  *
120  * @return uint8_t const*
121  */
122 #if CFG_TUD_HID
tud_hid_descriptor_report_cb(void)123 uint8_t const *tud_hid_descriptor_report_cb(void)
124 {
125     return desc_hid_report;
126 }
127 #endif
128 
129 // =============================================================================
130 // Driver functions
131 // =============================================================================
132 
tusb_set_descriptor(tusb_desc_device_t * dev_desc,const char ** str_desc)133 void tusb_set_descriptor(tusb_desc_device_t *dev_desc, const char **str_desc)
134 {
135     ESP_LOGI(TAG, "\n"
136              "┌─────────────────────────────────┐\n"
137              "│  USB Device Descriptor Summary  │\n"
138              "├───────────────────┬─────────────┤\n"
139              "│bDeviceClass       │ %-4u        │\n"
140              "├───────────────────┼─────────────┤\n"
141              "│bDeviceSubClass    │ %-4u        │\n"
142              "├───────────────────┼─────────────┤\n"
143              "│bDeviceProtocol    │ %-4u        │\n"
144              "├───────────────────┼─────────────┤\n"
145              "│bMaxPacketSize0    │ %-4u        │\n"
146              "├───────────────────┼─────────────┤\n"
147              "│idVendor           │ %-#10x  │\n"
148              "├───────────────────┼─────────────┤\n"
149              "│idProduct          │ %-#10x  │\n"
150              "├───────────────────┼─────────────┤\n"
151              "│bcdDevice          │ %-#10x  │\n"
152              "├───────────────────┼─────────────┤\n"
153              "│iManufacturer      │ %-#10x  │\n"
154              "├───────────────────┼─────────────┤\n"
155              "│iProduct           │ %-#10x  │\n"
156              "├───────────────────┼─────────────┤\n"
157              "│iSerialNumber      │ %-#10x  │\n"
158              "├───────────────────┼─────────────┤\n"
159              "│bNumConfigurations │ %-#10x  │\n"
160              "└───────────────────┴─────────────┘",
161              dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
162              dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0,
163              dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice,
164              dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber,
165              dev_desc->bNumConfigurations);
166     s_descriptor = *dev_desc;
167 
168     if (str_desc != NULL) {
169         memcpy(s_str_descriptor, str_desc,
170                sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE);
171     }
172     tusb_desc_set = true;
173 }
174 
tusb_get_active_desc(void)175 tusb_desc_device_t *tusb_get_active_desc(void)
176 {
177     return &s_descriptor;
178 }
179 
tusb_get_active_str_desc(void)180 char **tusb_get_active_str_desc(void)
181 {
182     return s_str_descriptor;
183 }
184 
tusb_clear_descriptor(void)185 void tusb_clear_descriptor(void)
186 {
187     memset(&s_descriptor, 0, sizeof(s_descriptor));
188     memset(&s_str_descriptor, 0, sizeof(s_str_descriptor));
189     tusb_desc_set = false;
190 }
191