419 lines
11 KiB
C
419 lines
11 KiB
C
|
/*
|
||
|
* Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
|
||
|
*
|
||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||
|
*/
|
||
|
|
||
|
#include <limits.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <platform_def.h>
|
||
|
|
||
|
#include <common/debug.h>
|
||
|
#include <drivers/st/bsec.h>
|
||
|
#include <lib/usb/usb_core.h>
|
||
|
#include <lib/usb/usb_st_dfu.h>
|
||
|
|
||
|
#include <stm32mp_common.h>
|
||
|
#include <stm32mp1_usb_desc.h>
|
||
|
|
||
|
/* USB Standard Device Descriptor */
|
||
|
static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
|
||
|
USB_LEN_DEV_DESC, /* bLength */
|
||
|
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
||
|
0x00, /* bcdUSB */
|
||
|
0x02, /* version */
|
||
|
0x00, /* bDeviceClass */
|
||
|
0x00, /* bDeviceSubClass */
|
||
|
0x00, /* bDeviceProtocol */
|
||
|
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
||
|
LOBYTE(USBD_VID), /* idVendor */
|
||
|
HIBYTE(USBD_VID), /* idVendor */
|
||
|
LOBYTE(USBD_PID), /* idVendor */
|
||
|
HIBYTE(USBD_PID), /* idVendor */
|
||
|
0x00, /* bcdDevice rel. 2.00 */
|
||
|
0x02,
|
||
|
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
||
|
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
||
|
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
||
|
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
|
||
|
}; /* USB_DeviceDescriptor */
|
||
|
|
||
|
/* USB Standard String Descriptor */
|
||
|
static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
|
||
|
USB_LEN_LANGID_STR_DESC,
|
||
|
USB_DESC_TYPE_STRING,
|
||
|
LOBYTE(USBD_LANGID_STRING),
|
||
|
HIBYTE(USBD_LANGID_STRING),
|
||
|
};
|
||
|
|
||
|
/* USB Standard Device Descriptor */
|
||
|
static const uint8_t
|
||
|
usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
|
||
|
USB_LEN_DEV_QUALIFIER_DESC,
|
||
|
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||
|
0x00,
|
||
|
0x02,
|
||
|
0x00,
|
||
|
0x00,
|
||
|
0x00,
|
||
|
0x40,
|
||
|
0x01,
|
||
|
0x00,
|
||
|
};
|
||
|
|
||
|
static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1] = {
|
||
|
USB_SIZ_STRING_SERIAL,
|
||
|
USB_DESC_TYPE_STRING,
|
||
|
};
|
||
|
|
||
|
/* USB DFU device Configuration Descriptor */
|
||
|
static uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
|
||
|
0x09, /* bLength: Configuration Descriptor size */
|
||
|
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||
|
USB_DFU_CONFIG_DESC_SIZ,
|
||
|
/* wTotalLength: Bytes returned */
|
||
|
0x00,
|
||
|
0x01,/* bNumInterfaces: 1 interface*/
|
||
|
0x01,/* bConfigurationValue: Configuration value*/
|
||
|
0x02,/* iConfiguration: Index of string descriptor
|
||
|
* describing the configuration
|
||
|
*/
|
||
|
0xC0,/* bmAttributes: bus powered and Supprts Remote Wakeup */
|
||
|
0x32,/* MaxPower 100 mA: this current is used for detecting Vbus */
|
||
|
/* 09 */
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 0 */
|
||
|
USBD_DFU_IF_DESC(0), /* This interface is mandatory for all devices */
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 1 */
|
||
|
USBD_DFU_IF_DESC(1),
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 2 */
|
||
|
USBD_DFU_IF_DESC(2),
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 3 */
|
||
|
USBD_DFU_IF_DESC(3),
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 4 */
|
||
|
USBD_DFU_IF_DESC(4),
|
||
|
|
||
|
/* Descriptor of DFU interface 0 Alternate setting 5 */
|
||
|
USBD_DFU_IF_DESC(5),
|
||
|
|
||
|
/* DFU Functional Descriptor */
|
||
|
0x09,/* blength = 9 Bytes */
|
||
|
DFU_DESCRIPTOR_TYPE,/* DFU Functional Descriptor*/
|
||
|
DFU_BM_ATTRIBUTE,/* bmAttribute
|
||
|
* bitCanDnload = 1 (bit 0)
|
||
|
* bitCanUpload = 1 (bit 1)
|
||
|
* bitManifestationTolerant = 1 (bit 2)
|
||
|
* bitWillDetach = 1 (bit 3)
|
||
|
* Reserved (bit4-6)
|
||
|
* bitAcceleratedST = 0 (bit 7)
|
||
|
*/
|
||
|
0xFF,/* DetachTimeOut = 255 ms */
|
||
|
0x00,
|
||
|
/* WARNING: In DMA mode the multiple MPS packets feature
|
||
|
* is still not supported ==> In this case,
|
||
|
* when using DMA USBD_DFU_XFER_SIZE should be set
|
||
|
* to 64 in usbd_conf.h
|
||
|
*/
|
||
|
TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE),/* TransferSize = 1024 Byte*/
|
||
|
((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion*/
|
||
|
((USB_DFU_VERSION >> 8) & 0xFF)
|
||
|
};
|
||
|
|
||
|
static uint8_t usb_local_string_dec[USBD_MAX_STR_DESC_SIZ];
|
||
|
|
||
|
/*
|
||
|
* Convert Hex 32Bits value into char
|
||
|
* value: value to convert
|
||
|
* pbuf: pointer to the buffer
|
||
|
* len: buffer length
|
||
|
*/
|
||
|
static void 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Create the serial number string descriptor
|
||
|
*/
|
||
|
static void update_serial_num_string(void)
|
||
|
{
|
||
|
/* serial number is set to 0*/
|
||
|
uint8_t i;
|
||
|
uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U};
|
||
|
uint32_t otp;
|
||
|
uint32_t len;
|
||
|
|
||
|
if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
|
||
|
ERROR("BSEC: Get UID_OTP number Error\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ((len / __WORD_BIT) != UID_WORD_NB) {
|
||
|
ERROR("BSEC: Get UID_OTP length Error\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < UID_WORD_NB; i++) {
|
||
|
if (bsec_shadow_read_otp(&deviceserial[i], i + otp) !=
|
||
|
BSEC_OK) {
|
||
|
ERROR("BSEC: UID%d Error\n", i);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int_to_unicode(deviceserial[0], (uint8_t *)&usb_stm32mp1_serial[2], 8);
|
||
|
int_to_unicode(deviceserial[1], (uint8_t *)&usb_stm32mp1_serial[18], 8);
|
||
|
int_to_unicode(deviceserial[2], (uint8_t *)&usb_stm32mp1_serial[34], 8);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* usb_get_qualifier_desc
|
||
|
* return Device Qualifier descriptor
|
||
|
* param : length : pointer data length
|
||
|
* return : pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
|
||
|
{
|
||
|
*length = sizeof(usbd_stm32mp1_qualifier_desc);
|
||
|
return (uint8_t *)usbd_stm32mp1_qualifier_desc;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_get_dfu_desc
|
||
|
* return Device Qualifier descriptor
|
||
|
* param : length : pointer data length
|
||
|
* return : pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_get_dfu_desc(uint16_t *len)
|
||
|
{
|
||
|
*len = USB_DFU_DESC_SIZ;
|
||
|
return ((uint8_t *)usb_stm32mp1_config_desc + (9 * 7));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_get_config_desc
|
||
|
* return configuration descriptor
|
||
|
* param : speed : current device speed
|
||
|
* param : length : pointer data length
|
||
|
* return : pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
|
||
|
{
|
||
|
*length = sizeof(usb_stm32mp1_config_desc);
|
||
|
return (uint8_t *)usb_stm32mp1_config_desc;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_get_string
|
||
|
* Convert Ascii string into unicode one
|
||
|
* param : desc : descriptor buffer
|
||
|
* param : unicode : Formatted string buffer (unicode)
|
||
|
* param : len : descriptor length
|
||
|
* return : None
|
||
|
*/
|
||
|
static void stm32mp1_get_string(uint8_t *desc, uint8_t *unicode, uint16_t *len)
|
||
|
{
|
||
|
uint8_t idx = 0;
|
||
|
|
||
|
if (!desc)
|
||
|
return;
|
||
|
|
||
|
*len = strlen((char *)desc) * 2 + 2;
|
||
|
unicode[idx++] = *len;
|
||
|
unicode[idx++] = USB_DESC_TYPE_STRING;
|
||
|
|
||
|
while (*desc != '\0') {
|
||
|
unicode[idx++] = *desc++;
|
||
|
unicode[idx++] = 0x00;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_device_desc
|
||
|
* Returns the device descriptor.
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_device_desc(uint16_t *length)
|
||
|
{
|
||
|
*length = sizeof(usb_stm32mp1_desc);
|
||
|
return (uint8_t *)usb_stm32mp1_desc;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_lang_id_desc
|
||
|
* Returns the LangID string descriptor.
|
||
|
* speed: Current device speed
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
|
||
|
{
|
||
|
*length = sizeof(usb_stm32mp1_lang_id_desc);
|
||
|
|
||
|
return (uint8_t *)usb_stm32mp1_lang_id_desc;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_product_desc
|
||
|
* Returns the product string descriptor.
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_product_desc(uint16_t *length)
|
||
|
{
|
||
|
stm32mp1_get_string((uint8_t *)USBD_PRODUCT_HS_STRING,
|
||
|
usb_local_string_dec, length);
|
||
|
|
||
|
return usb_local_string_dec;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_manufacturer_desc
|
||
|
* Returns the manufacturer string descriptor.
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
|
||
|
{
|
||
|
stm32mp1_get_string((uint8_t *)USBD_MANUFACTURER_STRING,
|
||
|
usb_local_string_dec, length);
|
||
|
|
||
|
return usb_local_string_dec;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_serial_desc
|
||
|
* Returns the serial number string descriptor.
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_serial_desc(uint16_t *length)
|
||
|
{
|
||
|
*length = USB_SIZ_STRING_SERIAL;
|
||
|
|
||
|
/* Update the serial number string descriptor
|
||
|
* with the data from the unique ID
|
||
|
*/
|
||
|
update_serial_num_string();
|
||
|
|
||
|
return (uint8_t *)usb_stm32mp1_serial;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_Config_desc
|
||
|
* Returns the configuration string descriptor.
|
||
|
* length: Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_config_desc(uint16_t *length)
|
||
|
{
|
||
|
stm32mp1_get_string((uint8_t *)USBD_CONFIGURATION_HS_STRING,
|
||
|
usb_local_string_dec, length);
|
||
|
|
||
|
return usb_local_string_dec;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_interface_desc
|
||
|
* Returns the interface string descriptor.
|
||
|
* length : Pointer to data length variable
|
||
|
* return : Pointer to descriptor buffer
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_interface_desc(uint16_t *length)
|
||
|
{
|
||
|
stm32mp1_get_string((uint8_t *)USBD_INTERFACE_HS_STRING,
|
||
|
usb_local_string_dec, length);
|
||
|
|
||
|
return usb_local_string_dec;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* stm32mp1_get_usr_desc
|
||
|
* Manages the transfer of memory interfaces string descriptors.
|
||
|
* param : index: descriptor index
|
||
|
* param : length : pointer data length
|
||
|
* return : pointer to the descriptor table or NULL if the descriptor
|
||
|
* is not supported.
|
||
|
*/
|
||
|
static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
|
||
|
{
|
||
|
uint8_t *ret;
|
||
|
|
||
|
if (index > (USBD_IDX_INTERFACE_STR + USBD_DESC_MAX_ITF_NUM))
|
||
|
return NULL;
|
||
|
|
||
|
switch (index) {
|
||
|
case 6:
|
||
|
stm32mp1_get_string((uint8_t *)"@Partition0 /0x00/1*256Ke",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
case 7:
|
||
|
stm32mp1_get_string((uint8_t *)"@FSBL /0x01/1*1Me",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
case 8:
|
||
|
stm32mp1_get_string((uint8_t *)"@Partition2 /0x02/1*1Me",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
case 9:
|
||
|
stm32mp1_get_string((uint8_t *)"@Partition3 /0x03/1*16Me",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
case 10:
|
||
|
stm32mp1_get_string((uint8_t *)"@Partition4 /0x04/1*16Me",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
case 11:
|
||
|
stm32mp1_get_string((uint8_t *)"@virtual /0xF1/1*512Ba",
|
||
|
usb_local_string_dec, length);
|
||
|
ret = usb_local_string_dec;
|
||
|
break;
|
||
|
default:
|
||
|
ret = NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static const usb_desc_t dfu_desc = {
|
||
|
.get_device_desc = stm32mp1_device_desc,
|
||
|
.get_lang_id_desc = stm32mp1_lang_id_desc,
|
||
|
.get_manufacturer_desc = stm32mp1_manufacturer_desc,
|
||
|
.get_product_desc = stm32mp1_product_desc,
|
||
|
.get_configuration_desc = stm32mp1_config_desc,
|
||
|
.get_serial_desc = stm32mp1_serial_desc,
|
||
|
.get_interface_desc = stm32mp1_interface_desc,
|
||
|
.get_usr_desc = stm32mp1_get_usr_desc,
|
||
|
.get_hs_config_desc = stm32mp1_get_config_desc,
|
||
|
.get_fs_config_desc = stm32mp1_get_config_desc,
|
||
|
.get_other_speed_config_desc = stm32mp1_get_config_desc,
|
||
|
.get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
|
||
|
.get_dfu_desc = stm32mp1_get_dfu_desc
|
||
|
};
|
||
|
|
||
|
void stm32mp_usb_init_desc(usb_handle_t *pdev)
|
||
|
{
|
||
|
register_platform(pdev, &dfu_desc);
|
||
|
}
|