1 /* 2 * f_dfu.c -- Device Firmware Update USB function 3 * 4 * Copyright (C) 2012 Samsung Electronics 5 * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 6 * Lukasz Majewski <l.majewski@samsung.com> 7 * 8 * Based on OpenMoko u-boot: drivers/usb/usbdfu.c 9 * (C) 2007 by OpenMoko, Inc. 10 * Author: Harald Welte <laforge@openmoko.org> 11 * 12 * based on existing SAM7DFU code from OpenPCD: 13 * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de> 14 * 15 * SPDX-License-Identifier: GPL-2.0+ 16 */ 17 18 #include <errno.h> 19 #include <common.h> 20 #include <malloc.h> 21 22 #include <linux/usb/ch9.h> 23 #include <linux/usb/gadget.h> 24 #include <linux/usb/composite.h> 25 26 #include <dfu.h> 27 #include <g_dnl.h> 28 #include "f_dfu.h" 29 30 struct f_dfu { 31 struct usb_function usb_function; 32 33 struct usb_descriptor_header **function; 34 struct usb_string *strings; 35 36 /* when configured, we have one config */ 37 u8 config; 38 u8 altsetting; 39 enum dfu_state dfu_state; 40 unsigned int dfu_status; 41 42 /* Send/received block number is handy for data integrity check */ 43 int blk_seq_num; 44 unsigned int poll_timeout; 45 }; 46 47 typedef int (*dfu_state_fn) (struct f_dfu *, 48 const struct usb_ctrlrequest *, 49 struct usb_gadget *, 50 struct usb_request *); 51 52 static inline struct f_dfu *func_to_dfu(struct usb_function *f) 53 { 54 return container_of(f, struct f_dfu, usb_function); 55 } 56 57 static const struct dfu_function_descriptor dfu_func = { 58 .bLength = sizeof dfu_func, 59 .bDescriptorType = DFU_DT_FUNC, 60 .bmAttributes = DFU_BIT_WILL_DETACH | 61 DFU_BIT_MANIFESTATION_TOLERANT | 62 DFU_BIT_CAN_UPLOAD | 63 DFU_BIT_CAN_DNLOAD, 64 .wDetachTimeOut = 0, 65 .wTransferSize = DFU_USB_BUFSIZ, 66 .bcdDFUVersion = __constant_cpu_to_le16(0x0110), 67 }; 68 69 static struct usb_interface_descriptor dfu_intf_runtime = { 70 .bLength = sizeof dfu_intf_runtime, 71 .bDescriptorType = USB_DT_INTERFACE, 72 .bNumEndpoints = 0, 73 .bInterfaceClass = USB_CLASS_APP_SPEC, 74 .bInterfaceSubClass = 1, 75 .bInterfaceProtocol = 1, 76 /* .iInterface = DYNAMIC */ 77 }; 78 79 static struct usb_descriptor_header *dfu_runtime_descs[] = { 80 (struct usb_descriptor_header *) &dfu_intf_runtime, 81 NULL, 82 }; 83 84 static const char dfu_name[] = "Device Firmware Upgrade"; 85 86 /* 87 * static strings, in UTF-8 88 * 89 * dfu_generic configuration 90 */ 91 static struct usb_string strings_dfu_generic[] = { 92 [0].s = dfu_name, 93 { } /* end of list */ 94 }; 95 96 static struct usb_gadget_strings stringtab_dfu_generic = { 97 .language = 0x0409, /* en-us */ 98 .strings = strings_dfu_generic, 99 }; 100 101 static struct usb_gadget_strings *dfu_generic_strings[] = { 102 &stringtab_dfu_generic, 103 NULL, 104 }; 105 106 /* 107 * usb_function specific 108 */ 109 static struct usb_gadget_strings stringtab_dfu = { 110 .language = 0x0409, /* en-us */ 111 /* 112 * .strings 113 * 114 * assigned during initialization, 115 * depends on number of flash entities 116 * 117 */ 118 }; 119 120 static struct usb_gadget_strings *dfu_strings[] = { 121 &stringtab_dfu, 122 NULL, 123 }; 124 125 static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms) 126 { 127 /* 128 * The bwPollTimeout DFU_GETSTATUS request payload provides information 129 * about minimum time, in milliseconds, that the host should wait before 130 * sending a subsequent DFU_GETSTATUS request 131 * 132 * This permits the device to vary the delay depending on its need to 133 * erase or program the memory 134 * 135 */ 136 137 unsigned char *p = (unsigned char *)&ms; 138 139 if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) { 140 dstat->bwPollTimeout[0] = 0; 141 dstat->bwPollTimeout[1] = 0; 142 dstat->bwPollTimeout[2] = 0; 143 144 return; 145 } 146 147 dstat->bwPollTimeout[0] = *p++; 148 dstat->bwPollTimeout[1] = *p++; 149 dstat->bwPollTimeout[2] = *p; 150 } 151 152 /*-------------------------------------------------------------------------*/ 153 154 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) 155 { 156 struct f_dfu *f_dfu = req->context; 157 int ret; 158 159 ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, 160 req->length, f_dfu->blk_seq_num); 161 if (ret) { 162 f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; 163 f_dfu->dfu_state = DFU_STATE_dfuERROR; 164 } 165 } 166 167 static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) 168 { 169 struct f_dfu *f_dfu = req->context; 170 int ret; 171 172 ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, 173 req->length, f_dfu->blk_seq_num); 174 if (ret) { 175 f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; 176 f_dfu->dfu_state = DFU_STATE_dfuERROR; 177 } 178 } 179 180 static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu) 181 { 182 return dfu->poll_timeout ? dfu->poll_timeout(dfu) : 183 DFU_MANIFEST_POLL_TIMEOUT; 184 } 185 186 static void handle_getstatus(struct usb_request *req) 187 { 188 struct dfu_status *dstat = (struct dfu_status *)req->buf; 189 struct f_dfu *f_dfu = req->context; 190 struct dfu_entity *dfu = dfu_get_entity(f_dfu->altsetting); 191 192 dfu_set_poll_timeout(dstat, 0); 193 194 switch (f_dfu->dfu_state) { 195 case DFU_STATE_dfuDNLOAD_SYNC: 196 case DFU_STATE_dfuDNBUSY: 197 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; 198 break; 199 case DFU_STATE_dfuMANIFEST_SYNC: 200 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; 201 break; 202 case DFU_STATE_dfuMANIFEST: 203 dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu)); 204 break; 205 default: 206 break; 207 } 208 209 if (f_dfu->poll_timeout) 210 if (!(f_dfu->blk_seq_num % 211 (dfu_get_buf_size() / DFU_USB_BUFSIZ))) 212 dfu_set_poll_timeout(dstat, f_dfu->poll_timeout); 213 214 /* send status response */ 215 dstat->bStatus = f_dfu->dfu_status; 216 dstat->bState = f_dfu->dfu_state; 217 dstat->iString = 0; 218 } 219 220 static void handle_getstate(struct usb_request *req) 221 { 222 struct f_dfu *f_dfu = req->context; 223 224 ((u8 *)req->buf)[0] = f_dfu->dfu_state; 225 req->actual = sizeof(u8); 226 } 227 228 static inline void to_dfu_mode(struct f_dfu *f_dfu) 229 { 230 f_dfu->usb_function.strings = dfu_strings; 231 f_dfu->usb_function.hs_descriptors = f_dfu->function; 232 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 233 } 234 235 static inline void to_runtime_mode(struct f_dfu *f_dfu) 236 { 237 f_dfu->usb_function.strings = NULL; 238 f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; 239 } 240 241 static int handle_upload(struct usb_request *req, u16 len) 242 { 243 struct f_dfu *f_dfu = req->context; 244 245 return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf, 246 req->length, f_dfu->blk_seq_num); 247 } 248 249 static int handle_dnload(struct usb_gadget *gadget, u16 len) 250 { 251 struct usb_composite_dev *cdev = get_gadget_data(gadget); 252 struct usb_request *req = cdev->req; 253 struct f_dfu *f_dfu = req->context; 254 255 if (len == 0) 256 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; 257 258 req->complete = dnload_request_complete; 259 260 return len; 261 } 262 263 /*-------------------------------------------------------------------------*/ 264 /* DFU state machine */ 265 static int state_app_idle(struct f_dfu *f_dfu, 266 const struct usb_ctrlrequest *ctrl, 267 struct usb_gadget *gadget, 268 struct usb_request *req) 269 { 270 int value = 0; 271 272 switch (ctrl->bRequest) { 273 case USB_REQ_DFU_GETSTATUS: 274 handle_getstatus(req); 275 value = RET_STAT_LEN; 276 break; 277 case USB_REQ_DFU_GETSTATE: 278 handle_getstate(req); 279 break; 280 case USB_REQ_DFU_DETACH: 281 f_dfu->dfu_state = DFU_STATE_appDETACH; 282 to_dfu_mode(f_dfu); 283 value = RET_ZLP; 284 break; 285 default: 286 value = RET_STALL; 287 break; 288 } 289 290 return value; 291 } 292 293 static int state_app_detach(struct f_dfu *f_dfu, 294 const struct usb_ctrlrequest *ctrl, 295 struct usb_gadget *gadget, 296 struct usb_request *req) 297 { 298 int value = 0; 299 300 switch (ctrl->bRequest) { 301 case USB_REQ_DFU_GETSTATUS: 302 handle_getstatus(req); 303 value = RET_STAT_LEN; 304 break; 305 case USB_REQ_DFU_GETSTATE: 306 handle_getstate(req); 307 break; 308 default: 309 f_dfu->dfu_state = DFU_STATE_appIDLE; 310 value = RET_STALL; 311 break; 312 } 313 314 return value; 315 } 316 317 static int state_dfu_idle(struct f_dfu *f_dfu, 318 const struct usb_ctrlrequest *ctrl, 319 struct usb_gadget *gadget, 320 struct usb_request *req) 321 { 322 u16 w_value = le16_to_cpu(ctrl->wValue); 323 u16 len = le16_to_cpu(ctrl->wLength); 324 int value = 0; 325 326 switch (ctrl->bRequest) { 327 case USB_REQ_DFU_DNLOAD: 328 if (len == 0) { 329 f_dfu->dfu_state = DFU_STATE_dfuERROR; 330 value = RET_STALL; 331 break; 332 } 333 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; 334 f_dfu->blk_seq_num = w_value; 335 value = handle_dnload(gadget, len); 336 break; 337 case USB_REQ_DFU_UPLOAD: 338 f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; 339 f_dfu->blk_seq_num = 0; 340 value = handle_upload(req, len); 341 break; 342 case USB_REQ_DFU_ABORT: 343 /* no zlp? */ 344 value = RET_ZLP; 345 break; 346 case USB_REQ_DFU_GETSTATUS: 347 handle_getstatus(req); 348 value = RET_STAT_LEN; 349 break; 350 case USB_REQ_DFU_GETSTATE: 351 handle_getstate(req); 352 break; 353 case USB_REQ_DFU_DETACH: 354 /* 355 * Proprietary extension: 'detach' from idle mode and 356 * get back to runtime mode in case of USB Reset. As 357 * much as I dislike this, we just can't use every USB 358 * bus reset to switch back to runtime mode, since at 359 * least the Linux USB stack likes to send a number of 360 * resets in a row :( 361 */ 362 f_dfu->dfu_state = 363 DFU_STATE_dfuMANIFEST_WAIT_RST; 364 to_runtime_mode(f_dfu); 365 f_dfu->dfu_state = DFU_STATE_appIDLE; 366 367 dfu_trigger_detach(); 368 break; 369 default: 370 f_dfu->dfu_state = DFU_STATE_dfuERROR; 371 value = RET_STALL; 372 break; 373 } 374 375 return value; 376 } 377 378 static int state_dfu_dnload_sync(struct f_dfu *f_dfu, 379 const struct usb_ctrlrequest *ctrl, 380 struct usb_gadget *gadget, 381 struct usb_request *req) 382 { 383 int value = 0; 384 385 switch (ctrl->bRequest) { 386 case USB_REQ_DFU_GETSTATUS: 387 handle_getstatus(req); 388 value = RET_STAT_LEN; 389 break; 390 case USB_REQ_DFU_GETSTATE: 391 handle_getstate(req); 392 break; 393 default: 394 f_dfu->dfu_state = DFU_STATE_dfuERROR; 395 value = RET_STALL; 396 break; 397 } 398 399 return value; 400 } 401 402 static int state_dfu_dnbusy(struct f_dfu *f_dfu, 403 const struct usb_ctrlrequest *ctrl, 404 struct usb_gadget *gadget, 405 struct usb_request *req) 406 { 407 int value = 0; 408 409 switch (ctrl->bRequest) { 410 case USB_REQ_DFU_GETSTATUS: 411 handle_getstatus(req); 412 value = RET_STAT_LEN; 413 break; 414 default: 415 f_dfu->dfu_state = DFU_STATE_dfuERROR; 416 value = RET_STALL; 417 break; 418 } 419 420 return value; 421 } 422 423 static int state_dfu_dnload_idle(struct f_dfu *f_dfu, 424 const struct usb_ctrlrequest *ctrl, 425 struct usb_gadget *gadget, 426 struct usb_request *req) 427 { 428 u16 w_value = le16_to_cpu(ctrl->wValue); 429 u16 len = le16_to_cpu(ctrl->wLength); 430 int value = 0; 431 432 switch (ctrl->bRequest) { 433 case USB_REQ_DFU_DNLOAD: 434 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; 435 f_dfu->blk_seq_num = w_value; 436 value = handle_dnload(gadget, len); 437 break; 438 case USB_REQ_DFU_ABORT: 439 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 440 value = RET_ZLP; 441 break; 442 case USB_REQ_DFU_GETSTATUS: 443 handle_getstatus(req); 444 value = RET_STAT_LEN; 445 break; 446 case USB_REQ_DFU_GETSTATE: 447 handle_getstate(req); 448 break; 449 default: 450 f_dfu->dfu_state = DFU_STATE_dfuERROR; 451 value = RET_STALL; 452 break; 453 } 454 455 return value; 456 } 457 458 static int state_dfu_manifest_sync(struct f_dfu *f_dfu, 459 const struct usb_ctrlrequest *ctrl, 460 struct usb_gadget *gadget, 461 struct usb_request *req) 462 { 463 int value = 0; 464 465 switch (ctrl->bRequest) { 466 case USB_REQ_DFU_GETSTATUS: 467 /* We're MainfestationTolerant */ 468 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; 469 handle_getstatus(req); 470 f_dfu->blk_seq_num = 0; 471 value = RET_STAT_LEN; 472 req->complete = dnload_request_flush; 473 break; 474 case USB_REQ_DFU_GETSTATE: 475 handle_getstate(req); 476 break; 477 default: 478 f_dfu->dfu_state = DFU_STATE_dfuERROR; 479 value = RET_STALL; 480 break; 481 } 482 483 return value; 484 } 485 486 static int state_dfu_manifest(struct f_dfu *f_dfu, 487 const struct usb_ctrlrequest *ctrl, 488 struct usb_gadget *gadget, 489 struct usb_request *req) 490 { 491 int value = 0; 492 493 switch (ctrl->bRequest) { 494 case USB_REQ_DFU_GETSTATUS: 495 /* We're MainfestationTolerant */ 496 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 497 handle_getstatus(req); 498 f_dfu->blk_seq_num = 0; 499 value = RET_STAT_LEN; 500 puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); 501 break; 502 case USB_REQ_DFU_GETSTATE: 503 handle_getstate(req); 504 break; 505 default: 506 f_dfu->dfu_state = DFU_STATE_dfuERROR; 507 value = RET_STALL; 508 break; 509 } 510 return value; 511 } 512 513 static int state_dfu_upload_idle(struct f_dfu *f_dfu, 514 const struct usb_ctrlrequest *ctrl, 515 struct usb_gadget *gadget, 516 struct usb_request *req) 517 { 518 u16 w_value = le16_to_cpu(ctrl->wValue); 519 u16 len = le16_to_cpu(ctrl->wLength); 520 int value = 0; 521 522 switch (ctrl->bRequest) { 523 case USB_REQ_DFU_UPLOAD: 524 /* state transition if less data then requested */ 525 f_dfu->blk_seq_num = w_value; 526 value = handle_upload(req, len); 527 if (value >= 0 && value < len) 528 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 529 break; 530 case USB_REQ_DFU_ABORT: 531 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 532 /* no zlp? */ 533 value = RET_ZLP; 534 break; 535 case USB_REQ_DFU_GETSTATUS: 536 handle_getstatus(req); 537 value = RET_STAT_LEN; 538 break; 539 case USB_REQ_DFU_GETSTATE: 540 handle_getstate(req); 541 break; 542 default: 543 f_dfu->dfu_state = DFU_STATE_dfuERROR; 544 value = RET_STALL; 545 break; 546 } 547 548 return value; 549 } 550 551 static int state_dfu_error(struct f_dfu *f_dfu, 552 const struct usb_ctrlrequest *ctrl, 553 struct usb_gadget *gadget, 554 struct usb_request *req) 555 { 556 int value = 0; 557 558 switch (ctrl->bRequest) { 559 case USB_REQ_DFU_GETSTATUS: 560 handle_getstatus(req); 561 value = RET_STAT_LEN; 562 break; 563 case USB_REQ_DFU_GETSTATE: 564 handle_getstate(req); 565 break; 566 case USB_REQ_DFU_CLRSTATUS: 567 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 568 f_dfu->dfu_status = DFU_STATUS_OK; 569 /* no zlp? */ 570 value = RET_ZLP; 571 break; 572 default: 573 f_dfu->dfu_state = DFU_STATE_dfuERROR; 574 value = RET_STALL; 575 break; 576 } 577 578 return value; 579 } 580 581 static dfu_state_fn dfu_state[] = { 582 state_app_idle, /* DFU_STATE_appIDLE */ 583 state_app_detach, /* DFU_STATE_appDETACH */ 584 state_dfu_idle, /* DFU_STATE_dfuIDLE */ 585 state_dfu_dnload_sync, /* DFU_STATE_dfuDNLOAD_SYNC */ 586 state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */ 587 state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */ 588 state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */ 589 state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */ 590 NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */ 591 state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */ 592 state_dfu_error /* DFU_STATE_dfuERROR */ 593 }; 594 595 static int 596 dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) 597 { 598 struct usb_gadget *gadget = f->config->cdev->gadget; 599 struct usb_request *req = f->config->cdev->req; 600 struct f_dfu *f_dfu = f->config->cdev->req->context; 601 u16 len = le16_to_cpu(ctrl->wLength); 602 u16 w_value = le16_to_cpu(ctrl->wValue); 603 int value = 0; 604 u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; 605 606 debug("w_value: 0x%x len: 0x%x\n", w_value, len); 607 debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n", 608 req_type, ctrl->bRequest, f_dfu->dfu_state); 609 610 if (req_type == USB_TYPE_STANDARD) { 611 if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR && 612 (w_value >> 8) == DFU_DT_FUNC) { 613 value = min(len, (u16) sizeof(dfu_func)); 614 memcpy(req->buf, &dfu_func, value); 615 } 616 } else /* DFU specific request */ 617 value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req); 618 619 if (value >= 0) { 620 req->length = value; 621 req->zero = value < len; 622 value = usb_ep_queue(gadget->ep0, req, 0); 623 if (value < 0) { 624 debug("ep_queue --> %d\n", value); 625 req->status = 0; 626 } 627 } 628 629 return value; 630 } 631 632 /*-------------------------------------------------------------------------*/ 633 634 static int 635 dfu_prepare_strings(struct f_dfu *f_dfu, int n) 636 { 637 struct dfu_entity *de = NULL; 638 int i = 0; 639 640 f_dfu->strings = calloc(sizeof(struct usb_string), n + 1); 641 if (!f_dfu->strings) 642 goto enomem; 643 644 for (i = 0; i < n; ++i) { 645 de = dfu_get_entity(i); 646 f_dfu->strings[i].s = de->name; 647 } 648 649 f_dfu->strings[i].id = 0; 650 f_dfu->strings[i].s = NULL; 651 652 return 0; 653 654 enomem: 655 while (i) 656 f_dfu->strings[--i].s = NULL; 657 658 free(f_dfu->strings); 659 660 return -ENOMEM; 661 } 662 663 static int dfu_prepare_function(struct f_dfu *f_dfu, int n) 664 { 665 struct usb_interface_descriptor *d; 666 int i = 0; 667 668 f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1); 669 if (!f_dfu->function) 670 goto enomem; 671 672 for (i = 0; i < n; ++i) { 673 d = calloc(sizeof(*d), 1); 674 if (!d) 675 goto enomem; 676 677 d->bLength = sizeof(*d); 678 d->bDescriptorType = USB_DT_INTERFACE; 679 d->bAlternateSetting = i; 680 d->bNumEndpoints = 0; 681 d->bInterfaceClass = USB_CLASS_APP_SPEC; 682 d->bInterfaceSubClass = 1; 683 d->bInterfaceProtocol = 2; 684 685 f_dfu->function[i] = (struct usb_descriptor_header *)d; 686 } 687 f_dfu->function[i] = NULL; 688 689 return 0; 690 691 enomem: 692 while (i) { 693 free(f_dfu->function[--i]); 694 f_dfu->function[i] = NULL; 695 } 696 free(f_dfu->function); 697 698 return -ENOMEM; 699 } 700 701 static int dfu_bind(struct usb_configuration *c, struct usb_function *f) 702 { 703 struct usb_composite_dev *cdev = c->cdev; 704 struct f_dfu *f_dfu = func_to_dfu(f); 705 int alt_num = dfu_get_alt_number(); 706 int rv, id, i; 707 708 id = usb_interface_id(c, f); 709 if (id < 0) 710 return id; 711 dfu_intf_runtime.bInterfaceNumber = id; 712 713 f_dfu->dfu_state = DFU_STATE_appIDLE; 714 f_dfu->dfu_status = DFU_STATUS_OK; 715 716 rv = dfu_prepare_function(f_dfu, alt_num); 717 if (rv) 718 goto error; 719 720 rv = dfu_prepare_strings(f_dfu, alt_num); 721 if (rv) 722 goto error; 723 for (i = 0; i < alt_num; i++) { 724 id = usb_string_id(cdev); 725 if (id < 0) 726 return id; 727 f_dfu->strings[i].id = id; 728 ((struct usb_interface_descriptor *)f_dfu->function[i]) 729 ->iInterface = id; 730 } 731 732 to_dfu_mode(f_dfu); 733 734 stringtab_dfu.strings = f_dfu->strings; 735 736 cdev->req->context = f_dfu; 737 738 error: 739 return rv; 740 } 741 742 static void dfu_unbind(struct usb_configuration *c, struct usb_function *f) 743 { 744 struct f_dfu *f_dfu = func_to_dfu(f); 745 int alt_num = dfu_get_alt_number(); 746 int i; 747 748 if (f_dfu->strings) { 749 i = alt_num; 750 while (i) 751 f_dfu->strings[--i].s = NULL; 752 753 free(f_dfu->strings); 754 } 755 756 if (f_dfu->function) { 757 i = alt_num; 758 while (i) { 759 free(f_dfu->function[--i]); 760 f_dfu->function[i] = NULL; 761 } 762 free(f_dfu->function); 763 } 764 765 free(f_dfu); 766 } 767 768 static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 769 { 770 struct f_dfu *f_dfu = func_to_dfu(f); 771 772 debug("%s: intf:%d alt:%d\n", __func__, intf, alt); 773 774 f_dfu->altsetting = alt; 775 f_dfu->dfu_state = DFU_STATE_dfuIDLE; 776 f_dfu->dfu_status = DFU_STATUS_OK; 777 778 return 0; 779 } 780 781 /* TODO: is this really what we need here? */ 782 static void dfu_disable(struct usb_function *f) 783 { 784 struct f_dfu *f_dfu = func_to_dfu(f); 785 if (f_dfu->config == 0) 786 return; 787 788 debug("%s: reset config\n", __func__); 789 790 f_dfu->config = 0; 791 } 792 793 static int dfu_bind_config(struct usb_configuration *c) 794 { 795 struct f_dfu *f_dfu; 796 int status; 797 798 f_dfu = calloc(sizeof(*f_dfu), 1); 799 if (!f_dfu) 800 return -ENOMEM; 801 f_dfu->usb_function.name = "dfu"; 802 f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; 803 f_dfu->usb_function.bind = dfu_bind; 804 f_dfu->usb_function.unbind = dfu_unbind; 805 f_dfu->usb_function.set_alt = dfu_set_alt; 806 f_dfu->usb_function.disable = dfu_disable; 807 f_dfu->usb_function.strings = dfu_generic_strings; 808 f_dfu->usb_function.setup = dfu_handle; 809 f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT; 810 811 status = usb_add_function(c, &f_dfu->usb_function); 812 if (status) 813 free(f_dfu); 814 815 return status; 816 } 817 818 int dfu_add(struct usb_configuration *c) 819 { 820 int id; 821 822 id = usb_string_id(c->cdev); 823 if (id < 0) 824 return id; 825 strings_dfu_generic[0].id = id; 826 dfu_intf_runtime.iInterface = id; 827 828 debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__, 829 c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); 830 831 return dfu_bind_config(c); 832 } 833 834 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add); 835