1 /* 2 * Copyright (c) 2021-2025, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <errno.h> 8 #include <string.h> 9 10 #include <common/debug.h> 11 #include <drivers/delay_timer.h> 12 13 #include <platform_def.h> 14 #include <usb_dfu.h> 15 16 /* Device states as defined in DFU spec */ 17 #define STATE_APP_IDLE 0 18 #define STATE_APP_DETACH 1 19 #define STATE_DFU_IDLE 2 20 #define STATE_DFU_DNLOAD_SYNC 3 21 #define STATE_DFU_DNLOAD_BUSY 4 22 #define STATE_DFU_DNLOAD_IDLE 5 23 #define STATE_DFU_MANIFEST_SYNC 6 24 #define STATE_DFU_MANIFEST 7 25 #define STATE_DFU_MANIFEST_WAIT_RESET 8 26 #define STATE_DFU_UPLOAD_IDLE 9 27 #define STATE_DFU_ERROR 10 28 29 /* DFU errors */ 30 #define DFU_ERROR_NONE 0x00 31 #define DFU_ERROR_TARGET 0x01 32 #define DFU_ERROR_FILE 0x02 33 #define DFU_ERROR_WRITE 0x03 34 #define DFU_ERROR_ERASE 0x04 35 #define DFU_ERROR_CHECK_ERASED 0x05 36 #define DFU_ERROR_PROG 0x06 37 #define DFU_ERROR_VERIFY 0x07 38 #define DFU_ERROR_ADDRESS 0x08 39 #define DFU_ERROR_NOTDONE 0x09 40 #define DFU_ERROR_FIRMWARE 0x0A 41 #define DFU_ERROR_VENDOR 0x0B 42 #define DFU_ERROR_USB 0x0C 43 #define DFU_ERROR_POR 0x0D 44 #define DFU_ERROR_UNKNOWN 0x0E 45 #define DFU_ERROR_STALLEDPKT 0x0F 46 47 /* DFU request */ 48 #define DFU_DETACH 0 49 #define DFU_DNLOAD 1 50 #define DFU_UPLOAD 2 51 #define DFU_GETSTATUS 3 52 #define DFU_CLRSTATUS 4 53 #define DFU_GETSTATE 5 54 #define DFU_ABORT 6 55 56 static bool usb_dfu_detach_req; 57 static uint64_t detach_timeout; 58 59 /* 60 * usb_dfu_init 61 * Initialize the DFU interface 62 * pdev: device instance 63 * cfgidx: Configuration index 64 * return: status 65 */ 66 static uint8_t usb_dfu_init(struct usb_handle *pdev, uint8_t cfgidx) 67 { 68 (void)pdev; 69 (void)cfgidx; 70 71 /* Nothing to do in this stage */ 72 return USBD_OK; 73 } 74 75 /* 76 * usb_dfu_de_init 77 * De-Initialize the DFU layer 78 * pdev: device instance 79 * cfgidx: Configuration index 80 * return: status 81 */ 82 static uint8_t usb_dfu_de_init(struct usb_handle *pdev, uint8_t cfgidx) 83 { 84 (void)pdev; 85 (void)cfgidx; 86 87 /* Nothing to do in this stage */ 88 return USBD_OK; 89 } 90 91 /* 92 * usb_dfu_data_in 93 * handle data IN Stage 94 * pdev: device instance 95 * epnum: endpoint index 96 * return: status 97 */ 98 static uint8_t usb_dfu_data_in(struct usb_handle *pdev, uint8_t epnum) 99 { 100 (void)pdev; 101 (void)epnum; 102 103 return USBD_OK; 104 } 105 106 /* 107 * usb_dfu_ep0_rx_ready 108 * handle EP0 Rx Ready event 109 * pdev: device 110 * return: status 111 */ 112 static uint8_t usb_dfu_ep0_rx_ready(struct usb_handle *pdev) 113 { 114 (void)pdev; 115 116 return USBD_OK; 117 } 118 119 /* 120 * usb_dfu_ep0_tx_ready 121 * handle EP0 TRx Ready event 122 * pdev: device instance 123 * return: status 124 */ 125 static uint8_t usb_dfu_ep0_tx_ready(struct usb_handle *pdev) 126 { 127 (void)pdev; 128 129 return USBD_OK; 130 } 131 132 /* 133 * usb_dfu_sof 134 * handle SOF event 135 * pdev: device instance 136 * return: status 137 */ 138 static uint8_t usb_dfu_sof(struct usb_handle *pdev) 139 { 140 (void)pdev; 141 142 return USBD_OK; 143 } 144 145 /* 146 * usb_dfu_iso_in_incomplete 147 * handle data ISO IN Incomplete event 148 * pdev: device instance 149 * epnum: endpoint index 150 * return: status 151 */ 152 static uint8_t usb_dfu_iso_in_incomplete(struct usb_handle *pdev, uint8_t epnum) 153 { 154 (void)pdev; 155 (void)epnum; 156 157 return USBD_OK; 158 } 159 160 /* 161 * usb_dfu_iso_out_incomplete 162 * handle data ISO OUT Incomplete event 163 * pdev: device instance 164 * epnum: endpoint index 165 * return: status 166 */ 167 static uint8_t usb_dfu_iso_out_incomplete(struct usb_handle *pdev, 168 uint8_t epnum) 169 { 170 (void)pdev; 171 (void)epnum; 172 173 return USBD_OK; 174 } 175 176 /* 177 * usb_dfu_data_out 178 * handle data OUT Stage 179 * pdev: device instance 180 * epnum: endpoint index 181 * return: status 182 */ 183 static uint8_t usb_dfu_data_out(struct usb_handle *pdev, uint8_t epnum) 184 { 185 (void)pdev; 186 (void)epnum; 187 188 return USBD_OK; 189 } 190 191 /* 192 * usb_dfu_detach 193 * Handles the DFU DETACH request. 194 * pdev: device instance 195 * req: pointer to the request structure. 196 */ 197 static void usb_dfu_detach(struct usb_handle *pdev, struct usb_setup_req *req) 198 { 199 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 200 201 INFO("Receive DFU Detach\n"); 202 203 if ((hdfu->dev_state == STATE_DFU_IDLE) || 204 (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) || 205 (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) || 206 (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) || 207 (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) { 208 /* Update the state machine */ 209 hdfu->dev_state = STATE_DFU_IDLE; 210 hdfu->dev_status = DFU_ERROR_NONE; 211 } 212 213 /* Timeout that lets the core handle interrupts before detach */ 214 detach_timeout = timeout_init_us(100); /* usec */ 215 usb_dfu_detach_req = true; 216 } 217 218 /* 219 * usb_dfu_download 220 * Handles the DFU DNLOAD request. 221 * pdev: device instance 222 * req: pointer to the request structure 223 */ 224 static void usb_dfu_download(struct usb_handle *pdev, struct usb_setup_req *req) 225 { 226 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 227 uintptr_t data_ptr; 228 uint32_t length; 229 int ret; 230 231 /* Data setup request */ 232 if (req->length > 0) { 233 /* Unsupported state */ 234 if ((hdfu->dev_state != STATE_DFU_IDLE) && 235 (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE)) { 236 /* Call the error management function (command will be nacked) */ 237 usb_core_ctl_error(pdev); 238 return; 239 } 240 241 /* Get the data address */ 242 length = req->length; 243 ret = hdfu->callback->download(hdfu->alt_setting, &data_ptr, 244 &length, pdev->user_data); 245 if (ret == 0U) { 246 /* Update the state machine */ 247 hdfu->dev_state = STATE_DFU_DNLOAD_SYNC; 248 /* Start the transfer */ 249 usb_core_receive_ep0(pdev, (uint8_t *)data_ptr, length); 250 } else { 251 usb_core_ctl_error(pdev); 252 } 253 } else { 254 /* End of DNLOAD operation*/ 255 if (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE) { 256 /* Call the error management function (command will be nacked) */ 257 usb_core_ctl_error(pdev); 258 return; 259 } 260 /* End of DNLOAD operation*/ 261 hdfu->dev_state = STATE_DFU_MANIFEST_SYNC; 262 ret = hdfu->callback->manifestation(hdfu->alt_setting, pdev->user_data); 263 if (ret == 0U) { 264 hdfu->dev_state = STATE_DFU_MANIFEST_SYNC; 265 } else { 266 usb_core_ctl_error(pdev); 267 } 268 } 269 } 270 271 /* 272 * usb_dfu_upload 273 * Handles the DFU UPLOAD request. 274 * pdev: instance 275 * req: pointer to the request structure 276 */ 277 static void usb_dfu_upload(struct usb_handle *pdev, struct usb_setup_req *req) 278 { 279 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 280 uintptr_t data_ptr; 281 uint32_t length; 282 int ret; 283 284 /* Data setup request */ 285 if (req->length == 0) { 286 /* No Data setup request */ 287 hdfu->dev_state = STATE_DFU_IDLE; 288 return; 289 } 290 291 /* Unsupported state */ 292 if ((hdfu->dev_state != STATE_DFU_IDLE) && (hdfu->dev_state != STATE_DFU_UPLOAD_IDLE)) { 293 ERROR("UPLOAD : Unsupported State\n"); 294 /* Call the error management function (command will be nacked) */ 295 usb_core_ctl_error(pdev); 296 return; 297 } 298 299 /* Update the data address */ 300 length = req->length; 301 ret = hdfu->callback->upload(hdfu->alt_setting, &data_ptr, &length, pdev->user_data); 302 if (ret == 0U) { 303 /* Short frame */ 304 hdfu->dev_state = (req->length > length) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; 305 306 /* Start the transfer */ 307 usb_core_transmit_ep0(pdev, (uint8_t *)data_ptr, length); 308 } else { 309 ERROR("UPLOAD : bad block %i on alt %i\n", req->value, req->index); 310 hdfu->dev_state = STATE_DFU_ERROR; 311 hdfu->dev_status = DFU_ERROR_STALLEDPKT; 312 313 /* Call the error management function (command will be nacked) */ 314 usb_core_ctl_error(pdev); 315 } 316 } 317 318 /* 319 * usb_dfu_get_status 320 * Handles the DFU GETSTATUS request. 321 * pdev: instance 322 */ 323 static void usb_dfu_get_status(struct usb_handle *pdev) 324 { 325 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 326 327 hdfu->status[0] = hdfu->dev_status; /* bStatus */ 328 hdfu->status[1] = 0; /* bwPollTimeout[3] */ 329 hdfu->status[2] = 0; 330 hdfu->status[3] = 0; 331 hdfu->status[4] = hdfu->dev_state; /* bState */ 332 hdfu->status[5] = 0; /* iString */ 333 334 /* next step */ 335 switch (hdfu->dev_state) { 336 case STATE_DFU_DNLOAD_SYNC: 337 hdfu->dev_state = STATE_DFU_DNLOAD_IDLE; 338 break; 339 case STATE_DFU_MANIFEST_SYNC: 340 /* the device is 'ManifestationTolerant' */ 341 hdfu->status[4] = STATE_DFU_MANIFEST; 342 hdfu->status[1] = 1U; /* bwPollTimeout = 1ms */ 343 hdfu->dev_state = STATE_DFU_IDLE; 344 break; 345 346 default: 347 break; 348 } 349 350 /* Start the transfer */ 351 usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->status[0], sizeof(hdfu->status)); 352 } 353 354 /* 355 * usb_dfu_clear_status 356 * Handles the DFU CLRSTATUS request. 357 * pdev: device instance 358 */ 359 static void usb_dfu_clear_status(struct usb_handle *pdev) 360 { 361 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 362 363 if (hdfu->dev_state == STATE_DFU_ERROR) { 364 hdfu->dev_state = STATE_DFU_IDLE; 365 hdfu->dev_status = DFU_ERROR_NONE; 366 } else { 367 /* State Error */ 368 hdfu->dev_state = STATE_DFU_ERROR; 369 hdfu->dev_status = DFU_ERROR_UNKNOWN; 370 } 371 } 372 373 /* 374 * usb_dfu_get_state 375 * Handles the DFU GETSTATE request. 376 * pdev: device instance 377 */ 378 static void usb_dfu_get_state(struct usb_handle *pdev) 379 { 380 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 381 382 /* Return the current state of the DFU interface */ 383 usb_core_transmit_ep0(pdev, &hdfu->dev_state, 1); 384 } 385 386 /* 387 * usb_dfu_abort 388 * Handles the DFU ABORT request. 389 * pdev: device instance 390 */ 391 static void usb_dfu_abort(struct usb_handle *pdev) 392 { 393 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 394 395 if ((hdfu->dev_state == STATE_DFU_IDLE) || 396 (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) || 397 (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) || 398 (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) || 399 (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) { 400 hdfu->dev_state = STATE_DFU_IDLE; 401 hdfu->dev_status = DFU_ERROR_NONE; 402 } 403 } 404 405 /* 406 * usb_dfu_setup 407 * Handle the DFU specific requests 408 * pdev: instance 409 * req: usb requests 410 * return: status 411 */ 412 static uint8_t usb_dfu_setup(struct usb_handle *pdev, struct usb_setup_req *req) 413 { 414 uint8_t *pbuf = NULL; 415 uint16_t len = 0U; 416 uint8_t ret = USBD_OK; 417 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 418 419 switch (req->bm_request & USB_REQ_TYPE_MASK) { 420 case USB_REQ_TYPE_CLASS: 421 switch (req->b_request) { 422 case DFU_DNLOAD: 423 usb_dfu_download(pdev, req); 424 break; 425 426 case DFU_UPLOAD: 427 usb_dfu_upload(pdev, req); 428 break; 429 430 case DFU_GETSTATUS: 431 usb_dfu_get_status(pdev); 432 break; 433 434 case DFU_CLRSTATUS: 435 usb_dfu_clear_status(pdev); 436 break; 437 438 case DFU_GETSTATE: 439 usb_dfu_get_state(pdev); 440 break; 441 442 case DFU_ABORT: 443 usb_dfu_abort(pdev); 444 break; 445 446 case DFU_DETACH: 447 usb_dfu_detach(pdev, req); 448 break; 449 450 default: 451 ERROR("unknown request %x on alternate %i\n", 452 req->b_request, hdfu->alt_setting); 453 usb_core_ctl_error(pdev); 454 ret = USBD_FAIL; 455 break; 456 } 457 break; 458 case USB_REQ_TYPE_STANDARD: 459 switch (req->b_request) { 460 case USB_REQ_GET_DESCRIPTOR: 461 if (HIBYTE(req->value) == DFU_DESCRIPTOR_TYPE) { 462 pbuf = pdev->desc->get_config_desc(&len); 463 /* DFU descriptor at the end of the USB */ 464 pbuf += len - 9U; 465 len = 9U; 466 len = MIN(len, req->length); 467 } 468 469 /* Start the transfer */ 470 usb_core_transmit_ep0(pdev, pbuf, len); 471 472 break; 473 474 case USB_REQ_GET_INTERFACE: 475 /* Start the transfer */ 476 usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->alt_setting, 1U); 477 break; 478 479 case USB_REQ_SET_INTERFACE: 480 hdfu->alt_setting = LOBYTE(req->value); 481 break; 482 483 default: 484 usb_core_ctl_error(pdev); 485 ret = USBD_FAIL; 486 break; 487 } 488 default: 489 break; 490 } 491 492 return ret; 493 } 494 495 static const struct usb_class usb_dfu = { 496 .init = usb_dfu_init, 497 .de_init = usb_dfu_de_init, 498 .setup = usb_dfu_setup, 499 .ep0_tx_sent = usb_dfu_ep0_tx_ready, 500 .ep0_rx_ready = usb_dfu_ep0_rx_ready, 501 .data_in = usb_dfu_data_in, 502 .data_out = usb_dfu_data_out, 503 .sof = usb_dfu_sof, 504 .iso_in_incomplete = usb_dfu_iso_in_incomplete, 505 .iso_out_incomplete = usb_dfu_iso_out_incomplete, 506 }; 507 508 void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle) 509 { 510 pdev->class = (struct usb_class *)&usb_dfu; 511 pdev->class_data = phandle; 512 513 phandle->dev_state = STATE_DFU_IDLE; 514 phandle->dev_status = DFU_ERROR_NONE; 515 } 516 517 int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia) 518 { 519 enum usb_status ret; 520 struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; 521 522 hdfu->callback = pmedia; 523 usb_dfu_detach_req = false; 524 525 /* DFU infinite loop until DETACH_REQ */ 526 for (;;) { 527 ret = usb_core_handle_it(pdev); 528 if (ret != USBD_OK) { 529 return -EIO; 530 } 531 532 /* 533 * Detach request received, continue to handle USB core IT 534 * to assure complete data transmission 535 */ 536 if (usb_dfu_detach_req && timeout_elapsed(detach_timeout)) { 537 break; 538 } 539 } 540 541 return 0; 542 } 543