| .. | .. |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling |
|---|
| 4 | 4 | * |
|---|
| 5 | | - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com |
|---|
| 5 | + * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com |
|---|
| 6 | 6 | * |
|---|
| 7 | 7 | * Authors: Felipe Balbi <balbi@ti.com>, |
|---|
| 8 | 8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
|---|
| .. | .. |
|---|
| 105 | 105 | * IRQ we were waiting for is long gone. |
|---|
| 106 | 106 | */ |
|---|
| 107 | 107 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { |
|---|
| 108 | | - unsigned direction; |
|---|
| 108 | + unsigned int direction; |
|---|
| 109 | 109 | |
|---|
| 110 | 110 | direction = !!(dep->flags & DWC3_EP0_DIR_IN); |
|---|
| 111 | 111 | |
|---|
| .. | .. |
|---|
| 127 | 127 | * handle it here. |
|---|
| 128 | 128 | */ |
|---|
| 129 | 129 | if (dwc->delayed_status) { |
|---|
| 130 | | - unsigned direction; |
|---|
| 130 | + unsigned int direction; |
|---|
| 131 | 131 | |
|---|
| 132 | 132 | direction = !dwc->ep0_expect_in; |
|---|
| 133 | 133 | dwc->delayed_status = false; |
|---|
| 134 | | - usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); |
|---|
| 134 | + usb_gadget_set_state(dwc->gadget, USB_STATE_CONFIGURED); |
|---|
| 135 | 135 | |
|---|
| 136 | 136 | if (dwc->ep0state == EP0_STATUS_PHASE) |
|---|
| 137 | 137 | __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); |
|---|
| .. | .. |
|---|
| 172 | 172 | * XferNotReady(STATUS). |
|---|
| 173 | 173 | */ |
|---|
| 174 | 174 | if (dwc->three_stage_setup) { |
|---|
| 175 | | - unsigned direction; |
|---|
| 175 | + unsigned int direction; |
|---|
| 176 | 176 | |
|---|
| 177 | 177 | direction = dwc->ep0_expect_in; |
|---|
| 178 | 178 | dwc->ep0state = EP0_DATA_PHASE; |
|---|
| .. | .. |
|---|
| 197 | 197 | int ret; |
|---|
| 198 | 198 | |
|---|
| 199 | 199 | spin_lock_irqsave(&dwc->lock, flags); |
|---|
| 200 | | - if (!dep->endpoint.desc) { |
|---|
| 200 | + if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) { |
|---|
| 201 | 201 | dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", |
|---|
| 202 | 202 | dep->name); |
|---|
| 203 | 203 | ret = -ESHUTDOWN; |
|---|
| .. | .. |
|---|
| 218 | 218 | return ret; |
|---|
| 219 | 219 | } |
|---|
| 220 | 220 | |
|---|
| 221 | | -static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) |
|---|
| 221 | +void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) |
|---|
| 222 | 222 | { |
|---|
| 223 | 223 | struct dwc3_ep *dep; |
|---|
| 224 | 224 | |
|---|
| .. | .. |
|---|
| 239 | 239 | dwc3_gadget_giveback(dep, req, -ECONNRESET); |
|---|
| 240 | 240 | } |
|---|
| 241 | 241 | |
|---|
| 242 | + dwc->eps[0]->trb_enqueue = 0; |
|---|
| 243 | + dwc->eps[1]->trb_enqueue = 0; |
|---|
| 242 | 244 | dwc->ep0state = EP0_SETUP_PHASE; |
|---|
| 243 | 245 | dwc3_ep0_out_start(dwc); |
|---|
| 244 | 246 | } |
|---|
| .. | .. |
|---|
| 271 | 273 | { |
|---|
| 272 | 274 | struct dwc3_ep *dep; |
|---|
| 273 | 275 | int ret; |
|---|
| 276 | + int i; |
|---|
| 274 | 277 | |
|---|
| 275 | 278 | complete(&dwc->ep0_in_setup); |
|---|
| 276 | 279 | |
|---|
| .. | .. |
|---|
| 279 | 282 | DWC3_TRBCTL_CONTROL_SETUP, false); |
|---|
| 280 | 283 | ret = dwc3_ep0_start_trans(dep); |
|---|
| 281 | 284 | WARN_ON(ret < 0); |
|---|
| 285 | + for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) { |
|---|
| 286 | + struct dwc3_ep *dwc3_ep; |
|---|
| 287 | + |
|---|
| 288 | + dwc3_ep = dwc->eps[i]; |
|---|
| 289 | + if (!dwc3_ep) |
|---|
| 290 | + continue; |
|---|
| 291 | + |
|---|
| 292 | + if (!(dwc3_ep->flags & DWC3_EP_DELAY_STOP)) |
|---|
| 293 | + continue; |
|---|
| 294 | + |
|---|
| 295 | + dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP; |
|---|
| 296 | + if (dwc->connected) |
|---|
| 297 | + dwc3_stop_active_transfer(dwc3_ep, true, true); |
|---|
| 298 | + else |
|---|
| 299 | + dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN); |
|---|
| 300 | + } |
|---|
| 282 | 301 | } |
|---|
| 283 | 302 | |
|---|
| 284 | 303 | static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le) |
|---|
| 285 | 304 | { |
|---|
| 286 | | - struct dwc3_ep *dep = NULL; |
|---|
| 305 | + struct dwc3_ep *dep; |
|---|
| 287 | 306 | u32 windex = le16_to_cpu(wIndex_le); |
|---|
| 288 | | - u32 epnum, ep_index; |
|---|
| 289 | | - u8 num, direction; |
|---|
| 307 | + u32 ep, epnum; |
|---|
| 308 | + u8 num_in_eps, num_out_eps, min_eps; |
|---|
| 290 | 309 | |
|---|
| 291 | | - epnum = windex & USB_ENDPOINT_NUMBER_MASK; |
|---|
| 292 | | - direction = windex & USB_ENDPOINT_DIR_MASK; |
|---|
| 293 | | - ep_index = 0; |
|---|
| 310 | + num_in_eps = DWC3_NUM_IN_EPS(&dwc->hwparams); |
|---|
| 311 | + num_out_eps = dwc->num_eps - num_in_eps; |
|---|
| 312 | + min_eps = min_t(u8, num_in_eps, num_out_eps); |
|---|
| 313 | + ep = windex & USB_ENDPOINT_NUMBER_MASK; |
|---|
| 294 | 314 | |
|---|
| 295 | | - for (num = 0; num < dwc->num_eps; num++) { |
|---|
| 296 | | - dep = dwc->eps[num]; |
|---|
| 297 | | - if (!dep) { |
|---|
| 298 | | - dev_warn(dwc->dev, "dep is NULL, num %d, windex 0x%08x\n", |
|---|
| 299 | | - num, windex); |
|---|
| 300 | | - return NULL; |
|---|
| 301 | | - } |
|---|
| 315 | + if (ep + 1 > min_eps && num_in_eps != num_out_eps) { |
|---|
| 316 | + epnum = ep + min_eps; |
|---|
| 302 | 317 | |
|---|
| 303 | | - if ((direction == USB_DIR_IN && dep->direction) || |
|---|
| 304 | | - (direction == USB_DIR_OUT && !dep->direction)) |
|---|
| 305 | | - ep_index++; |
|---|
| 306 | | - |
|---|
| 307 | | - if (ep_index == epnum + 1) |
|---|
| 308 | | - break; |
|---|
| 318 | + } else { |
|---|
| 319 | + epnum = ep << 1; |
|---|
| 320 | + if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) |
|---|
| 321 | + epnum |= 1; |
|---|
| 309 | 322 | } |
|---|
| 310 | 323 | |
|---|
| 324 | + dep = dwc->eps[epnum]; |
|---|
| 325 | + if (dep == NULL) |
|---|
| 326 | + return NULL; |
|---|
| 311 | 327 | |
|---|
| 312 | | - if (dep && (dep->flags & DWC3_EP_ENABLED)) |
|---|
| 328 | + if (dep->flags & DWC3_EP_ENABLED) |
|---|
| 313 | 329 | return dep; |
|---|
| 314 | 330 | |
|---|
| 315 | 331 | return NULL; |
|---|
| .. | .. |
|---|
| 342 | 358 | /* |
|---|
| 343 | 359 | * LTM will be set once we know how to set this in HW. |
|---|
| 344 | 360 | */ |
|---|
| 345 | | - usb_status |= dwc->gadget.is_selfpowered; |
|---|
| 361 | + usb_status |= dwc->gadget->is_selfpowered; |
|---|
| 346 | 362 | |
|---|
| 347 | 363 | if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || |
|---|
| 348 | 364 | (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { |
|---|
| .. | .. |
|---|
| 396 | 412 | if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && |
|---|
| 397 | 413 | (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) |
|---|
| 398 | 414 | return -EINVAL; |
|---|
| 415 | + if (set && dwc->dis_u1_entry_quirk) |
|---|
| 416 | + return -EINVAL; |
|---|
| 399 | 417 | |
|---|
| 400 | 418 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
|---|
| 401 | | - if (set && !dwc->dis_u1u2_quirk) |
|---|
| 419 | + if (set) |
|---|
| 402 | 420 | reg |= DWC3_DCTL_INITU1ENA; |
|---|
| 403 | 421 | else |
|---|
| 404 | 422 | reg &= ~DWC3_DCTL_INITU1ENA; |
|---|
| .. | .. |
|---|
| 418 | 436 | if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && |
|---|
| 419 | 437 | (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS)) |
|---|
| 420 | 438 | return -EINVAL; |
|---|
| 439 | + if (set && dwc->dis_u2_entry_quirk) |
|---|
| 440 | + return -EINVAL; |
|---|
| 421 | 441 | |
|---|
| 422 | 442 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
|---|
| 423 | | - if (set && !dwc->dis_u1u2_quirk) |
|---|
| 443 | + if (set) |
|---|
| 424 | 444 | reg |= DWC3_DCTL_INITU2ENA; |
|---|
| 425 | 445 | else |
|---|
| 426 | 446 | reg &= ~DWC3_DCTL_INITU2ENA; |
|---|
| .. | .. |
|---|
| 438 | 458 | return -EINVAL; |
|---|
| 439 | 459 | |
|---|
| 440 | 460 | switch (wIndex >> 8) { |
|---|
| 441 | | - case TEST_J: |
|---|
| 442 | | - case TEST_K: |
|---|
| 443 | | - case TEST_SE0_NAK: |
|---|
| 444 | | - case TEST_PACKET: |
|---|
| 445 | | - case TEST_FORCE_EN: |
|---|
| 461 | + case USB_TEST_J: |
|---|
| 462 | + case USB_TEST_K: |
|---|
| 463 | + case USB_TEST_SE0_NAK: |
|---|
| 464 | + case USB_TEST_PACKET: |
|---|
| 465 | + case USB_TEST_FORCE_ENABLE: |
|---|
| 446 | 466 | dwc->test_mode_nr = wIndex >> 8; |
|---|
| 447 | 467 | dwc->test_mode = true; |
|---|
| 448 | 468 | break; |
|---|
| .. | .. |
|---|
| 463 | 483 | |
|---|
| 464 | 484 | wValue = le16_to_cpu(ctrl->wValue); |
|---|
| 465 | 485 | wIndex = le16_to_cpu(ctrl->wIndex); |
|---|
| 466 | | - state = dwc->gadget.state; |
|---|
| 486 | + state = dwc->gadget->state; |
|---|
| 467 | 487 | |
|---|
| 468 | 488 | switch (wValue) { |
|---|
| 469 | 489 | case USB_DEVICE_REMOTE_WAKEUP: |
|---|
| 470 | 490 | break; |
|---|
| 471 | 491 | /* |
|---|
| 472 | | - * 9.4.1 says only only for SS, in AddressState only for |
|---|
| 492 | + * 9.4.1 says only for SS, in AddressState only for |
|---|
| 473 | 493 | * default control pipe |
|---|
| 474 | 494 | */ |
|---|
| 475 | 495 | case USB_DEVICE_U1_ENABLE: |
|---|
| .. | .. |
|---|
| 537 | 557 | ret = __dwc3_gadget_ep_set_halt(dep, set, true); |
|---|
| 538 | 558 | if (ret) |
|---|
| 539 | 559 | return -EINVAL; |
|---|
| 560 | + |
|---|
| 561 | + /* ClearFeature(Halt) may need delayed status */ |
|---|
| 562 | + if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) |
|---|
| 563 | + return USB_GADGET_DELAYED_STATUS; |
|---|
| 564 | + |
|---|
| 540 | 565 | break; |
|---|
| 541 | 566 | default: |
|---|
| 542 | 567 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 572 | 597 | |
|---|
| 573 | 598 | static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
|---|
| 574 | 599 | { |
|---|
| 575 | | - enum usb_device_state state = dwc->gadget.state; |
|---|
| 600 | + enum usb_device_state state = dwc->gadget->state; |
|---|
| 576 | 601 | u32 addr; |
|---|
| 577 | 602 | u32 reg; |
|---|
| 578 | 603 | |
|---|
| .. | .. |
|---|
| 593 | 618 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); |
|---|
| 594 | 619 | |
|---|
| 595 | 620 | if (addr) |
|---|
| 596 | | - usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); |
|---|
| 621 | + usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS); |
|---|
| 597 | 622 | else |
|---|
| 598 | | - usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); |
|---|
| 623 | + usb_gadget_set_state(dwc->gadget, USB_STATE_DEFAULT); |
|---|
| 599 | 624 | |
|---|
| 600 | 625 | return 0; |
|---|
| 601 | 626 | } |
|---|
| 602 | 627 | |
|---|
| 603 | 628 | static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
|---|
| 604 | 629 | { |
|---|
| 605 | | - int ret; |
|---|
| 630 | + int ret = -EINVAL; |
|---|
| 606 | 631 | |
|---|
| 607 | | - spin_unlock(&dwc->lock); |
|---|
| 608 | | - ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); |
|---|
| 609 | | - spin_lock(&dwc->lock); |
|---|
| 632 | + if (dwc->async_callbacks) { |
|---|
| 633 | + spin_unlock(&dwc->lock); |
|---|
| 634 | + ret = dwc->gadget_driver->setup(dwc->gadget, ctrl); |
|---|
| 635 | + spin_lock(&dwc->lock); |
|---|
| 636 | + } |
|---|
| 610 | 637 | return ret; |
|---|
| 611 | 638 | } |
|---|
| 612 | 639 | |
|---|
| 613 | 640 | static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
|---|
| 614 | 641 | { |
|---|
| 615 | | - enum usb_device_state state = dwc->gadget.state; |
|---|
| 642 | + enum usb_device_state state = dwc->gadget->state; |
|---|
| 616 | 643 | u32 cfg; |
|---|
| 617 | 644 | int ret; |
|---|
| 618 | 645 | u32 reg; |
|---|
| .. | .. |
|---|
| 624 | 651 | return -EINVAL; |
|---|
| 625 | 652 | |
|---|
| 626 | 653 | case USB_STATE_ADDRESS: |
|---|
| 654 | + dwc3_gadget_clear_tx_fifos(dwc); |
|---|
| 655 | + |
|---|
| 627 | 656 | ret = dwc3_ep0_delegate_req(dwc, ctrl); |
|---|
| 628 | 657 | /* if the cfg matches and the cfg is non zero */ |
|---|
| 629 | 658 | if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { |
|---|
| .. | .. |
|---|
| 635 | 664 | * to change the state on the next usb_ep_queue() |
|---|
| 636 | 665 | */ |
|---|
| 637 | 666 | if (ret == 0) |
|---|
| 638 | | - usb_gadget_set_state(&dwc->gadget, |
|---|
| 667 | + usb_gadget_set_state(dwc->gadget, |
|---|
| 639 | 668 | USB_STATE_CONFIGURED); |
|---|
| 640 | 669 | |
|---|
| 641 | 670 | /* |
|---|
| .. | .. |
|---|
| 643 | 672 | * nothing is pending from application. |
|---|
| 644 | 673 | */ |
|---|
| 645 | 674 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
|---|
| 646 | | - if (dwc->dis_u1u2_quirk) |
|---|
| 647 | | - reg &= ~(DWC3_DCTL_ACCEPTU1ENA | |
|---|
| 648 | | - DWC3_DCTL_ACCEPTU2ENA); |
|---|
| 649 | | - else |
|---|
| 650 | | - reg |= (DWC3_DCTL_ACCEPTU1ENA | |
|---|
| 651 | | - DWC3_DCTL_ACCEPTU2ENA); |
|---|
| 675 | + if (!dwc->dis_u1_entry_quirk) |
|---|
| 676 | + reg |= DWC3_DCTL_ACCEPTU1ENA; |
|---|
| 677 | + if (!dwc->dis_u2_entry_quirk) |
|---|
| 678 | + reg |= DWC3_DCTL_ACCEPTU2ENA; |
|---|
| 652 | 679 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
|---|
| 653 | 680 | } |
|---|
| 654 | 681 | break; |
|---|
| .. | .. |
|---|
| 656 | 683 | case USB_STATE_CONFIGURED: |
|---|
| 657 | 684 | ret = dwc3_ep0_delegate_req(dwc, ctrl); |
|---|
| 658 | 685 | if (!cfg && !ret) |
|---|
| 659 | | - usb_gadget_set_state(&dwc->gadget, |
|---|
| 686 | + usb_gadget_set_state(dwc->gadget, |
|---|
| 660 | 687 | USB_STATE_ADDRESS); |
|---|
| 661 | 688 | break; |
|---|
| 662 | 689 | default: |
|---|
| .. | .. |
|---|
| 712 | 739 | static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
|---|
| 713 | 740 | { |
|---|
| 714 | 741 | struct dwc3_ep *dep; |
|---|
| 715 | | - enum usb_device_state state = dwc->gadget.state; |
|---|
| 742 | + enum usb_device_state state = dwc->gadget->state; |
|---|
| 716 | 743 | u16 wLength; |
|---|
| 717 | 744 | |
|---|
| 718 | 745 | if (state == USB_STATE_DEFAULT) |
|---|
| .. | .. |
|---|
| 756 | 783 | if (wIndex || wLength) |
|---|
| 757 | 784 | return -EINVAL; |
|---|
| 758 | 785 | |
|---|
| 759 | | - dwc->gadget.isoch_delay = wValue; |
|---|
| 786 | + dwc->gadget->isoch_delay = wValue; |
|---|
| 760 | 787 | |
|---|
| 761 | 788 | return 0; |
|---|
| 762 | 789 | } |
|---|
| .. | .. |
|---|
| 801 | 828 | struct usb_ctrlrequest *ctrl = (void *) dwc->ep0_trb; |
|---|
| 802 | 829 | int ret = -EINVAL; |
|---|
| 803 | 830 | u32 len; |
|---|
| 831 | + struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc); |
|---|
| 804 | 832 | |
|---|
| 805 | | - if (!dwc->gadget_driver) |
|---|
| 833 | + if (!dwc->gadget_driver || !vdwc->softconnect || !dwc->connected) |
|---|
| 806 | 834 | goto out; |
|---|
| 807 | 835 | |
|---|
| 808 | 836 | trace_dwc3_ctrl_req(ctrl); |
|---|
| .. | .. |
|---|
| 1064 | 1092 | __dwc3_ep0_do_control_status(dwc, dep); |
|---|
| 1065 | 1093 | } |
|---|
| 1066 | 1094 | |
|---|
| 1067 | | -static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) |
|---|
| 1095 | +void dwc3_ep0_send_delayed_status(struct dwc3 *dwc) |
|---|
| 1096 | +{ |
|---|
| 1097 | + unsigned int direction = !dwc->ep0_expect_in; |
|---|
| 1098 | + struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc); |
|---|
| 1099 | + |
|---|
| 1100 | + dwc->delayed_status = false; |
|---|
| 1101 | + vdwc->clear_stall_protocol = 0; |
|---|
| 1102 | + |
|---|
| 1103 | + if (dwc->ep0state != EP0_STATUS_PHASE) |
|---|
| 1104 | + return; |
|---|
| 1105 | + |
|---|
| 1106 | + __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); |
|---|
| 1107 | +} |
|---|
| 1108 | + |
|---|
| 1109 | +void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) |
|---|
| 1068 | 1110 | { |
|---|
| 1069 | 1111 | struct dwc3_gadget_ep_cmd_params params; |
|---|
| 1070 | 1112 | u32 cmd; |
|---|
| 1071 | 1113 | int ret; |
|---|
| 1072 | 1114 | |
|---|
| 1073 | | - if (!dep->resource_index) |
|---|
| 1115 | + /* |
|---|
| 1116 | + * For status/DATA OUT stage, TRB will be queued on ep0 out |
|---|
| 1117 | + * endpoint for which resource index is zero. Hence allow |
|---|
| 1118 | + * queuing ENDXFER command for ep0 out endpoint. |
|---|
| 1119 | + */ |
|---|
| 1120 | + if (!dep->resource_index && dep->number) |
|---|
| 1074 | 1121 | return; |
|---|
| 1075 | 1122 | |
|---|
| 1076 | 1123 | cmd = DWC3_DEPCMD_ENDTRANSFER; |
|---|
| .. | .. |
|---|
| 1085 | 1132 | static void dwc3_ep0_xfernotready(struct dwc3 *dwc, |
|---|
| 1086 | 1133 | const struct dwc3_event_depevt *event) |
|---|
| 1087 | 1134 | { |
|---|
| 1135 | + struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc); |
|---|
| 1136 | + |
|---|
| 1088 | 1137 | switch (event->status) { |
|---|
| 1089 | 1138 | case DEPEVT_STATUS_CONTROL_DATA: |
|---|
| 1139 | + if (!vdwc->softconnect || !dwc->connected) |
|---|
| 1140 | + return; |
|---|
| 1090 | 1141 | /* |
|---|
| 1091 | 1142 | * We already have a DATA transfer in the controller's cache, |
|---|
| 1092 | 1143 | * if we receive a XferNotReady(DATA) we will ignore it, unless |
|---|
| .. | .. |
|---|
| 1111 | 1162 | if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) |
|---|
| 1112 | 1163 | return; |
|---|
| 1113 | 1164 | |
|---|
| 1165 | + if (dwc->setup_packet_pending) { |
|---|
| 1166 | + dwc3_ep0_stall_and_restart(dwc); |
|---|
| 1167 | + return; |
|---|
| 1168 | + } |
|---|
| 1169 | + |
|---|
| 1114 | 1170 | dwc->ep0state = EP0_STATUS_PHASE; |
|---|
| 1115 | 1171 | |
|---|
| 1116 | 1172 | if (dwc->delayed_status) { |
|---|
| .. | .. |
|---|
| 1124 | 1180 | */ |
|---|
| 1125 | 1181 | if (!list_empty(&dep->pending_list)) { |
|---|
| 1126 | 1182 | dwc->delayed_status = false; |
|---|
| 1127 | | - usb_gadget_set_state(&dwc->gadget, |
|---|
| 1183 | + usb_gadget_set_state(dwc->gadget, |
|---|
| 1128 | 1184 | USB_STATE_CONFIGURED); |
|---|
| 1129 | 1185 | dwc3_ep0_do_control_status(dwc, event); |
|---|
| 1130 | 1186 | } |
|---|