common: Implement Time::fmt_time().
[gps-watch.git] / src / common / usb_device_descriptor.c
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  * 
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  *  that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  *   of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  *   list of conditions and the following disclaimer in the documentation and/or
16  *   other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  *   contributors may be used to endorse or promote products derived from this
20  *   software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include "usb_device_config.h"
35 #include "usb.h"
36 #include "usb_device.h"
37
38 #include "usb_device_cdc_acm.h"
39
40 #include "usb_device_descriptor.h"
41
42 /*******************************************************************************
43 * Variables
44 ******************************************************************************/
45 uint8_t g_currentConfigure = 0;
46 uint8_t g_interface[USB_CDC_VCOM_INTERFACE_COUNT];
47
48 /* Define device descriptor */
49 uint8_t g_UsbDeviceDescriptor[USB_DESCRIPTOR_LENGTH_DEVICE] = {
50     /* Size of this descriptor in bytes */
51     USB_DESCRIPTOR_LENGTH_DEVICE,
52     /* DEVICE Descriptor Type */
53     USB_DESCRIPTOR_TYPE_DEVICE,
54     /* USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). */
55     USB_SHORT_GET_LOW(USB_DEVICE_SPECIFIC_BCD_VERSION), USB_SHORT_GET_HIGH(USB_DEVICE_SPECIFIC_BCD_VERSION),
56     /* Class code (assigned by the USB-IF). */
57     USB_DEVICE_CLASS,
58     /* Subclass code (assigned by the USB-IF). */
59     USB_DEVICE_SUBCLASS,
60     /* Protocol code (assigned by the USB-IF). */
61     USB_DEVICE_PROTOCOL,
62     /* Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid) */
63     USB_CONTROL_MAX_PACKET_SIZE,
64     /* Vendor ID (assigned by the USB-IF) */
65     0x00, 0x00,
66     /* Product ID (assigned by the manufacturer) */
67     0x00, 0x00,
68     /* Device release number in binary-coded decimal */
69     USB_SHORT_GET_LOW(USB_DEVICE_DEMO_BCD_VERSION), USB_SHORT_GET_HIGH(USB_DEVICE_DEMO_BCD_VERSION),
70     /* Index of string descriptor describing manufacturer */
71     0x01,
72     /* Index of string descriptor describing product */
73     0x02,
74     /* Index of string descriptor describing the device's serial number */
75     0x00,
76     /* Number of possible configurations */
77     USB_DEVICE_CONFIGURATION_COUNT,
78 };
79
80 /* Define configuration descriptor */
81 uint8_t g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL] = {
82     /* Size of this descriptor in bytes */
83     USB_DESCRIPTOR_LENGTH_CONFIGURE,
84     /* CONFIGURATION Descriptor Type */
85     USB_DESCRIPTOR_TYPE_CONFIGURE,
86     /* Total length of data returned for this configuration. */
87     USB_SHORT_GET_LOW(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),
88     USB_SHORT_GET_HIGH(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),
89     /* Number of interfaces supported by this configuration */
90     USB_CDC_VCOM_INTERFACE_COUNT,
91     /* Value to use as an argument to the SetConfiguration() request to select this configuration */
92     USB_CDC_VCOM_CONFIGURE_INDEX,
93     /* Index of string descriptor describing this configuration */
94     0,
95     /* Configuration characteristics D7: Reserved (set to one) D6: Self-powered D5: Remote Wakeup D4...0: Reserved
96        (reset to zero) */
97     (USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK) |
98         (USB_DEVICE_CONFIG_SELF_POWER << USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT) |
99         (USB_DEVICE_CONFIG_REMOTE_WAKEUP << USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT),
100     /* Maximum power consumption of the USB * device from the bus in this specific * configuration when the device is
101        fully * operational. Expressed in 2 mA units *  (i.e., 50 = 100 mA).  */
102     USB_DEVICE_MAX_POWER,
103
104     /* Communication Interface Descriptor */
105     USB_DESCRIPTOR_LENGTH_INTERFACE, USB_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_VCOM_COMM_INTERFACE_INDEX, 0x00,
106     USB_CDC_VCOM_ENDPOINT_CIC_COUNT, USB_CDC_VCOM_CIC_CLASS, USB_CDC_VCOM_CIC_SUBCLASS, USB_CDC_VCOM_CIC_PROTOCOL,
107     0x00, /* Interface Description String Index*/
108
109     /* CDC Class-Specific descriptor */
110     USB_DESCRIPTOR_LENGTH_CDC_HEADER_FUNC, /* Size of this descriptor in bytes */
111     USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE,  /* CS_INTERFACE Descriptor Type */
112     USB_CDC_HEADER_FUNC_DESC, 0x10,
113     0x01, /* USB Class Definitions for Communications the Communication specification version 1.10 */
114
115     USB_DESCRIPTOR_LENGTH_CDC_CALL_MANAG, /* Size of this descriptor in bytes */
116     USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */
117     USB_CDC_CALL_MANAGEMENT_FUNC_DESC,
118     0x01, /*Bit 0: Whether device handle call management itself 1, Bit 1: Whether device can send/receive call
119              management information over a Data Class Interface 0 */
120     0x01, /* Indicates multiplexed commands are handled via data interface */
121
122     USB_DESCRIPTOR_LENGTH_CDC_ABSTRACT,   /* Size of this descriptor in bytes */
123     USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */
124     USB_CDC_ABSTRACT_CONTROL_FUNC_DESC,
125     0x06, /* Bit 0: Whether device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and
126              Get_Comm_Feature 0, Bit 1: Whether device supports the request combination of Set_Line_Coding,
127              Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State 1, Bit ...  */
128
129     USB_DESCRIPTOR_LENGTH_CDC_UNION_FUNC, /* Size of this descriptor in bytes */
130     USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */
131     USB_CDC_UNION_FUNC_DESC, 0x00,        /* The interface number of the Communications or Data Class interface  */
132     0x01,                                 /* Interface number of subordinate interface in the Union  */
133
134     /*Notification Endpoint descriptor */
135     USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT | (USB_IN << 7U),
136     USB_ENDPOINT_INTERRUPT, USB_SHORT_GET_LOW(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE),
137     USB_SHORT_GET_HIGH(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE), FS_CDC_VCOM_INTERRUPT_IN_INTERVAL,
138
139     /* Data Interface Descriptor */
140     USB_DESCRIPTOR_LENGTH_INTERFACE, USB_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_VCOM_DATA_INTERFACE_INDEX, 0x00,
141     USB_CDC_VCOM_ENDPOINT_DIC_COUNT, USB_CDC_VCOM_DIC_CLASS, USB_CDC_VCOM_DIC_SUBCLASS, USB_CDC_VCOM_DIC_PROTOCOL,
142     0x00, /* Interface Description String Index*/
143
144     /*Bulk IN Endpoint descriptor */
145     USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << 7U),
146     USB_ENDPOINT_BULK, USB_SHORT_GET_LOW(FS_CDC_VCOM_BULK_IN_PACKET_SIZE),
147     USB_SHORT_GET_HIGH(FS_CDC_VCOM_BULK_IN_PACKET_SIZE), 0x00, /* The polling interval value is every 0 Frames */
148
149     /*Bulk OUT Endpoint descriptor */
150     USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << 7U),
151     USB_ENDPOINT_BULK, USB_SHORT_GET_LOW(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE),
152     USB_SHORT_GET_HIGH(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE), 0x00, /* The polling interval value is every 0 Frames */
153 };
154
155 /* Define string descriptor */
156 uint8_t g_UsbDeviceString0[USB_DESCRIPTOR_LENGTH_STRING0] = {sizeof(g_UsbDeviceString0), USB_DESCRIPTOR_TYPE_STRING,
157                                                              0x09, 0x04};
158
159 uint8_t g_UsbDeviceString1[USB_DESCRIPTOR_LENGTH_STRING1] = {
160     sizeof(g_UsbDeviceString1),
161     USB_DESCRIPTOR_TYPE_STRING,
162     'N',
163     0x00U,
164     'X',
165     0x00U,
166     'P',
167     0x00U,
168     ' ',
169     0x00U,
170     'S',
171     0x00U,
172     'E',
173     0x00U,
174     'M',
175     0x00U,
176     'I',
177     0x00U,
178     'C',
179     0x00U,
180     'O',
181     0x00U,
182     'N',
183     0x00U,
184     'D',
185     0x00U,
186     'U',
187     0x00U,
188     'C',
189     0x00U,
190     'T',
191     0x00U,
192     'O',
193     0x00U,
194     'R',
195     0x00U,
196     'S',
197     0x00U,
198 };
199
200 uint8_t g_UsbDeviceString2[USB_DESCRIPTOR_LENGTH_STRING2] = {sizeof(g_UsbDeviceString2),
201                                                              USB_DESCRIPTOR_TYPE_STRING,
202                                                              'M',
203                                                              0,
204                                                              'C',
205                                                              0,
206                                                              'U',
207                                                              0,
208                                                              ' ',
209                                                              0,
210                                                              'V',
211                                                              0,
212                                                              'I',
213                                                              0,
214                                                              'R',
215                                                              0,
216                                                              'T',
217                                                              0,
218                                                              'U',
219                                                              0,
220                                                              'A',
221                                                              0,
222                                                              'L',
223                                                              0,
224                                                              ' ',
225                                                              0,
226                                                              'C',
227                                                              0,
228                                                              'O',
229                                                              0,
230                                                              'M',
231                                                              0,
232                                                              ' ',
233                                                              0,
234                                                              'D',
235                                                              0,
236                                                              'E',
237                                                              0,
238                                                              'M',
239                                                              0,
240                                                              'O',
241                                                              0};
242
243 uint8_t *g_UsbDeviceStringDescriptorArray[USB_DEVICE_STRING_COUNT] = {g_UsbDeviceString0, g_UsbDeviceString1,
244                                                                       g_UsbDeviceString2};
245
246 /* Define string descriptor size */
247 uint32_t g_UsbDeviceStringDescriptorLength[USB_DEVICE_STRING_COUNT] = {
248     sizeof(g_UsbDeviceString0), sizeof(g_UsbDeviceString1), sizeof(g_UsbDeviceString2)};
249 usb_language_t g_UsbDeviceLanguage[USB_DEVICE_LANGUAGE_COUNT] = {{
250     g_UsbDeviceStringDescriptorArray, g_UsbDeviceStringDescriptorLength, (uint16_t)0x0409,
251 }};
252
253 usb_language_list_t g_UsbDeviceLanguageList = {
254     g_UsbDeviceString0, sizeof(g_UsbDeviceString0), g_UsbDeviceLanguage, USB_DEVICE_LANGUAGE_COUNT,
255 };
256
257 /*******************************************************************************
258 * Code
259 ******************************************************************************/
260 /*!
261  * @brief Get the descritpor.
262  *
263  * The function is used to get the descritpor, including the device descritpor, configuration descriptor, and string
264  * descriptor, etc.
265  *
266  * @param handle              The device handle.
267  * @param setup               The setup packet buffer address.
268  * @param length              It is an OUT parameter, return the data length need to be sent to host.
269  * @param buffer              It is an OUT parameter, return the data buffer address.
270  *
271  * @return A USB error code or kStatus_USB_Success.
272  */
273 usb_status_t USB_DeviceGetDescriptor(usb_device_handle handle,
274                                      usb_setup_struct_t *setup,
275                                      uint32_t *length,
276                                      uint8_t **buffer)
277 {
278     uint8_t descriptorType = (uint8_t)((setup->wValue & 0xFF00U) >> 8U);
279     uint8_t descriptorIndex = (uint8_t)((setup->wValue & 0x00FFU));
280     usb_status_t ret = kStatus_USB_Success;
281     if (USB_REQUEST_STANDARD_GET_DESCRIPTOR != setup->bRequest)
282     {
283         return kStatus_USB_InvalidRequest;
284     }
285     switch (descriptorType)
286     {
287         case USB_DESCRIPTOR_TYPE_STRING:
288         {
289             if (descriptorIndex == 0)
290             {
291                 *buffer = (uint8_t *)g_UsbDeviceLanguageList.languageString;
292                 *length = g_UsbDeviceLanguageList.stringLength;
293             }
294             else
295             {
296                 uint8_t langId = 0;
297                 uint8_t langIndex = USB_DEVICE_STRING_COUNT;
298
299                 for (; langId < USB_DEVICE_LANGUAGE_COUNT; langId++)
300                 {
301                     if (setup->wIndex == g_UsbDeviceLanguageList.languageList[langId].languageId)
302                     {
303                         if (descriptorIndex < USB_DEVICE_STRING_COUNT)
304                         {
305                             langIndex = descriptorIndex;
306                         }
307                         break;
308                     }
309                 }
310
311                 if (USB_DEVICE_STRING_COUNT == langIndex)
312                 {
313                     langId = 0;
314                 }
315                 *buffer = (uint8_t *)g_UsbDeviceLanguageList.languageList[langId].string[langIndex];
316                 *length = g_UsbDeviceLanguageList.languageList[langId].length[langIndex];
317             }
318         }
319         break;
320         case USB_DESCRIPTOR_TYPE_DEVICE:
321         {
322             *buffer = g_UsbDeviceDescriptor;
323             *length = USB_DESCRIPTOR_LENGTH_DEVICE;
324         }
325         break;
326         case USB_DESCRIPTOR_TYPE_CONFIGURE:
327         {
328             *buffer = g_UsbDeviceConfigurationDescriptor;
329             *length = USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL;
330         }
331         break;
332         default:
333             ret = kStatus_USB_InvalidRequest;
334             break;
335     } /* End Switch */
336     return ret;
337 }
338
339 /*!
340  * @brief Set the device configuration.
341  *
342  * The function is used to set the device configuration.
343  *
344  * @param handle              The device handle.
345  * @param configure           The configuration value.
346  *
347  * @return A USB error code or kStatus_USB_Success.
348  */
349 usb_status_t USB_DeviceSetConfigure(usb_device_handle handle, uint8_t configure)
350 {
351     if (!configure)
352     {
353         return kStatus_USB_Error;
354     }
355     g_currentConfigure = configure;
356     return USB_DeviceCallback(handle, kUSB_DeviceEventSetConfiguration, &configure);
357 }
358
359 /*!
360  * @brief Get the device configuration.
361  *
362  * The function is used to get the device configuration.
363  *
364  * @param handle The device handle.
365  * @param configure It is an OUT parameter, save the current configuration value.
366  *
367  * @return A USB error code or kStatus_USB_Success.
368  */
369 usb_status_t USB_DeviceGetConfigure(usb_device_handle handle, uint8_t *configure)
370 {
371     *configure = g_currentConfigure;
372     return kStatus_USB_Success;
373 }
374
375 /*!
376  * @brief Set an interface alternate setting.
377  *
378  * The function is used to set an interface alternate setting.
379  *
380  * @param handle The device handle.
381  * @param interface The interface index.
382  * @param alternateSetting The new alternate setting value.
383  *
384  * @return A USB error code or kStatus_USB_Success.
385  */
386 usb_status_t USB_DeviceSetInterface(usb_device_handle handle, uint8_t interface, uint8_t alternateSetting)
387 {
388     g_interface[interface] = alternateSetting;
389     return USB_DeviceCallback(handle, kUSB_DeviceEventSetInterface, &interface);
390 }
391
392 /*!
393  * @brief Get an interface alternate setting.
394  *
395  * The function is used to get an interface alternate setting.
396  *
397  * @param handle The device handle.
398  * @param interface The interface index.
399  * @param alternateSetting It is an OUT parameter, save the new alternate setting value of the interface.
400  *
401  * @return A USB error code or kStatus_USB_Success.
402  */
403 usb_status_t USB_DeviceGetInterface(usb_device_handle handle, uint8_t interface, uint8_t *alternateSetting)
404 {
405     *alternateSetting = g_interface[interface];
406     return kStatus_USB_Success;
407 }
408
409 /*!
410  * @brief USB device set speed function.
411  *
412  * This function sets the speed of the USB device.
413  *
414  * Due to the difference of HS and FS descriptors, the device descriptors and configurations need to be updated to match
415  * current speed.
416  * As the default, the device descriptors and configurations are configured by using FS parameters for both EHCI and
417  * KHCI.
418  * When the EHCI is enabled, the application needs to call this fucntion to update device by using current speed.
419  * The updated information includes endpoint max packet size, endpoint interval, etc.
420  *
421  * @param handle The USB device handle.
422  * @param speed Speed type. USB_SPEED_HIGH/USB_SPEED_FULL/USB_SPEED_LOW.
423  *
424  * @return A USB error code or kStatus_USB_Success.
425  */
426 usb_status_t USB_DeviceSetSpeed(usb_device_handle handle, uint8_t speed)
427 {
428     usb_descriptor_union_t *ptr1;
429     usb_descriptor_union_t *ptr2;
430
431     ptr1 = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[0]);
432     ptr2 = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL - 1]);
433
434     while (ptr1 < ptr2)
435     {
436         if (ptr1->common.bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT)
437         {
438             if (USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & 0x0FU))
439             {
440                 if (USB_SPEED_HIGH == speed)
441                 {
442                     ptr1->endpoint.bInterval = HS_CDC_VCOM_INTERRUPT_IN_INTERVAL;
443                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE,
444                                                        ptr1->endpoint.wMaxPacketSize);
445                 }
446                 else
447                 {
448                     ptr1->endpoint.bInterval = FS_CDC_VCOM_INTERRUPT_IN_INTERVAL;
449                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE,
450                                                        ptr1->endpoint.wMaxPacketSize);
451                 }
452             }
453             else if (USB_CDC_VCOM_BULK_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & 0x0FU))
454             {
455                 if (USB_SPEED_HIGH == speed)
456                 {
457                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_BULK_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize);
458                 }
459                 else
460                 {
461                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_BULK_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize);
462                 }
463             }
464             else if (USB_CDC_VCOM_BULK_OUT_ENDPOINT == (ptr1->endpoint.bEndpointAddress & 0x0FU))
465             {
466                 if (USB_SPEED_HIGH == speed)
467                 {
468                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_BULK_OUT_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize);
469                 }
470                 else
471                 {
472                     USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize);
473                 }
474             }
475             else
476             {
477             }
478         }
479         ptr1 = (usb_descriptor_union_t *)((uint8_t *)ptr1 + ptr1->common.bLength);
480     }
481     return kStatus_USB_Success;
482 }
483
484 void
485 USB_DeviceSetVendorId (uint16_t vid)
486 {
487         g_UsbDeviceDescriptor[8] = (vid >> 0) & 0xff;
488         g_UsbDeviceDescriptor[9] = (vid >> 8) & 0xff;
489 }
490
491 void
492 USB_DeviceSetProductId (uint16_t pid)
493 {
494         g_UsbDeviceDescriptor[10] = (pid >> 0) & 0xff;
495         g_UsbDeviceDescriptor[11] = (pid >> 8) & 0xff;
496 }