/* Dispatch an incoming Setup packet according to its type */ static void handle_setup(enum table_case tc) { struct usb_setup_packet *req = cur_out_desc->addr; int data_phase_in = req->bmRequestType & USB_DIR_IN; int data_phase_out = !data_phase_in && req->wLength; int bytes = -1; /* default is to stall */ print_later("R: %02x %02x %04x %04x %04x", req->bmRequestType, req->bRequest, req->wValue, req->wIndex, req->wLength); if (0 == (req->bmRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))) { /* Standard Device requests */ if (data_phase_in) bytes = handle_setup_with_in_stage(tc, req); else if (data_phase_out) bytes = handle_setup_with_out_stage(tc, req); else bytes = handle_setup_with_no_data_stage(tc, req); } else if (USB_RECIP_INTERFACE == (req->bmRequestType & USB_RECIP_MASK)) { /* Interface-specific requests */ uint8_t iface = req->wIndex & 0xff; print_later("iface %d request (vs %d)", iface, USB_IFACE_COUNT, 0, 0, 0); if (iface < USB_IFACE_COUNT) { bytes = usb_iface_request[iface](req); print_later(" iface returned %d", bytes, 0, 0, 0, 0); } } else { /* Something we need to add support for? */ report_error(-1); } print_later("data_phase_in %d data_phase_out %d bytes %d", !!data_phase_in, !!data_phase_out, bytes, 0, 0); /* We say "no" to unsupported and intentionally unhandled requests by * stalling the Data and/or Status stage. */ if (bytes < 0) { /* Stall both IN and OUT. SETUP will come through anyway. */ stall_both_fifos(); } else { if (data_phase_in) expect_data_phase_in(tc); else if (data_phase_out) expect_data_phase_out(tc); else expect_status_phase_in(tc); } }
static void expect_data_phase_out(enum table_case tc) { print_later("expect_data_phase_out(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); /* TODO: This is not yet supported */ report_error(tc); expect_setup_packet(); }
/* Now put those constants into the correct registers */ static void setup_data_fifos(void) { int i; print_later("setup_data_fifos()", 0, 0, 0, 0, 0); /* Programmer's Guide, p31 */ GR_USB_GRXFSIZ = RXFIFO_SIZE; /* RXFIFO */ GR_USB_GNPTXFSIZ = (TXFIFO_SIZE << 16) | RXFIFO_SIZE; /* TXFIFO 0 */ /* TXFIFO 1..15 */ for (i = 1; i < MAX_NORMAL_EPS; i++) GR_USB_DIEPTXF(i) = ((TXFIFO_SIZE << 16) | (RXFIFO_SIZE + i * TXFIFO_SIZE)); /* * TODO: The Programmer's Guide is confusing about when or whether to * flush the FIFOs. Section 2.1.1.2 (p31) just says to flush. Section * 2.2.2 (p55) says to stop all the FIFOs first, then flush. Section * 7.5.4 (p162) says that flushing the RXFIFO at reset is not * recommended at all. * * I'm also unclear on whether or not the individual EPs are expected * to be disabled already (DIEPCTLn/DOEPCTLn.EPENA == 0), and if so, * whether by firmware or hardware. */ /* Flush all FIFOs according to Section 2.1.1.2 */ GR_USB_GRSTCTL = GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH; while (GR_USB_GRSTCTL & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) ; /* TODO: timeout 100ms */ }
static void usb_resetdet(void) { /* TODO: Same as normal reset, right? I think we only get this if we're * suspended (sleeping) and the host resets us. Try it and see. */ print_later("usb_resetdet()", 0, 0, 0, 0, 0); usb_reset(); }
void usb_disconnect(void) { print_later("usb_disconnect()", 0, 0, 0, 0, 0); GR_USB_DCTL |= DCTL_SFTDISCON; device_state = DS_DEFAULT; configuration_value = 0; }
/* Handle a Setup that comes with additional data for us. */ static int handle_setup_with_out_stage(enum table_case tc, struct usb_setup_packet *req) { print_later("handle_setup_with_out_stage(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); /* TODO: We don't support any of these. We should. */ return -1; }
static void usb_init_endpoints(void) { int ep; print_later("usb_init_endpoints()", 0, 0, 0, 0, 0); /* Prepare to receive packets on EP0 */ initialize_dma_buffers(); expect_setup_packet(); /* Reset the other endpoints */ for (ep = 1; ep < USB_EP_COUNT; ep++) usb_ep_reset[ep](); }
static void usb_reset(void) { CPRINTS("%s, status %x", __func__, GR_USB_GINTSTS); print_later("usb_reset()", 0, 0, 0, 0, 0); /* Clear our internal state */ device_state = DS_DEFAULT; configuration_value = 0; /* Clear the device address */ GWRITE_FIELD(USB, DCFG, DEVADDR, 0); /* Reinitialize all the endpoints */ usb_init_endpoints(); }
/* The next packet from the host should be a Setup packet. Get ready for it. */ static void expect_setup_packet(void) { print_later("expect_setup_packet()", 0, 0, 0, 0, 0); what_am_i_doing = WAITING_FOR_SETUP_PACKET; next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We don't care about IN packets right now, only OUT. */ GR_USB_DAINTMSK |= DAINT_OUTEP(0); GR_USB_DAINTMSK &= ~DAINT_INEP(0); /* Let it run. We might need CNAK if we just got an OUT for status */ GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; }
/* We're complaining about something by stalling both IN and OUT packets, * but a SETUP packet will get through anyway, so prepare for it. */ static void stall_both_fifos(void) { print_later("stall_both_fifos()", 0, 0, 0, 0, 0); what_am_i_doing = WAITING_FOR_SETUP_PACKET; next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We don't care about IN packets right now, only OUT. */ GR_USB_DAINTMSK |= DAINT_OUTEP(0); GR_USB_DAINTMSK &= ~DAINT_INEP(0); /* Stall both IN and OUT. The hardware will reset them when the next * SETUP comes along. */ GR_USB_DOEPCTL(0) = DXEPCTL_STALL | DXEPCTL_EPENA; flush_in_fifo(); GR_USB_DIEPCTL(0) = DXEPCTL_STALL | DXEPCTL_EPENA; }
/* No Data phase, just Status phase (which is IN, since Setup is OUT) */ static void expect_status_phase_in(enum table_case tc) { print_later("expect_status_phase_in(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); what_am_i_doing = NO_DATA_STAGE; /* Expect a zero-length IN for the Status phase */ (void) load_in_fifo(0, 0); /* We apparently have to do this every time we transmit anything */ flush_in_fifo(); /* I don't think we have to do this every time, but the Programmer's * Guide says to, so... */ GR_USB_DIEPDMA(0) = (uint32_t)(cur_in_desc); /* Blindly following instructions here, too. */ if (tc == TABLE_CASE_C) GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; /* The Programmer's Guide instructions for the Normal Two-Stage Control * Transfer leave this next bit out, so we only need it if we intend to * process an Exceptional Two-Stage Control Transfer. Because obviously * we always know in advance what the host is going to do. Idiots. */ /* Be prepared to get a new Setup packet during the Status phase */ next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We've already set GR_USB_DOEPDMA(0), so just enable it. */ if (tc == TABLE_CASE_C) GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DOEPCTL(0) = DXEPCTL_EPENA; /* Get an interrupt when either IN or OUT arrives */ GR_USB_DAINTMSK |= (DAINT_OUTEP(0) | DAINT_INEP(0)); }
/* Reset all this to a good starting state. */ static void initialize_dma_buffers(void) { int i; print_later("initialize_dma_buffers()", 0, 0, 0, 0, 0); for (i = 0; i < NUM_OUT_BUFFERS; i++) { ep0_out_desc[i].addr = ep0_out_buf[i]; ep0_out_desc[i].flags = DOEPDMA_BS_HOST_BSY; } next_out_idx = 0; next_out_desc = ep0_out_desc + next_out_idx; GR_USB_DOEPDMA(0) = (uint32_t)next_out_desc; /* cur_out_* will be updated when we get the first RX packet */ for (i = 0; i < NUM_IN_PACKETS_AT_ONCE; i++) { ep0_in_desc[i].addr = ep0_in_buf + i * USB_MAX_PACKET_SIZE; ep0_in_desc[i].flags = DIEPDMA_BS_HOST_BSY; } cur_in_desc = ep0_in_desc; GR_USB_DIEPDMA(0) = (uint32_t)(cur_in_desc); };
/* The TX FIFO buffer is loaded. Start the Data phase. */ static void expect_data_phase_in(enum table_case tc) { print_later("expect_data_phase_in(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); what_am_i_doing = DATA_STAGE_IN; /* We apparently have to do this every time we transmit anything */ flush_in_fifo(); /* I don't think we have to do this every time, but the Programmer's * Guide says to, so... */ GR_USB_DIEPDMA(0) = (uint32_t)(cur_in_desc); /* Blindly following instructions here, too. */ if (tc == TABLE_CASE_C) GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; /* * When the IN is done, we expect a zero-length OUT for the status * phase but it could be an early SETUP instead. We'll have to deal * with either one when it arrives. */ next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* And here's this jimmy rustler again... */ if (tc == TABLE_CASE_C) GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DOEPCTL(0) = DXEPCTL_EPENA; /* Get an interrupt when either IN or OUT arrives */ GR_USB_DAINTMSK |= (DAINT_OUTEP(0) | DAINT_INEP(0)); }
/* This handles both IN and OUT interrupts for EP0 */ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in) { uint32_t doepint, diepint; enum table_case tc; int sr; /* Determine the interrupt cause and clear the bits quickly, but only * if they really apply. I don't think they're trustworthy if we didn't * actually get an interrupt. */ doepint = GR_USB_DOEPINT(0); if (intr_on_out) GR_USB_DOEPINT(0) = doepint; diepint = GR_USB_DIEPINT(0); if (intr_on_in) GR_USB_DIEPINT(0) = diepint; print_later("doepint%c 0x%08x diepint%c 0x%08x what %d", intr_on_out ? '!' : '_', doepint, intr_on_in ? '!' : '_', diepint, what_am_i_doing); /* Update current and pending RX FIFO buffers */ if (intr_on_out && (doepint & DOEPINT_XFERCOMPL)) got_RX_packet(); /* Decode the situation according to Table 10-7 */ tc = decode_table_10_7(doepint); sr = cur_out_desc->flags & DOEPDMA_SR; print_later("cur_out_idx %d flags 0x%08x case=%c SR=%d", cur_out_idx, cur_out_desc->flags, "0ABCDE67"[tc], !!sr, 0); switch (what_am_i_doing) { case WAITING_FOR_SETUP_PACKET: if (tc == TABLE_CASE_A || tc == TABLE_CASE_C) { if (sr) { handle_setup(tc); } else { report_error(tc); print_later("next_out_idx %d flags 0x%08x", next_out_idx, next_out_desc->flags, 0, 0, 0); expect_setup_packet(); } } /* This only happens if we're stalling, so keep doing it. */ if (tc == TABLE_CASE_B) { print_later("Still waiting for Setup...", 0, 0, 0, 0, 0); stall_both_fifos(); } break; case DATA_STAGE_IN: if (intr_on_in && (diepint & DIEPINT_XFERCOMPL)) { print_later("IN is complete? Maybe? How do we know?", 0, 0, 0, 0, 0); /* I don't *think* we need to do this, unless we need * to transfer more data. Customer support agrees and * it shouldn't matter if the host is well-behaved, but * it seems like we had issues without it. * TODO: Test this case until we know for sure. */ GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; /* * The Programmer's Guide says (p291) to stall any * further INs, but that's stupid because it'll destroy * the packet we just transferred to SPRAM, so don't do * that (we tried it anyway, and Bad Things happened). * Also don't stop here, but keep looking at stuff. */ } /* But we should ignore the OUT endpoint if we didn't actually * get an OUT interrupt. */ if (!intr_on_out) break; if (tc == TABLE_CASE_B) { print_later("IN has been detected...", 0, 0, 0, 0, 0); /* The first IN packet has been seen. Keep going. */ GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; break; } if (tc == TABLE_CASE_A) { if (!sr) { /* We've handled the Status phase. All done. */ print_later("Status phase complete", 0, 0, 0, 0, 0); expect_setup_packet(); break; } /* We expected an OUT, but got a Setup. Deal with it. */ print_later("Early Setup", 0, 0, 0, 0, 0); handle_setup(tc); break; } /* From the Exceptional Control Read Transfer section ... */ if (tc == TABLE_CASE_C) { if (sr) { print_later("Early Setup w/Data packet seen", 0, 0, 0, 0, 0); handle_setup(tc); break; } print_later("Status phase complete. I think...", 0, 0, 0, 0, 0); expect_setup_packet(); break; } /* Anything else should be ignorable. Right? */ break; case NO_DATA_STAGE: if (intr_on_in && (diepint & DIEPINT_XFERCOMPL)) { print_later("IN descriptor processed", 0, 0, 0, 0, 0); /* Let the IN proceed */ GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; } /* Done unless we got an OUT interrupt */ if (!intr_on_out) break; if (tc == TABLE_CASE_B) { print_later("IN has been detected...", 0, 0, 0, 0, 0); /* Let the IN proceed */ GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; /* Reenable the previously prepared OUT descriptor. */ GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; break; } if (tc == TABLE_CASE_A || tc == TABLE_CASE_C) { if (sr) { /* We expected an IN, but got a Setup. */ print_later("Early Setup", 0, 0, 0, 0, 0); handle_setup(tc); break; } } /* Anything else means get ready for a Setup packet */ print_later("Status phase complete. Maybe.", 0, 0, 0, 0, 0); expect_setup_packet(); break; } }
void usb_interrupt(void) { uint32_t status = GR_USB_GINTSTS; uint32_t oepint = status & GINTSTS(OEPINT); uint32_t iepint = status & GINTSTS(IEPINT); int ep; print_later("interrupt: GINTSTS 0x%08x", status, 0, 0, 0, 0); /* We can suspend if the host stops talking to us. But if anything else * comes along (even ERLYSUSP), we should NOT suspend. */ if (status & GINTSTS(USBSUSP)) { print_later("usb_suspend()", 0, 0, 0, 0, 0); enable_sleep(SLEEP_MASK_USB_DEVICE); } else { disable_sleep(SLEEP_MASK_USB_DEVICE); } #ifdef DEBUG_ME if (status & GINTSTS(ERLYSUSP)) print_later("usb_early_suspend()", 0, 0, 0, 0, 0); if (status & GINTSTS(WKUPINT)) print_later("usb_wakeup()", 0, 0, 0, 0, 0); if (status & GINTSTS(ENUMDONE)) print_later("usb_enumdone()", 0, 0, 0, 0, 0); #endif if (status & (GINTSTS(RESETDET) | GINTSTS(USBRST))) usb_reset(); /* Initialize the SOF clock calibrator only on the first SOF */ if (GR_USB_GINTMSK & GINTMSK(SOF) && status & GINTSTS(SOF)) { init_sof_clock(); GR_USB_GINTMSK &= ~GINTMSK(SOF); } /* Endpoint interrupts */ if (oepint || iepint) { /* Note: It seems that the DAINT bits are only trustworthy for * identifying interrupts when selected by the corresponding * OEPINT and IEPINT bits from GINTSTS. */ uint32_t daint = GR_USB_DAINT; print_later(" oepint%c iepint%c daint 0x%08x", oepint ? '!' : '_', iepint ? '!' : '_', daint, 0, 0); /* EP0 has a combined IN/OUT handler. Only call it once, but * let it know which direction(s) had an interrupt. */ if (daint & (DAINT_OUTEP(0) | DAINT_INEP(0))) { uint32_t intr_on_out = (oepint && (daint & DAINT_OUTEP(0))); uint32_t intr_on_in = (iepint && (daint & DAINT_INEP(0))); ep0_interrupt(intr_on_out, intr_on_in); } /* Invoke the unidirectional IN and OUT functions for the other * endpoints. Each handler must clear their own bits in * DIEPINTn/DOEPINTn. */ for (ep = 1; ep < USB_EP_COUNT; ep++) { if (oepint && (daint & DAINT_OUTEP(ep))) usb_ep_rx[ep](); if (iepint && (daint & DAINT_INEP(ep))) usb_ep_tx[ep](); } } if (status & GINTSTS(GOUTNAKEFF)) GR_USB_DCTL |= DCTL_CGOUTNAK; if (status & GINTSTS(GINNAKEFF)) GR_USB_DCTL |= DCTL_CGNPINNAK; GR_USB_GINTSTS = status; print_later("end of interrupt", 0, 0, 0, 0, 0); }
/* Some Setup packets don't have a data stage at all. */ static int handle_setup_with_no_data_stage(enum table_case tc, struct usb_setup_packet *req) { uint8_t set_addr; print_later("handle_setup_with_no_data_stage(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); switch (req->bRequest) { case USB_REQ_SET_ADDRESS: /* * Set the address after the IN packet handshake. * * From the USB 2.0 spec, section 9.4.6: * * As noted elsewhere, requests actually may result in * up to three stages. In the first stage, the Setup * packet is sent to the device. In the optional second * stage, data is transferred between the host and the * device. In the final stage, status is transferred * between the host and the device. The direction of * data and status transfer depends on whether the host * is sending data to the device or the device is * sending data to the host. The Status stage transfer * is always in the opposite direction of the Data * stage. If there is no Data stage, the Status stage * is from the device to the host. * * Stages after the initial Setup packet assume the * same device address as the Setup packet. The USB * device does not change its device address until * after the Status stage of this request is completed * successfully. Note that this is a difference between * this request and all other requests. For all other * requests, the operation indicated must be completed * before the Status stage */ set_addr = req->wValue & 0xff; /* * NOTE: Now that we've said that, we don't do it. The * hardware for this SoC knows that an IN packet will * be following the SET ADDRESS, so it waits until it * sees that happen before the address change takes * effect. If we wait until after the IN packet to * change the register, the hardware gets confused and * doesn't respond to anything. */ GWRITE_FIELD(USB, DCFG, DEVADDR, set_addr); CPRINTS("SETAD 0x%02x (%d)", set_addr, set_addr); print_later("SETAD 0x%02x (%d)", set_addr, set_addr, 0, 0, 0); device_state = DS_ADDRESS; processed_update_counter = 1; break; case USB_REQ_SET_CONFIGURATION: print_later("SETCFG 0x%x", req->wValue, 0, 0, 0, 0); switch (req->wValue) { case 0: configuration_value = req->wValue; device_state = DS_ADDRESS; break; case 1: /* Caution: Only one config descriptor TODAY */ /* TODO: All endpoints set to DATA0 toggle state */ configuration_value = req->wValue; device_state = DS_CONFIGURED; break; default: /* Nope. That's a paddlin. */ return -1; } break; case USB_REQ_CLEAR_FEATURE: case USB_REQ_SET_FEATURE: /* TODO: Handle DEVICE_REMOTE_WAKEUP, ENDPOINT_HALT? */ print_later("SET_FEATURE/CLEAR_FEATURE. Whatever...", 0, 0, 0, 0, 0); break; default: /* Anything else is unsupported */ return -1; } /* No data to transfer, go straight to the Status phase. */ return 0; }
void usb_connect(void) { print_later("usb_connect()", 0, 0, 0, 0, 0); GR_USB_DCTL &= ~DCTL_SFTDISCON; }
/* Handle a Setup packet that expects us to send back data in reply. Return the * length of the data we're returning, or negative to indicate an error. */ static int handle_setup_with_in_stage(enum table_case tc, struct usb_setup_packet *req) { const void *data = 0; uint32_t len = 0; int ugly_hack = 0; static const uint16_t zero; /* == 0 */ print_later("handle_setup_with_in_stage(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: { uint8_t type = req->wValue >> 8; uint8_t idx = req->wValue & 0xff; switch (type) { case USB_DT_DEVICE: data = &dev_desc; len = sizeof(dev_desc); break; case USB_DT_CONFIGURATION: data = __usb_desc; len = USB_DESC_SIZE; ugly_hack = 1; /* see below */ break; #ifdef CONFIG_USB_BOS case USB_DT_BOS: data = bos_ctx.descp; len = bos_ctx.size; break; #endif case USB_DT_STRING: if (idx >= USB_STR_COUNT) return -1; #if USE_SERIAL_NUMBER if (idx == USB_STR_SERIALNO && ccd_get_mode() == CCD_MODE_ENABLED) data = usb_serialno_desc; else #endif data = usb_strings[idx]; len = *(uint8_t *)data; break; case USB_DT_DEVICE_QUALIFIER: /* We're not high speed */ return -1; default: report_error(type); return -1; } break; } case USB_REQ_GET_STATUS: { /* TODO: Device Status: Remote Wakeup? Self Powered? */ data = &zero; len = sizeof(zero); break; } case USB_REQ_GET_CONFIGURATION: data = &configuration_value; len = sizeof(configuration_value); break; case USB_REQ_SYNCH_FRAME: /* Unimplemented */ return -1; default: report_error(req->bRequest); return -1; } /* Don't send back more than we were asked for. */ len = MIN(req->wLength, len); /* Prepare the TX FIFO. If we haven't preallocated enough room in the * TX FIFO for the largest reply, we'll have to stall. This is a bug in * our code, but detecting it easily at compile time is related to the * ugly_hack directly below. */ if (load_in_fifo(data, len) < 0) return -1; if (ugly_hack) { /* * TODO: Somebody figure out how to fix this, please. * * The USB configuration descriptor request is unique in that * it not only returns the configuration descriptor, but also * all the interface descriptors and all their endpoint * descriptors as one enormous blob. We've set up some macros * so we can declare and implement separate interfaces in * separate files just by compiling them, and all the relevant * descriptors are sorted and bundled up by the linker. But the * total length of the entire blob needs to appear in the first * configuration descriptor struct and because we don't know * that value until after linking, it can't be initialized as a * constant. So we have to compute it at run-time and shove it * in here, which also means that we have to copy the whole * blob into our TX FIFO buffer so that it's mutable. Otherwise * we could just point at it (or pretty much any other constant * struct that we wanted to send to the host). Bah. */ struct usb_config_descriptor *cfg = (struct usb_config_descriptor *)ep0_in_buf; /* set the real descriptor size */ cfg->wTotalLength = USB_DESC_SIZE; } return len; }
void usb_connect(void) { CPRINTS("%s", __func__); print_later("usb_connect()", 0, 0, 0, 0, 0); GR_USB_DCTL &= ~DCTL_SFTDISCON; }