1 /* 2 * Copyright (c) 2021-2025, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <limits.h> 8 #include <string.h> 9 10 #include <common/debug.h> 11 #include <drivers/st/bsec.h> 12 #include <drivers/st/stm32mp1_usb.h> 13 #include <drivers/usb_device.h> 14 15 #include <platform_def.h> 16 #include <stm32cubeprogrammer.h> 17 #include <stm32mp_common.h> 18 #include <usb_dfu.h> 19 20 /* String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */ 21 #define SIZ_STRING_SERIAL U(24) 22 #define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U)) 23 #define USBD_MAX_STR_DESC_SIZ 0x100 24 #define USBD_VID 0x0483 25 #define USBD_PID 0xDF11 26 #define USBD_LANGID_STRING 0x409 27 #define USBD_MANUFACTURER_STRING "STMicroelectronics" 28 #define USBD_CONFIGURATION_STRING "DFU Config" 29 #define USBD_INTERFACE_STRING "DFU Interface" 30 31 #if STM32MP13 32 #define USB_DFU_ITF_NUM 2 33 #endif 34 #if STM32MP15 35 #define USB_DFU_ITF_NUM 6 36 #endif 37 38 #define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM) 39 40 /* DFU devices */ 41 static struct usb_dfu_handle usb_dfu_handle; 42 43 /* USB Standard Device Descriptor */ 44 static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = { 45 USB_LEN_DEV_DESC, /* bLength */ 46 USB_DESC_TYPE_DEVICE, /* bDescriptorType */ 47 0x00, /* bcdUSB */ 48 0x02, /* version */ 49 0x00, /* bDeviceClass */ 50 0x00, /* bDeviceSubClass */ 51 0x00, /* bDeviceProtocol */ 52 USB_MAX_EP0_SIZE, /* bMaxPacketSize */ 53 LOBYTE(USBD_VID), /* idVendor */ 54 HIBYTE(USBD_VID), /* idVendor */ 55 LOBYTE(USBD_PID), /* idVendor */ 56 HIBYTE(USBD_PID), /* idVendor */ 57 0x00, /* bcdDevice rel. 2.00 */ 58 0x02, 59 USBD_IDX_MFC_STR, /* Index of manufacturer string */ 60 USBD_IDX_PRODUCT_STR, /* Index of product string */ 61 USBD_IDX_SERIAL_STR, /* Index of serial number string */ 62 USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */ 63 }; /* USB_DeviceDescriptor */ 64 65 /* USB Standard String Descriptor */ 66 static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = { 67 USB_LEN_LANGID_STR_DESC, 68 USB_DESC_TYPE_STRING, 69 LOBYTE(USBD_LANGID_STRING), 70 HIBYTE(USBD_LANGID_STRING), 71 }; 72 73 /* USB Standard Device Descriptor */ 74 static const uint8_t 75 usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = { 76 USB_LEN_DEV_QUALIFIER_DESC, 77 USB_DESC_TYPE_DEVICE_QUALIFIER, 78 0x00, 79 0x02, 80 0x00, 81 0x00, 82 0x00, 83 0x40, 84 0x01, 85 0x00, 86 }; 87 88 /* USB serial number: build dynamically */ 89 static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1]; 90 91 /* USB DFU device Configuration Descriptor */ 92 static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { 93 0x09, /* bLength: Configuration Descriptor size */ 94 USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ 95 USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ 96 0x00, 97 0x01, /* bNumInterfaces: 1 interface */ 98 0x01, /* bConfigurationValue: Configuration value */ 99 0x02, /* iConfiguration: Index of string descriptor for configuration */ 100 0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */ 101 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ 102 103 /* Descriptor of DFU interface 0 Alternate setting 0..N */ 104 USBD_DFU_IF_DESC(0), 105 USBD_DFU_IF_DESC(1), 106 #if USB_DFU_ITF_NUM > 2 107 USBD_DFU_IF_DESC(2), 108 #endif 109 #if USB_DFU_ITF_NUM > 3 110 USBD_DFU_IF_DESC(3), 111 #endif 112 #if USB_DFU_ITF_NUM > 4 113 USBD_DFU_IF_DESC(4), 114 #endif 115 #if USB_DFU_ITF_NUM > 5 116 USBD_DFU_IF_DESC(5), 117 #endif 118 /* DFU Functional Descriptor */ 119 0x09, /* blength = 9 Bytes */ 120 DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */ 121 DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */ 122 0xFF, /* DetachTimeOut = 255 ms */ 123 0x00, 124 TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */ 125 ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */ 126 ((USB_DFU_VERSION >> 8) & 0xFF) 127 }; 128 129 /* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */ 130 #if STM32MP13 131 const char *const if_desc_string[USB_DFU_ITF_NUM] = { 132 "@SSBL /0x03/1*16Me", 133 "@virtual /0xF1/1*512Ba" 134 }; 135 #endif 136 #if STM32MP15 137 const char *const if_desc_string[USB_DFU_ITF_NUM] = { 138 "@Partition0 /0x00/1*256Ke", 139 "@FSBL /0x01/1*1Me", 140 "@Partition2 /0x02/1*1Me", 141 "@Partition3 /0x03/1*16Me", 142 "@Partition4 /0x04/1*16Me", 143 "@virtual /0xF1/1*512Ba" 144 }; 145 #endif 146 147 /* Buffer to build the unicode string provided to USB device stack */ 148 static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ]; 149 150 /* 151 * Convert Ascii string into unicode one 152 * desc : descriptor buffer 153 * unicode : Formatted string buffer (unicode) 154 * len : descriptor length 155 */ 156 static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len) 157 { 158 uint8_t idx = 0U; 159 160 if (desc == NULL) { 161 return; 162 } 163 164 *len = strlen(desc) * 2U + 2U; 165 unicode[idx++] = *len; 166 unicode[idx++] = USB_DESC_TYPE_STRING; 167 168 while (*desc != '\0') { 169 unicode[idx++] = *desc++; 170 unicode[idx++] = 0x00U; 171 } 172 } 173 174 /* 175 * Create the serial number string descriptor 176 */ 177 static void update_serial_num_string(void) 178 { 179 char serial_string[SIZ_STRING_SERIAL + 2U]; 180 /* serial number is set to 0 */ 181 uint32_t deviceserial[UID_WORD_NB] = { 0U, 0U, 0U }; 182 uint16_t length; 183 184 if (stm32_get_uid_otp(deviceserial) != 0) { 185 return; 186 } 187 188 /* build serial number with OTP value as in ROM code */ 189 snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X", 190 deviceserial[0], deviceserial[1], deviceserial[2]); 191 192 length = USB_SIZ_STRING_SERIAL; 193 stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length); 194 } 195 196 /* 197 * Return Device Qualifier descriptor 198 * length : pointer data length 199 * return : pointer to descriptor buffer 200 */ 201 static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length) 202 { 203 *length = sizeof(usbd_stm32mp1_qualifier_desc); 204 205 return (uint8_t *)usbd_stm32mp1_qualifier_desc; 206 } 207 208 /* 209 * Return configuration descriptor 210 * length : pointer data length 211 * return : pointer to descriptor buffer 212 */ 213 static uint8_t *stm32mp1_get_config_desc(uint16_t *length) 214 { 215 *length = sizeof(usb_stm32mp1_config_desc); 216 217 return (uint8_t *)usb_stm32mp1_config_desc; 218 } 219 220 /* 221 * Returns the device descriptor. 222 * length: Pointer to data length variable 223 * return : Pointer to descriptor buffer 224 */ 225 static uint8_t *stm32mp1_device_desc(uint16_t *length) 226 { 227 *length = sizeof(usb_stm32mp1_desc); 228 229 return (uint8_t *)usb_stm32mp1_desc; 230 } 231 232 /* 233 * Returns the LangID string descriptor. 234 * length: Pointer to data length variable 235 * return : Pointer to descriptor buffer 236 */ 237 static uint8_t *stm32mp1_lang_id_desc(uint16_t *length) 238 { 239 *length = sizeof(usb_stm32mp1_lang_id_desc); 240 241 return (uint8_t *)usb_stm32mp1_lang_id_desc; 242 } 243 244 /* 245 * Returns the product string descriptor. 246 * length: Pointer to data length variable 247 * return : Pointer to descriptor buffer 248 */ 249 static uint8_t *stm32mp1_product_desc(uint16_t *length) 250 { 251 char name[STM32_SOC_NAME_SIZE]; 252 char product[128]; 253 uint32_t chip_id; 254 uint32_t chip_version; 255 256 stm32mp_get_soc_name(name); 257 chip_id = stm32mp_get_chip_dev_id(); 258 chip_version = stm32mp_get_chip_version(); 259 260 snprintf(product, sizeof(product), 261 "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,", 262 chip_id, chip_version, name); 263 264 stm32mp1_get_string(product, usb_str_dec, length); 265 266 return usb_str_dec; 267 } 268 269 /* 270 * Returns the manufacturer string descriptor. 271 * length: Pointer to data length variable 272 * return : Pointer to descriptor buffer 273 */ 274 static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length) 275 { 276 stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length); 277 278 return usb_str_dec; 279 } 280 281 /* 282 * Returns the serial number string descriptor. 283 * length: Pointer to data length variable 284 * return : Pointer to descriptor buffer 285 */ 286 static uint8_t *stm32mp1_serial_desc(uint16_t *length) 287 { 288 *length = USB_SIZ_STRING_SERIAL; 289 290 return (uint8_t *)usb_stm32mp1_serial; 291 } 292 293 /* 294 * Returns the configuration string descriptor. 295 * length: Pointer to data length variable 296 * return : Pointer to descriptor buffer 297 */ 298 static uint8_t *stm32mp1_config_desc(uint16_t *length) 299 { 300 stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length); 301 302 return usb_str_dec; 303 } 304 305 /* 306 * Returns the interface string descriptor. 307 * length : Pointer to data length variable 308 * return : Pointer to descriptor buffer 309 */ 310 static uint8_t *stm32mp1_interface_desc(uint16_t *length) 311 { 312 stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length); 313 314 return usb_str_dec; 315 } 316 317 /* 318 * Manages the transfer of memory interfaces string descriptors. 319 * index: descriptor index 320 * length : pointer data length 321 * return : pointer to the descriptor table or NULL if the descriptor 322 * is not supported. 323 */ 324 static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length) 325 { 326 if (index >= ARRAY_SIZE(if_desc_string)) { 327 return NULL; 328 } 329 330 stm32mp1_get_string(if_desc_string[index], usb_str_dec, length); 331 332 return usb_str_dec; 333 } 334 335 static const struct usb_desc dfu_desc = { 336 .get_device_desc = stm32mp1_device_desc, 337 .get_lang_id_desc = stm32mp1_lang_id_desc, 338 .get_manufacturer_desc = stm32mp1_manufacturer_desc, 339 .get_product_desc = stm32mp1_product_desc, 340 .get_configuration_desc = stm32mp1_config_desc, 341 .get_serial_desc = stm32mp1_serial_desc, 342 .get_interface_desc = stm32mp1_interface_desc, 343 .get_usr_desc = stm32mp1_get_usr_desc, 344 .get_config_desc = stm32mp1_get_config_desc, 345 .get_device_qualifier_desc = stm32mp1_get_qualifier_desc, 346 /* only HS is supported, as ROM code */ 347 .get_other_speed_config_desc = NULL, 348 }; 349 350 static struct usb_handle usb_core_handle; 351 static struct pcd_handle pcd_handle; 352 353 struct usb_handle *usb_dfu_plat_init(void) 354 { 355 /* Prepare USB Driver */ 356 pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE; 357 pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE; 358 stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle, 359 (uint32_t *)USB_OTG_BASE); 360 361 #if STM32MP15 362 /* STM32MP15 = keep the configuration from ROM code */ 363 usb_core_handle.ep0_state = USBD_EP0_DATA_IN; 364 usb_core_handle.dev_state = USBD_STATE_CONFIGURED; 365 #endif 366 367 /* Update the serial number string descriptor from the unique ID */ 368 update_serial_num_string(); 369 370 /* Prepare USB DFU stack */ 371 usb_dfu_register(&usb_core_handle, &usb_dfu_handle); 372 373 /* Register DFU descriptor in USB stack */ 374 register_platform(&usb_core_handle, &dfu_desc); 375 376 return &usb_core_handle; 377 } 378 379 /* Link between USB alternate and STM32CubeProgramer phase */ 380 uint8_t usb_dfu_get_phase(uint8_t alt) 381 { 382 uint8_t ret; 383 384 switch (alt) { 385 #if STM32MP13 386 case 0: 387 ret = PHASE_SSBL; 388 break; 389 case 1: 390 ret = PHASE_CMD; 391 break; 392 #endif 393 #if STM32MP15 394 case 3: 395 ret = PHASE_SSBL; 396 break; 397 case 5: 398 ret = PHASE_CMD; 399 break; 400 #endif 401 default: 402 ret = PHASE_RESET; 403 break; 404 } 405 406 return ret; 407 } 408