1 /* 2 * f_sdp.c -- USB HID Serial Download Protocol 3 * 4 * Copyright (C) 2017 Toradex 5 * Author: Stefan Agner <stefan.agner@toradex.com> 6 * 7 * This file implements the Serial Download Protocol (SDP) as specified in 8 * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and 9 * allows to download images directly to memory. The implementation 10 * works with the imx_loader (imx_usb) USB client software on host side. 11 * 12 * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and 13 * SKIP_DCD_HEADER are only stubs. 14 * 15 * Parts of the implementation are based on f_dfu and f_thor. 16 * 17 * SPDX-License-Identifier: GPL-2.0+ 18 */ 19 20 #include <errno.h> 21 #include <common.h> 22 #include <console.h> 23 #include <malloc.h> 24 25 #include <linux/usb/ch9.h> 26 #include <linux/usb/gadget.h> 27 #include <linux/usb/composite.h> 28 29 #include <asm/io.h> 30 #include <g_dnl.h> 31 #include <sdp.h> 32 #include <spl.h> 33 #include <image.h> 34 #include <imximage.h> 35 #include <watchdog.h> 36 37 #define HID_REPORT_ID_MASK 0x000000ff 38 39 /* 40 * HID class requests 41 */ 42 #define HID_REQ_GET_REPORT 0x01 43 #define HID_REQ_GET_IDLE 0x02 44 #define HID_REQ_GET_PROTOCOL 0x03 45 #define HID_REQ_SET_REPORT 0x09 46 #define HID_REQ_SET_IDLE 0x0A 47 #define HID_REQ_SET_PROTOCOL 0x0B 48 49 #define HID_USAGE_PAGE_LEN 76 50 51 struct hid_report { 52 u8 usage_page[HID_USAGE_PAGE_LEN]; 53 } __packed; 54 55 #define SDP_READ_REGISTER 0x0101 56 #define SDP_WRITE_REGISTER 0x0202 57 #define SDP_WRITE_FILE 0x0404 58 #define SDP_ERROR_STATUS 0x0505 59 #define SDP_DCD_WRITE 0x0a0a 60 #define SDP_JUMP_ADDRESS 0x0b0b 61 #define SDP_SKIP_DCD_HEADER 0x0c0c 62 63 #define SDP_SECURITY_CLOSED 0x12343412 64 #define SDP_SECURITY_OPEN 0x56787856 65 66 #define SDP_WRITE_FILE_COMPLETE 0x88888888 67 #define SDP_WRITE_REGISTER_COMPLETE 0x128A8A12 68 #define SDP_SKIP_DCD_HEADER_COMPLETE 0x900DD009 69 #define SDP_ERROR_IMXHEADER 0x000a0533 70 71 #define SDP_COMMAND_LEN 16 72 73 struct sdp_command { 74 u16 cmd; 75 u32 addr; 76 u8 format; 77 u32 cnt; 78 u32 data; 79 u8 rsvd; 80 } __packed; 81 82 enum sdp_state { 83 SDP_STATE_IDLE, 84 SDP_STATE_RX_DCD_DATA, 85 SDP_STATE_RX_FILE_DATA, 86 SDP_STATE_TX_SEC_CONF, 87 SDP_STATE_TX_SEC_CONF_BUSY, 88 SDP_STATE_TX_REGISTER, 89 SDP_STATE_TX_REGISTER_BUSY, 90 SDP_STATE_TX_STATUS, 91 SDP_STATE_TX_STATUS_BUSY, 92 SDP_STATE_JUMP, 93 }; 94 95 struct f_sdp { 96 struct usb_function usb_function; 97 98 struct usb_descriptor_header **function; 99 100 u8 altsetting; 101 enum sdp_state state; 102 enum sdp_state next_state; 103 u32 dnl_address; 104 u32 dnl_bytes_remaining; 105 u32 jmp_address; 106 bool always_send_status; 107 u32 error_status; 108 109 /* EP0 request */ 110 struct usb_request *req; 111 112 /* EP1 IN */ 113 struct usb_ep *in_ep; 114 struct usb_request *in_req; 115 116 bool configuration_done; 117 }; 118 119 static struct f_sdp *sdp_func; 120 121 static inline struct f_sdp *func_to_sdp(struct usb_function *f) 122 { 123 return container_of(f, struct f_sdp, usb_function); 124 } 125 126 static struct usb_interface_descriptor sdp_intf_runtime = { 127 .bLength = sizeof(sdp_intf_runtime), 128 .bDescriptorType = USB_DT_INTERFACE, 129 .bAlternateSetting = 0, 130 .bNumEndpoints = 1, 131 .bInterfaceClass = USB_CLASS_HID, 132 .bInterfaceSubClass = 0, 133 .bInterfaceProtocol = 0, 134 /* .iInterface = DYNAMIC */ 135 }; 136 137 /* HID configuration */ 138 static struct usb_class_hid_descriptor sdp_hid_desc = { 139 .bLength = sizeof(sdp_hid_desc), 140 .bDescriptorType = USB_DT_CS_DEVICE, 141 142 .bcdCDC = __constant_cpu_to_le16(0x0110), 143 .bCountryCode = 0, 144 .bNumDescriptors = 1, 145 146 .bDescriptorType0 = USB_DT_HID_REPORT, 147 .wDescriptorLength0 = HID_USAGE_PAGE_LEN, 148 }; 149 150 static struct usb_endpoint_descriptor in_desc = { 151 .bLength = USB_DT_ENDPOINT_SIZE, 152 .bDescriptorType = USB_DT_ENDPOINT, /*USB_DT_CS_ENDPOINT*/ 153 154 .bEndpointAddress = 1 | USB_DIR_IN, 155 .bmAttributes = USB_ENDPOINT_XFER_INT, 156 .wMaxPacketSize = 64, 157 .bInterval = 1, 158 }; 159 160 static struct usb_descriptor_header *sdp_runtime_descs[] = { 161 (struct usb_descriptor_header *)&sdp_intf_runtime, 162 (struct usb_descriptor_header *)&sdp_hid_desc, 163 (struct usb_descriptor_header *)&in_desc, 164 NULL, 165 }; 166 167 /* This is synchronized with what the SoC implementation reports */ 168 static struct hid_report sdp_hid_report = { 169 .usage_page = { 170 0x06, 0x00, 0xff, /* Usage Page */ 171 0x09, 0x01, /* Usage (Pointer?) */ 172 0xa1, 0x01, /* Collection */ 173 174 0x85, 0x01, /* Report ID */ 175 0x19, 0x01, /* Usage Minimum */ 176 0x29, 0x01, /* Usage Maximum */ 177 0x15, 0x00, /* Local Minimum */ 178 0x26, 0xFF, 0x00, /* Local Maximum? */ 179 0x75, 0x08, /* Report Size */ 180 0x95, 0x10, /* Report Count */ 181 0x91, 0x02, /* Output Data */ 182 183 0x85, 0x02, /* Report ID */ 184 0x19, 0x01, /* Usage Minimum */ 185 0x29, 0x01, /* Usage Maximum */ 186 0x15, 0x00, /* Local Minimum */ 187 0x26, 0xFF, 0x00, /* Local Maximum? */ 188 0x75, 0x80, /* Report Size 128 */ 189 0x95, 0x40, /* Report Count */ 190 0x91, 0x02, /* Output Data */ 191 192 0x85, 0x03, /* Report ID */ 193 0x19, 0x01, /* Usage Minimum */ 194 0x29, 0x01, /* Usage Maximum */ 195 0x15, 0x00, /* Local Minimum */ 196 0x26, 0xFF, 0x00, /* Local Maximum? */ 197 0x75, 0x08, /* Report Size 8 */ 198 0x95, 0x04, /* Report Count */ 199 0x81, 0x02, /* Input Data */ 200 201 0x85, 0x04, /* Report ID */ 202 0x19, 0x01, /* Usage Minimum */ 203 0x29, 0x01, /* Usage Maximum */ 204 0x15, 0x00, /* Local Minimum */ 205 0x26, 0xFF, 0x00, /* Local Maximum? */ 206 0x75, 0x08, /* Report Size 8 */ 207 0x95, 0x40, /* Report Count */ 208 0x81, 0x02, /* Input Data */ 209 0xc0 210 }, 211 }; 212 213 static const char sdp_name[] = "Serial Downloader Protocol"; 214 215 /* 216 * static strings, in UTF-8 217 */ 218 static struct usb_string strings_sdp_generic[] = { 219 [0].s = sdp_name, 220 { } /* end of list */ 221 }; 222 223 static struct usb_gadget_strings stringtab_sdp_generic = { 224 .language = 0x0409, /* en-us */ 225 .strings = strings_sdp_generic, 226 }; 227 228 static struct usb_gadget_strings *sdp_generic_strings[] = { 229 &stringtab_sdp_generic, 230 NULL, 231 }; 232 233 static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req) 234 { 235 struct f_sdp *sdp = req->context; 236 int status = req->status; 237 u8 *data = req->buf; 238 u8 report = data[0]; 239 240 if (status != 0) { 241 pr_err("Status: %d", status); 242 return; 243 } 244 245 if (report != 1) { 246 pr_err("Unexpected report %d", report); 247 return; 248 } 249 250 struct sdp_command *cmd = req->buf + 1; 251 252 debug("%s: command: %04x, addr: %08x, cnt: %u\n", 253 __func__, be16_to_cpu(cmd->cmd), 254 be32_to_cpu(cmd->addr), be32_to_cpu(cmd->cnt)); 255 256 switch (be16_to_cpu(cmd->cmd)) { 257 case SDP_READ_REGISTER: 258 sdp->always_send_status = false; 259 sdp->error_status = 0x0; 260 261 sdp->state = SDP_STATE_TX_SEC_CONF; 262 sdp->dnl_address = be32_to_cpu(cmd->addr); 263 sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); 264 sdp->next_state = SDP_STATE_TX_REGISTER; 265 printf("Reading %d registers at 0x%08x... ", 266 sdp->dnl_bytes_remaining, sdp->dnl_address); 267 break; 268 case SDP_WRITE_FILE: 269 sdp->always_send_status = true; 270 sdp->error_status = SDP_WRITE_FILE_COMPLETE; 271 272 sdp->state = SDP_STATE_RX_FILE_DATA; 273 sdp->dnl_address = be32_to_cpu(cmd->addr); 274 sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); 275 sdp->next_state = SDP_STATE_IDLE; 276 277 printf("Downloading file of size %d to 0x%08x... ", 278 sdp->dnl_bytes_remaining, sdp->dnl_address); 279 280 break; 281 case SDP_ERROR_STATUS: 282 sdp->always_send_status = true; 283 sdp->error_status = 0; 284 285 sdp->state = SDP_STATE_TX_SEC_CONF; 286 sdp->next_state = SDP_STATE_IDLE; 287 break; 288 case SDP_DCD_WRITE: 289 sdp->always_send_status = true; 290 sdp->error_status = SDP_WRITE_REGISTER_COMPLETE; 291 292 sdp->state = SDP_STATE_RX_DCD_DATA; 293 sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); 294 sdp->next_state = SDP_STATE_IDLE; 295 break; 296 case SDP_JUMP_ADDRESS: 297 sdp->always_send_status = false; 298 sdp->error_status = 0; 299 300 sdp->jmp_address = be32_to_cpu(cmd->addr); 301 sdp->state = SDP_STATE_TX_SEC_CONF; 302 sdp->next_state = SDP_STATE_JUMP; 303 break; 304 case SDP_SKIP_DCD_HEADER: 305 sdp->always_send_status = true; 306 sdp->error_status = SDP_SKIP_DCD_HEADER_COMPLETE; 307 308 /* Ignore command, DCD not supported anyway */ 309 sdp->state = SDP_STATE_TX_SEC_CONF; 310 sdp->next_state = SDP_STATE_IDLE; 311 break; 312 default: 313 pr_err("Unknown command: %04x\n", be16_to_cpu(cmd->cmd)); 314 } 315 } 316 317 static void sdp_rx_data_complete(struct usb_ep *ep, struct usb_request *req) 318 { 319 struct f_sdp *sdp = req->context; 320 int status = req->status; 321 u8 *data = req->buf; 322 u8 report = data[0]; 323 int datalen = req->length - 1; 324 325 if (status != 0) { 326 pr_err("Status: %d", status); 327 return; 328 } 329 330 if (report != 2) { 331 pr_err("Unexpected report %d", report); 332 return; 333 } 334 335 if (sdp->dnl_bytes_remaining < datalen) { 336 /* 337 * Some USB stacks require to send a complete buffer as 338 * specified in the HID descriptor. This leads to longer 339 * transfers than the file length, no problem for us. 340 */ 341 sdp->dnl_bytes_remaining = 0; 342 } else { 343 sdp->dnl_bytes_remaining -= datalen; 344 } 345 346 if (sdp->state == SDP_STATE_RX_FILE_DATA) { 347 memcpy((void *)sdp->dnl_address, req->buf + 1, datalen); 348 sdp->dnl_address += datalen; 349 } 350 351 if (sdp->dnl_bytes_remaining) 352 return; 353 354 printf("done\n"); 355 356 switch (sdp->state) { 357 case SDP_STATE_RX_FILE_DATA: 358 sdp->state = SDP_STATE_TX_SEC_CONF; 359 break; 360 case SDP_STATE_RX_DCD_DATA: 361 sdp->state = SDP_STATE_TX_SEC_CONF; 362 break; 363 default: 364 pr_err("Invalid state: %d", sdp->state); 365 } 366 } 367 368 static void sdp_tx_complete(struct usb_ep *ep, struct usb_request *req) 369 { 370 struct f_sdp *sdp = req->context; 371 int status = req->status; 372 373 if (status != 0) { 374 pr_err("Status: %d", status); 375 return; 376 } 377 378 switch (sdp->state) { 379 case SDP_STATE_TX_SEC_CONF_BUSY: 380 /* Not all commands require status report */ 381 if (sdp->always_send_status || sdp->error_status) 382 sdp->state = SDP_STATE_TX_STATUS; 383 else 384 sdp->state = sdp->next_state; 385 386 break; 387 case SDP_STATE_TX_STATUS_BUSY: 388 sdp->state = sdp->next_state; 389 break; 390 case SDP_STATE_TX_REGISTER_BUSY: 391 if (sdp->dnl_bytes_remaining) 392 sdp->state = SDP_STATE_TX_REGISTER; 393 else 394 sdp->state = SDP_STATE_IDLE; 395 break; 396 default: 397 pr_err("Wrong State: %d", sdp->state); 398 sdp->state = SDP_STATE_IDLE; 399 break; 400 } 401 debug("%s complete --> %d, %d/%d\n", ep->name, 402 status, req->actual, req->length); 403 } 404 405 static int sdp_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) 406 { 407 struct usb_gadget *gadget = f->config->cdev->gadget; 408 struct usb_request *req = f->config->cdev->req; 409 struct f_sdp *sdp = f->config->cdev->req->context; 410 u16 len = le16_to_cpu(ctrl->wLength); 411 u16 w_value = le16_to_cpu(ctrl->wValue); 412 int value = 0; 413 u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; 414 415 debug("w_value: 0x%04x len: 0x%04x\n", w_value, len); 416 debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n", 417 req_type, ctrl->bRequest, sdp->state); 418 419 if (req_type == USB_TYPE_STANDARD) { 420 if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR) { 421 /* Send HID report descriptor */ 422 value = min(len, (u16) sizeof(sdp_hid_report)); 423 memcpy(req->buf, &sdp_hid_report, value); 424 sdp->configuration_done = true; 425 } 426 } 427 428 if (req_type == USB_TYPE_CLASS) { 429 int report = w_value & HID_REPORT_ID_MASK; 430 431 /* HID (SDP) request */ 432 switch (ctrl->bRequest) { 433 case HID_REQ_SET_REPORT: 434 switch (report) { 435 case 1: 436 value = SDP_COMMAND_LEN + 1; 437 req->complete = sdp_rx_command_complete; 438 break; 439 case 2: 440 value = len; 441 req->complete = sdp_rx_data_complete; 442 break; 443 } 444 } 445 } 446 447 if (value >= 0) { 448 req->length = value; 449 req->zero = value < len; 450 value = usb_ep_queue(gadget->ep0, req, 0); 451 if (value < 0) { 452 debug("ep_queue --> %d\n", value); 453 req->status = 0; 454 } 455 } 456 457 return value; 458 } 459 460 static int sdp_bind(struct usb_configuration *c, struct usb_function *f) 461 { 462 struct usb_gadget *gadget = c->cdev->gadget; 463 struct usb_composite_dev *cdev = c->cdev; 464 struct f_sdp *sdp = func_to_sdp(f); 465 int rv = 0, id; 466 467 id = usb_interface_id(c, f); 468 if (id < 0) 469 return id; 470 sdp_intf_runtime.bInterfaceNumber = id; 471 472 struct usb_ep *ep; 473 474 /* allocate instance-specific endpoints */ 475 ep = usb_ep_autoconfig(gadget, &in_desc); 476 if (!ep) { 477 rv = -ENODEV; 478 goto error; 479 } 480 481 sdp->in_ep = ep; /* Store IN EP for enabling @ setup */ 482 483 cdev->req->context = sdp; 484 485 error: 486 return rv; 487 } 488 489 static void sdp_unbind(struct usb_configuration *c, struct usb_function *f) 490 { 491 free(sdp_func); 492 sdp_func = NULL; 493 } 494 495 static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) 496 { 497 struct usb_request *req; 498 499 req = usb_ep_alloc_request(ep, 0); 500 if (!req) 501 return req; 502 503 req->length = length; 504 req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length); 505 if (!req->buf) { 506 usb_ep_free_request(ep, req); 507 req = NULL; 508 } 509 510 return req; 511 } 512 513 514 static struct usb_request *sdp_start_ep(struct usb_ep *ep) 515 { 516 struct usb_request *req; 517 518 req = alloc_ep_req(ep, 64); 519 debug("%s: ep:%p req:%p\n", __func__, ep, req); 520 521 if (!req) 522 return NULL; 523 524 memset(req->buf, 0, req->length); 525 req->complete = sdp_tx_complete; 526 527 return req; 528 } 529 static int sdp_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 530 { 531 struct f_sdp *sdp = func_to_sdp(f); 532 struct usb_composite_dev *cdev = f->config->cdev; 533 int result; 534 535 debug("%s: intf: %d alt: %d\n", __func__, intf, alt); 536 537 result = usb_ep_enable(sdp->in_ep, &in_desc); 538 if (result) 539 return result; 540 sdp->in_req = sdp_start_ep(sdp->in_ep); 541 sdp->in_req->context = sdp; 542 543 sdp->in_ep->driver_data = cdev; /* claim */ 544 545 sdp->altsetting = alt; 546 sdp->state = SDP_STATE_IDLE; 547 548 return 0; 549 } 550 551 static int sdp_get_alt(struct usb_function *f, unsigned intf) 552 { 553 struct f_sdp *sdp = func_to_sdp(f); 554 555 return sdp->altsetting; 556 } 557 558 static void sdp_disable(struct usb_function *f) 559 { 560 struct f_sdp *sdp = func_to_sdp(f); 561 562 usb_ep_disable(sdp->in_ep); 563 564 if (sdp->in_req) { 565 free(sdp->in_req); 566 sdp->in_req = NULL; 567 } 568 } 569 570 static int sdp_bind_config(struct usb_configuration *c) 571 { 572 int status; 573 574 if (!sdp_func) { 575 sdp_func = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*sdp_func)); 576 if (!sdp_func) 577 return -ENOMEM; 578 } 579 580 memset(sdp_func, 0, sizeof(*sdp_func)); 581 582 sdp_func->usb_function.name = "sdp"; 583 sdp_func->usb_function.hs_descriptors = sdp_runtime_descs; 584 sdp_func->usb_function.descriptors = sdp_runtime_descs; 585 sdp_func->usb_function.bind = sdp_bind; 586 sdp_func->usb_function.unbind = sdp_unbind; 587 sdp_func->usb_function.set_alt = sdp_set_alt; 588 sdp_func->usb_function.get_alt = sdp_get_alt; 589 sdp_func->usb_function.disable = sdp_disable; 590 sdp_func->usb_function.strings = sdp_generic_strings; 591 sdp_func->usb_function.setup = sdp_setup; 592 593 status = usb_add_function(c, &sdp_func->usb_function); 594 595 return status; 596 } 597 598 int sdp_init(int controller_index) 599 { 600 printf("SDP: initialize...\n"); 601 while (!sdp_func->configuration_done) { 602 if (ctrlc()) { 603 puts("\rCTRL+C - Operation aborted.\n"); 604 return 1; 605 } 606 607 WATCHDOG_RESET(); 608 usb_gadget_handle_interrupts(controller_index); 609 } 610 611 return 0; 612 } 613 614 static u32 sdp_jump_imxheader(void *address) 615 { 616 flash_header_v2_t *headerv2 = address; 617 ulong (*entry)(void); 618 619 if (headerv2->header.tag != IVT_HEADER_TAG) { 620 printf("Header Tag is not an IMX image\n"); 621 return SDP_ERROR_IMXHEADER; 622 } 623 624 printf("Jumping to 0x%08x\n", headerv2->entry); 625 entry = (void *)headerv2->entry; 626 entry(); 627 628 /* The image probably never returns hence we won't reach that point */ 629 return 0; 630 } 631 632 static void sdp_handle_in_ep(void) 633 { 634 u8 *data = sdp_func->in_req->buf; 635 u32 status; 636 int datalen; 637 638 switch (sdp_func->state) { 639 case SDP_STATE_TX_SEC_CONF: 640 debug("Report 3: HAB security\n"); 641 data[0] = 3; 642 643 status = SDP_SECURITY_OPEN; 644 memcpy(&data[1], &status, 4); 645 sdp_func->in_req->length = 5; 646 usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); 647 sdp_func->state = SDP_STATE_TX_SEC_CONF_BUSY; 648 break; 649 650 case SDP_STATE_TX_STATUS: 651 debug("Report 4: Status\n"); 652 data[0] = 4; 653 654 memcpy(&data[1], &sdp_func->error_status, 4); 655 sdp_func->in_req->length = 65; 656 usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); 657 sdp_func->state = SDP_STATE_TX_STATUS_BUSY; 658 break; 659 case SDP_STATE_TX_REGISTER: 660 debug("Report 4: Register Values\n"); 661 data[0] = 4; 662 663 datalen = sdp_func->dnl_bytes_remaining; 664 665 if (datalen > 64) 666 datalen = 64; 667 668 memcpy(&data[1], (void *)sdp_func->dnl_address, datalen); 669 sdp_func->in_req->length = 65; 670 671 sdp_func->dnl_bytes_remaining -= datalen; 672 sdp_func->dnl_address += datalen; 673 674 usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); 675 sdp_func->state = SDP_STATE_TX_REGISTER_BUSY; 676 break; 677 case SDP_STATE_JUMP: 678 printf("Jumping to header at 0x%08x\n", sdp_func->jmp_address); 679 status = sdp_jump_imxheader((void *)sdp_func->jmp_address); 680 681 /* If imx header fails, try some U-Boot specific headers */ 682 if (status) { 683 #ifdef CONFIG_SPL_BUILD 684 /* In SPL, allow jumps to U-Boot images */ 685 struct spl_image_info spl_image = {}; 686 spl_parse_image_header(&spl_image, 687 (struct image_header *)sdp_func->jmp_address); 688 jump_to_image_no_args(&spl_image); 689 #else 690 /* In U-Boot, allow jumps to scripts */ 691 source(sdp_func->jmp_address, "script@1"); 692 #endif 693 } 694 695 sdp_func->next_state = SDP_STATE_IDLE; 696 sdp_func->error_status = status; 697 698 /* Only send Report 4 if there was an error */ 699 if (status) 700 sdp_func->state = SDP_STATE_TX_STATUS; 701 else 702 sdp_func->state = SDP_STATE_IDLE; 703 break; 704 default: 705 break; 706 }; 707 } 708 709 void sdp_handle(int controller_index) 710 { 711 printf("SDP: handle requests...\n"); 712 while (1) { 713 if (ctrlc()) { 714 puts("\rCTRL+C - Operation aborted.\n"); 715 return; 716 } 717 718 WATCHDOG_RESET(); 719 usb_gadget_handle_interrupts(controller_index); 720 721 sdp_handle_in_ep(); 722 } 723 } 724 725 int sdp_add(struct usb_configuration *c) 726 { 727 int id; 728 729 id = usb_string_id(c->cdev); 730 if (id < 0) 731 return id; 732 strings_sdp_generic[0].id = id; 733 sdp_intf_runtime.iInterface = id; 734 735 debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__, 736 c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); 737 738 return sdp_bind_config(c); 739 } 740 741 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp, sdp_add); 742