/** ************************************************************************** * @file cdc_desc.c * @version v2.0.6 * @date 2021-12-31 * @brief usb cdc device descriptor ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include "usb_std.h" #include "usbd_sdr.h" #include "usbd_core.h" #include "cdc_desc.h" /** @addtogroup AT32F403A_407_middlewares_usbd_class * @{ */ /** @defgroup USB_cdc_desc * @brief usb device cdc descriptor * @{ */ /** @defgroup USB_cdc_desc_private_functions * @{ */ usbd_desc_t *get_device_descriptor(void); usbd_desc_t *get_device_qualifier(void); usbd_desc_t *get_device_configuration(void); usbd_desc_t *get_device_other_speed(void); usbd_desc_t *get_device_lang_id(void); usbd_desc_t *get_device_manufacturer_string(void); usbd_desc_t *get_device_product_string(void); usbd_desc_t *get_device_serial_string(void); usbd_desc_t *get_device_interface_string(void); usbd_desc_t *get_device_config_string(void); uint16_t usbd_unicode_convert(uint8_t *string, uint8_t *unicode_buf); static void usbd_int_to_unicode (uint32_t value , uint8_t *pbuf , uint8_t len); static void get_serial_num(void); static uint8_t g_usbd_desc_buffer[256]; /** * @brief device descriptor handler structure */ usbd_desc_handler desc_handler = { get_device_descriptor, get_device_qualifier, get_device_configuration, get_device_other_speed, get_device_lang_id, get_device_manufacturer_string, get_device_product_string, get_device_serial_string, get_device_interface_string, get_device_config_string, }; /** * @brief usb device standard descriptor */ #if defined ( __ICCARM__ ) /* iar compiler */ #pragma data_alignment=4 #endif ALIGNED_HEAD uint8_t g_usbd_descriptor[USB_DEVICE_DESC_LEN] ALIGNED_TAIL = { USB_DEVICE_DESC_LEN, /* bLength */ USB_DESCIPTOR_TYPE_DEVICE, /* bDescriptorType */ 0x00, /* bcdUSB */ 0x02, 0x02, /* bDeviceClass */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ USB_MAX_EP0_SIZE, /* bMaxPacketSize */ LBYTE(USBD_VENDOR_ID), /* idVendor */ HBYTE(USBD_VENDOR_ID), /* idVendor */ LBYTE(USBD_PRODUCT_ID), /* idProduct */ HBYTE(USBD_PRODUCT_ID), /* idProduct */ 0x00, /* bcdDevice rel. 2.00 */ 0x02, USB_MFC_STRING, /* Index of manufacturer string */ USB_PRODUCT_STRING, /* Index of product string */ USB_SERIAL_STRING, /* Index of serial number string */ 1 /* bNumConfigurations */ }; /** * @brief usb configuration standard descriptor */ #if defined ( __ICCARM__ ) /* iar compiler */ #pragma data_alignment=4 #endif ALIGNED_HEAD uint8_t g_usbd_configuration[USBD_CONFIG_DESC_SIZE] ALIGNED_TAIL = { USB_DEVICE_CFG_DESC_LEN, /* bLength: configuration descriptor size */ USB_DESCIPTOR_TYPE_CONFIGURATION, /* bDescriptorType: configuration */ LBYTE(USBD_CONFIG_DESC_SIZE), /* wTotalLength: bytes returned */ HBYTE(USBD_CONFIG_DESC_SIZE), /* wTotalLength: bytes returned */ 0x02, /* bNumInterfaces: 2 interface */ 0x01, /* bConfigurationValue: configuration value */ 0x00, /* iConfiguration: index of string descriptor describing the configuration */ 0xC0, /* bmAttributes: self powered */ 0x32, /* MaxPower 100 mA: this current is used for detecting vbus */ USB_DEVICE_IF_DESC_LEN, /* bLength: interface descriptor size */ USB_DESCIPTOR_TYPE_INTERFACE, /* bDescriptorType: interface descriptor type */ 0x00, /* bInterfaceNumber: number of interface */ 0x00, /* bAlternateSetting: alternate set */ 0x01, /* bNumEndpoints: number of endpoints */ USB_CLASS_CODE_CDC, /* bInterfaceClass: CDC class code */ 0x02, /* bInterfaceSubClass: subclass code, Abstract Control Model*/ 0x01, /* bInterfaceProtocol: protocol code, AT Command */ 0x00, /* iInterface: index of string descriptor */ 0x05, /* bFunctionLength: size of this descriptor in bytes */ USBD_CDC_CS_INTERFACE, /* bDescriptorType: CDC interface descriptor type */ USBD_CDC_SUBTYPE_HEADER, /* bDescriptorSubtype: Header function Descriptor 0x00*/ LBYTE(BCD_NUM), HBYTE(BCD_NUM), /* bcdCDC: USB class definitions for communications */ 0x05, /* bFunctionLength: size of this descriptor in bytes */ USBD_CDC_CS_INTERFACE, /* bDescriptorType: CDC interface descriptor type */ USBD_CDC_SUBTYPE_CMF, /* bDescriptorSubtype: Call Management function descriptor subtype 0x01 */ 0x00, /* bmCapabilities: 0x00*/ 0x01, /* bDataInterface: interface number of data class interface optionally used for call management */ 0x04, /* bFunctionLength: size of this descriptor in bytes */ USBD_CDC_CS_INTERFACE, /* bDescriptorType: CDC interface descriptor type */ USBD_CDC_SUBTYPE_ACM, /* bDescriptorSubtype: Abstract Control Management functional descriptor subtype 0x02 */ 0x02, /* bmCapabilities: Support Set_Line_Coding and Get_Line_Coding 0x02 */ 0x05, /* bFunctionLength: size of this descriptor in bytes */ USBD_CDC_CS_INTERFACE, /* bDescriptorType: CDC interface descriptor type */ USBD_CDC_SUBTYPE_UFD, /* bDescriptorSubtype: Union Function Descriptor subtype 0x06 */ 0x00, /* bControlInterface: The interface number of the communications or data class interface 0x00 */ 0x01, /* bSubordinateInterface0: interface number of first subordinate interface in the union */ USB_DEVICE_EPT_LEN, /* bLength: size of endpoint descriptor in bytes */ USB_DESCIPTOR_TYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */ USBD_CDC_INT_EPT, /* bEndpointAddress: the address of endpoint on usb device described by this descriptor */ USB_EPT_DESC_INTERRUPT, /* bmAttributes: endpoint attributes */ LBYTE(USBD_CMD_MAXPACKET_SIZE), HBYTE(USBD_CMD_MAXPACKET_SIZE), /* wMaxPacketSize: maximum packe size this endpoint */ HID_BINTERVAL_TIME, /* bInterval: interval for polling endpoint for data transfers */ USB_DEVICE_IF_DESC_LEN, /* bLength: interface descriptor size */ USB_DESCIPTOR_TYPE_INTERFACE, /* bDescriptorType: interface descriptor type */ 0x01, /* bInterfaceNumber: number of interface */ 0x00, /* bAlternateSetting: alternate set */ 0x02, /* bNumEndpoints: number of endpoints */ USB_CLASS_CODE_CDCDATA, /* bInterfaceClass: CDC-data class code */ 0x00, /* bInterfaceSubClass: Data interface subclass code 0x00*/ 0x00, /* bInterfaceProtocol: data class protocol code 0x00 */ 0x00, /* iInterface: index of string descriptor */ USB_DEVICE_EPT_LEN, /* bLength: size of endpoint descriptor in bytes */ USB_DESCIPTOR_TYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */ USBD_CDC_BULK_IN_EPT, /* bEndpointAddress: the address of endpoint on usb device described by this descriptor */ USB_EPT_DESC_BULK, /* bmAttributes: endpoint attributes */ LBYTE(USBD_IN_MAXPACKET_SIZE), HBYTE(USBD_IN_MAXPACKET_SIZE), /* wMaxPacketSize: maximum packe size this endpoint */ 0x00, /* bInterval: interval for polling endpoint for data transfers */ USB_DEVICE_EPT_LEN, /* bLength: size of endpoint descriptor in bytes */ USB_DESCIPTOR_TYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */ USBD_CDC_BULK_OUT_EPT, /* bEndpointAddress: the address of endpoint on usb device described by this descriptor */ USB_EPT_DESC_BULK, /* bmAttributes: endpoint attributes */ LBYTE(USBD_OUT_MAXPACKET_SIZE), HBYTE(USBD_OUT_MAXPACKET_SIZE), /* wMaxPacketSize: maximum packe size this endpoint */ 0x00, /* bInterval: interval for polling endpoint for data transfers */ }; /** * @brief usb string lang id */ #if defined ( __ICCARM__ ) /* iar compiler */ #pragma data_alignment=4 #endif ALIGNED_HEAD uint8_t g_string_lang_id[USBD_SIZ_STRING_LANGID] ALIGNED_TAIL = { USBD_SIZ_STRING_LANGID, USB_DESCIPTOR_TYPE_STRING, 0x09, 0x04, }; /** * @brief usb string serial */ #if defined ( __ICCARM__ ) /* iar compiler */ #pragma data_alignment=4 #endif ALIGNED_HEAD uint8_t g_string_serial[USBD_SIZ_STRING_SERIAL] ALIGNED_TAIL = { USBD_SIZ_STRING_SERIAL, USB_DESCIPTOR_TYPE_STRING, }; /* device descriptor */ usbd_desc_t device_descriptor = { USB_DEVICE_DESC_LEN, g_usbd_descriptor }; /* config descriptor */ usbd_desc_t config_descriptor = { USBD_CONFIG_DESC_SIZE, g_usbd_configuration }; /* langid descriptor */ usbd_desc_t langid_descriptor = { USBD_SIZ_STRING_LANGID, g_string_lang_id }; /* serial descriptor */ usbd_desc_t serial_descriptor = { USBD_SIZ_STRING_SERIAL, g_string_serial }; usbd_desc_t vp_desc; /** * @brief standard usb unicode convert * @param string: source string * @param unicode_buf: unicode buffer * @retval length */ uint16_t usbd_unicode_convert(uint8_t *string, uint8_t *unicode_buf) { uint16_t str_len = 0, id_pos = 2; uint8_t *tmp_str = string; while(*tmp_str != '\0') { str_len ++; unicode_buf[id_pos ++] = *tmp_str ++; unicode_buf[id_pos ++] = 0x00; } str_len = str_len * 2 + 2; unicode_buf[0] = str_len; unicode_buf[1] = USB_DESCIPTOR_TYPE_STRING; return str_len; } /** * @brief usb int convert to unicode * @param value: int value * @param pbus: unicode buffer * @param len: length * @retval none */ static void usbd_int_to_unicode (uint32_t value , uint8_t *pbuf , uint8_t len) { uint8_t idx = 0; for( idx = 0 ; idx < len ; idx ++) { if( ((value >> 28)) < 0xA ) { pbuf[ 2 * idx] = (value >> 28) + '0'; } else { pbuf[2 * idx] = (value >> 28) + 'A' - 10; } value = value << 4; pbuf[2 * idx + 1] = 0; } } /** * @brief usb get serial number * @param none * @retval none */ static void get_serial_num(void) { uint32_t serial0, serial1, serial2; serial0 = *(uint32_t*)MCU_ID1; serial1 = *(uint32_t*)MCU_ID2; serial2 = *(uint32_t*)MCU_ID3; serial0 += serial2; if (serial0 != 0) { usbd_int_to_unicode (serial0, &g_string_serial[2] ,8); usbd_int_to_unicode (serial1, &g_string_serial[18] ,4); } } /** * @brief get device descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_descriptor(void) { return &device_descriptor; } /** * @brief get device qualifier * @param none * @retval usbd_desc */ usbd_desc_t * get_device_qualifier(void) { return NULL; } /** * @brief get config descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_configuration(void) { return &config_descriptor; } /** * @brief get other speed descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_other_speed(void) { return NULL; } /** * @brief get lang id descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_lang_id(void) { return &langid_descriptor; } /** * @brief get manufacturer descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_manufacturer_string(void) { vp_desc.length = usbd_unicode_convert((uint8_t *)USBD_DESC_MANUFACTURER_STRING, g_usbd_desc_buffer); vp_desc.descriptor = g_usbd_desc_buffer; return &vp_desc; } /** * @brief get product descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_product_string(void) { vp_desc.length = usbd_unicode_convert((uint8_t *)USBD_DESC_PRODUCT_STRING, g_usbd_desc_buffer); vp_desc.descriptor = g_usbd_desc_buffer; return &vp_desc; } /** * @brief get serial descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_serial_string(void) { get_serial_num(); return &serial_descriptor; } /** * @brief get interface descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_interface_string(void) { vp_desc.length = usbd_unicode_convert((uint8_t *)USBD_DESC_INTERFACE_STRING, g_usbd_desc_buffer); vp_desc.descriptor = g_usbd_desc_buffer; return &vp_desc; } /** * @brief get device config descriptor * @param none * @retval usbd_desc */ usbd_desc_t *get_device_config_string(void) { vp_desc.length = usbd_unicode_convert((uint8_t *)USBD_DESC_CONFIGURATION_STRING, g_usbd_desc_buffer); vp_desc.descriptor = g_usbd_desc_buffer; return &vp_desc; } /** * @} */ /** * @} */ /** * @} */