static int atausb_bbb_start(struct ata_request *request) { struct atausb_softc *sc = device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); sc->timeout = (request->timeout * 1000) + 5000; USETDW(sc->cbw.signature, CBWSIGNATURE); USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1); USETDW(sc->cbw.transfer_length, request->bytecount); sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT; sc->cbw.lun = ch->unit; sc->cbw.length = 16; bzero(sc->cbw.cdb, 16); bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */ sc->state = ATAUSB_S_BBB_COMMAND; if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw), 0, sc->transfer[ATAUSB_T_BBB_CBW])) { request->result = EIO; if (atausbdebug) device_printf(request->dev, "cannot setup USB transfer\n"); atausb_bbb_reset(sc); return ATA_OP_FINISHED; } return ATA_OP_CONTINUES; }
void umct_set_baudrate(struct umct_softc *sc, u_int rate, int cts) { usb_device_request_t req; uDWord arate; u_int val; if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232 || sc->sc_product == USB_PRODUCT_BELKIN_F5U109) { switch (rate) { case 300: val = 0x01; break; case 600: val = 0x02; break; case 1200: val = 0x03; break; case 2400: val = 0x04; break; case 4800: val = 0x06; break; case 9600: val = 0x08; break; case 19200: val = 0x09; break; case 38400: val = 0x0a; break; case 57600: val = 0x0b; break; case 115200: val = 0x0c; break; default: val = -1; break; } } else { val = UMCT_BAUD_RATE(rate); } USETDW(arate, val); req.bmRequestType = UMCT_SET_REQUEST; req.bRequest = REQ_SET_BAUD_RATE; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_number); USETW(req.wLength, LENGTH_BAUD_RATE); /* XXX should check */ (void)usbd_do_request(sc->sc_udev, &req, arate); /* unknown request, required after setting baud rate */ USETDW(arate, 0); req.bmRequestType = UMCT_SET_REQUEST; req.bRequest = REQ_UNKNOWN1; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_number); USETW(req.wLength, LENGTH_UNKNOWN1); (void)usbd_do_request(sc->sc_udev, &req, arate); /* update CTS, also required after setting baud rate */ USETDW(arate, cts); req.bmRequestType = UMCT_SET_REQUEST; req.bRequest = REQ_SET_CTS; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_number); USETW(req.wLength, LENGTH_SET_CTS); (void)usbd_do_request(sc->sc_udev, &req, arate); }
static int uplcom_param(void *addr, int portno, struct termios *t) { struct uplcom_softc *sc = addr; usbd_status err; usb_cdc_line_state_t ls; int i; DPRINTF(("uplcom_param: sc = %p\n", sc)); /* Check requested baud rate */ for (i = 0; i < N_UPLCOM_RATES; i++) if (uplcom_rates[i] == t->c_ospeed) break; if (i == N_UPLCOM_RATES) { DPRINTF(("uplcom_param: bad baud rate (%d)\n", t->c_ospeed)); return (EIO); } USETDW(ls.dwDTERate, t->c_ospeed); if (ISSET(t->c_cflag, CSTOPB)) ls.bCharFormat = UCDC_STOP_BIT_2; else ls.bCharFormat = UCDC_STOP_BIT_1; if (ISSET(t->c_cflag, PARENB)) { if (ISSET(t->c_cflag, PARODD)) ls.bParityType = UCDC_PARITY_ODD; else ls.bParityType = UCDC_PARITY_EVEN; } else ls.bParityType = UCDC_PARITY_NONE; switch (ISSET(t->c_cflag, CSIZE)) { case CS5: ls.bDataBits = 5; break; case CS6: ls.bDataBits = 6; break; case CS7: ls.bDataBits = 7; break; case CS8: ls.bDataBits = 8; break; } err = uplcom_set_line_coding(sc, &ls); if (err) return (EIO); if (ISSET(t->c_cflag, CRTSCTS)) { err = uplcom_set_crtscts(sc); if (err) return (EIO); } return (0); }
int uplcom_param(void *addr, int portno, struct termios *t) { struct uplcom_softc *sc = addr; usbd_status err; usb_cdc_line_state_t ls; DPRINTF(("uplcom_param: sc=%p\n", sc)); USETDW(ls.dwDTERate, t->c_ospeed); if (ISSET(t->c_cflag, CSTOPB)) ls.bCharFormat = UCDC_STOP_BIT_2; else ls.bCharFormat = UCDC_STOP_BIT_1; if (ISSET(t->c_cflag, PARENB)) { if (ISSET(t->c_cflag, PARODD)) ls.bParityType = UCDC_PARITY_ODD; else ls.bParityType = UCDC_PARITY_EVEN; } else ls.bParityType = UCDC_PARITY_NONE; switch (ISSET(t->c_cflag, CSIZE)) { case CS5: ls.bDataBits = 5; break; case CS6: ls.bDataBits = 6; break; case CS7: ls.bDataBits = 7; break; case CS8: ls.bDataBits = 8; break; } err = uplcom_set_line_coding(sc, &ls); if (err) { DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err))); return (EIO); } if (ISSET(t->c_cflag, CRTSCTS)) uplcom_set_crtscts(sc); if (sc->sc_rts == -1 || sc->sc_dtr == -1) uplcom_set_line_state(sc); if (err) { DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err))); return (EIO); } return (0); }
int ugl_send(struct ugl_softc *sc, struct mbuf *m, int idx) { int total_len; struct ugl_chain *c; usbd_status err; c = &sc->sc_cdata.ugl_tx_chain[idx]; /* * Copy the mbuf data into a contiguous buffer, leaving two * bytes at the beginning to hold the frame length. */ USETDW(c->ugl_buf->pkt_count, UGL_TX_FRAMES); USETDW(c->ugl_buf->pkt_length, m->m_pkthdr.len); m_copydata(m, 0, m->m_pkthdr.len, c->ugl_buf->pkt_data); c->ugl_mbuf = m; total_len = offsetof(struct ugl_packet, pkt_data[m->m_pkthdr.len]); DPRINTFN(10,("%s: %s: total_len=%d\n", sc->sc_dev.dv_xname, __func__, total_len)); usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_TX], c, c->ugl_buf, total_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, USBD_DEFAULT_TIMEOUT, ugl_txeof); /* Transmit */ err = usbd_transfer(c->ugl_xfer); if (err != USBD_IN_PROGRESS) { printf("%s: ugl_send error=%s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); ugl_stop(sc); return (EIO); } sc->sc_cdata.ugl_tx_cnt++; return (0); }
/* write 4bytes to register */ Static int url_csr_write_4(struct url_softc *sc, int reg, int aval) { uDWord val; DPRINTFN(0x100, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); USETDW(val, aval); if (sc->sc_dying) return (0); return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0); }
Static int umct_request(struct umct_softc *sc, uint8_t request, int len, uint32_t value) { usb_device_request_t req; usbd_status err; uint8_t oval[4]; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = request; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_number); USETW(req.wLength, len); USETDW(oval, value); err = usbd_do_request(sc->sc_ucom.sc_udev, &req, oval); if (err) printf("%s: ubsa_request: %s\n", USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err)); return (err); }
int ueagle_cr(struct ueagle_softc *sc, uint32_t address, uint16_t offset, uint32_t *data) { struct ueagle_cmv cmv; usbd_status error; int s; USETW(cmv.wPreamble, UEAGLE_CMV_PREAMBLE); cmv.bDst = UEAGLE_MODEM; cmv.bFunction = UEAGLE_CR; USETW(cmv.wIndex, sc->index); USETW(cmv.wOffsetAddress, offset); USETDW(cmv.dwSymbolicAddress, address); USETDATA(cmv.dwData, 0); #ifdef USB_DEBUG if (ueagledebug >= 15) { printf("%s: reading CMV\n", sc->sc_dev.dv_xname); ueagle_dump_cmv(sc, &cmv); } #endif s = splusb(); ueagle_request(sc, UEAGLE_SETBLOCK, UEAGLE_MPTXSTART, &cmv, sizeof cmv); /* wait at most 2 seconds for an answer */ error = tsleep(UEAGLE_COND_CMV(sc), PZERO, "cmv", 2 * hz); if (error != 0) { printf("%s: timeout waiting for CMV ack\n", sc->sc_dev.dv_xname); splx(s); return error; } *data = sc->data; splx(s); return 0; }
static void usb_modem_control_ep_test(struct modem *p, uint32_t duration, uint8_t flag) { struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; struct LIBUSB20_CONTROL_SETUP_DECODED setup; struct usb_cdc_abstract_state ast; struct usb_cdc_line_state ls; uint16_t feature = UCDC_ABSTRACT_STATE; uint16_t state = UCDC_DATA_MULTIPLEXED; uint8_t iface_no; uint8_t buf[4]; int id = 0; int iter = 0; time_t last_sec; iface_no = p->usb_iface - 1; gettimeofday(&ref_tv, 0); last_sec = ref_tv.tv_sec; printf("\nTest=%d\n", (int)flag); while (1) { gettimeofday(&sub_tv, 0); if (last_sec != sub_tv.tv_sec) { printf("STATUS: ID=%u, COUNT=%u tests/sec ERR=%u\n", (int)id, (int)iter, (int)p->errors); fflush(stdout); last_sec = sub_tv.tv_sec; id++; iter = 0; } timersub(&sub_tv, &ref_tv, &res_tv); if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) break; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); if (flag & 1) { setup.bmRequestType = UT_READ_CLASS_INTERFACE; setup.bRequest = 0x03; setup.wValue = 0x0001; setup.wIndex = iface_no; setup.wLength = 0x0002; if (libusb20_dev_request_sync(p->usb_dev, &setup, buf, NULL, 250, 0)) { p->errors++; } } if (flag & 2) { setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; setup.bRequest = UCDC_SET_COMM_FEATURE; setup.wValue = feature; setup.wIndex = iface_no; setup.wLength = UCDC_ABSTRACT_STATE_LENGTH; USETW(ast.wState, state); if (libusb20_dev_request_sync(p->usb_dev, &setup, &ast, NULL, 250, 0)) { p->errors++; } } if (flag & 4) { USETDW(ls.dwDTERate, 115200); ls.bCharFormat = UCDC_STOP_BIT_1; ls.bParityType = UCDC_PARITY_NONE; ls.bDataBits = 8; setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; setup.bRequest = UCDC_SET_LINE_CODING; setup.wValue = 0; setup.wIndex = iface_no; setup.wLength = sizeof(ls); if (libusb20_dev_request_sync(p->usb_dev, &setup, &ls, NULL, 250, 0)) { p->errors++; } } iter++; } printf("\nModem control endpoint test done!\n"); }
/*------------------------------------------------------------------------* * cdce_ncm_init * * Return values: * 0: Success * Else: Failure *------------------------------------------------------------------------*/ static uint8_t cdce_ncm_init(struct cdce_softc *sc) { struct usb_ncm_parameters temp; struct usb_device_request req; struct usb_ncm_func_descriptor *ufd; uint8_t value[8]; int err; ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL, sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0 - 1, UCDC_NCM_FUNC_DESC_SUBTYPE, 0 - 1); /* verify length of NCM functional descriptor */ if (ufd != NULL) { if (ufd->bLength < sizeof(*ufd)) ufd = NULL; else DPRINTFN(1, "Found NCM functional descriptor.\n"); } req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS; USETW(req.wValue, 0); req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, sizeof(temp)); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, &temp, 0, NULL, 1000 /* ms */); if (err) return (1); /* Read correct set of parameters according to device mode */ if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize); sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize); sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder); sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor); sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment); sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); } else { sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize); sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize); sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder); sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor); sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment); sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); } /* Verify maximum receive length */ if ((sc->sc_ncm.rx_max < 32) || (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) { DPRINTFN(1, "Using default maximum receive length\n"); sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN; } /* Verify maximum transmit length */ if ((sc->sc_ncm.tx_max < 32) || (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) { DPRINTFN(1, "Using default maximum transmit length\n"); sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN; } /* * Verify that the structure alignment is: * - power of two * - not greater than the maximum transmit length * - not less than four bytes */ if ((sc->sc_ncm.tx_struct_align < 4) || (sc->sc_ncm.tx_struct_align != ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) || (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) { DPRINTFN(1, "Using default other alignment: 4 bytes\n"); sc->sc_ncm.tx_struct_align = 4; } /* * Verify that the payload alignment is: * - power of two * - not greater than the maximum transmit length * - not less than four bytes */ if ((sc->sc_ncm.tx_modulus < 4) || (sc->sc_ncm.tx_modulus != ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) || (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) { DPRINTFN(1, "Using default transmit modulus: 4 bytes\n"); sc->sc_ncm.tx_modulus = 4; } /* Verify that the payload remainder */ if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) { DPRINTFN(1, "Using default transmit remainder: 0 bytes\n"); sc->sc_ncm.tx_remainder = 0; } /* * Offset the TX remainder so that IP packet payload starts at * the tx_modulus. This is not too clear in the specification. */ sc->sc_ncm.tx_remainder = (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) & (sc->sc_ncm.tx_modulus - 1); /* Verify max datagrams */ if (sc->sc_ncm.tx_nframe == 0 || sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) { DPRINTFN(1, "Using default max " "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1); /* need to reserve one entry for zero padding */ sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1); } /* Additional configuration, will fail in device side mode, which is OK. */ req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE; USETW(req.wValue, 0); req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; if (ufd != NULL && (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) { USETW(req.wLength, 8); USETDW(value, sc->sc_ncm.rx_max); USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1)); USETW(value + 6, 0); } else { USETW(req.wLength, 4); USETDW(value, sc->sc_ncm.rx_max); } err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, &value, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting input size " "to %u failed.\n", sc->sc_ncm.rx_max); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_CRC_MODE; USETW(req.wValue, 0); /* no CRC */ req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, 0); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, NULL, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting CRC mode to off failed.\n"); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_NTB_FORMAT; USETW(req.wValue, 0); /* NTB-16 */ req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, 0); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, NULL, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting NTB format to 16-bit failed.\n"); } return (0); /* success */ }
usbd_status umsm_umass_changemode(struct umsm_softc *sc) { #define UMASS_CMD_REZERO_UNIT 0x01 #define UMASS_CMD_START_STOP 0x1b #define UMASS_CMDPARAM_EJECT 0x02 #define UMASS_SERVICE_ACTION_OUT 0x9f usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct usbd_xfer *xfer; struct usbd_pipe *cmdpipe; usbd_status err; u_int32_t n; void *bufp; int target_ep, i; struct umass_bbb_cbw cbw; static int dCBWTag = 0x12345678; USETDW(cbw.dCBWSignature, CBWSIGNATURE); USETDW(cbw.dCBWTag, dCBWTag); cbw.bCBWLUN = 0; cbw.bCDBLength= 6; bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB)); switch (sc->sc_flag) { case DEV_UMASS1: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT; cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ break; case DEV_UMASS2: USETDW(cbw.dCBWDataTransferLength, 0x1); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT; cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ break; case DEV_UMASS3: /* longcheer */ USETDW(cbw.dCBWDataTransferLength, 0x80); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = 0x06; cbw.CBWCDB[1] = 0xf5; cbw.CBWCDB[2] = 0x04; cbw.CBWCDB[3] = 0x02; cbw.CBWCDB[4] = 0x52; cbw.CBWCDB[5] = 0x70; break; case DEV_UMASS4: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = UMASS_CMD_START_STOP; cbw.CBWCDB[1] = 0x00; /* target LUN: 0 */ cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT; break; case DEV_UMASS5: cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = 0x11; cbw.CBWCDB[1] = 0x06; break; case DEV_UMASS6: /* ZTE */ USETDW(cbw.dCBWDataTransferLength, 0x20); cbw.bCBWFlags = CBWFLAGS_IN; cbw.bCDBLength= 12; cbw.CBWCDB[0] = 0x85; cbw.CBWCDB[1] = 0x01; cbw.CBWCDB[2] = 0x01; cbw.CBWCDB[3] = 0x01; cbw.CBWCDB[4] = 0x18; cbw.CBWCDB[5] = 0x01; cbw.CBWCDB[6] = 0x01; cbw.CBWCDB[7] = 0x01; cbw.CBWCDB[8] = 0x01; cbw.CBWCDB[9] = 0x01; break; case DEV_UMASS7: /* ZTE */ USETDW(cbw.dCBWDataTransferLength, 0xc0); cbw.bCBWFlags = CBWFLAGS_IN; cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT; cbw.CBWCDB[1] = 0x03; break; case DEV_UMASS8: USETDW(cbw.dCBWDataTransferLength, 0x0); cbw.bCBWFlags = CBWFLAGS_OUT; cbw.CBWCDB[0] = 0xf0; cbw.CBWCDB[1] = 0x01; cbw.CBWCDB[2] = 0x03; break; default: DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname)); break; } /* get command endpoint address */ id = usbd_get_interface_descriptor(sc->sc_iface); for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { return (USBD_IOERROR); } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) target_ep = ed->bEndpointAddress; } /* open command endppoint */ err = usbd_open_pipe(sc->sc_iface, target_ep, USBD_EXCLUSIVE_USE, &cmdpipe); if (err) { DPRINTF(("%s: open pipe for modem change cmd failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err))); return (err); } xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) { usbd_close_pipe(cmdpipe); return (USBD_NOMEM); } else { bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE); if (bufp == NULL) err = USBD_NOMEM; else { n = UMASS_BBB_CBW_SIZE; memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE); usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n, USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(cmdpipe); DPRINTF(("%s: send error:%s", __func__, usbd_errstr(err))); } } usbd_close_pipe(cmdpipe); usbd_free_buffer(xfer); usbd_free_xfer(xfer); } return (err); }
static uint8_t do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen, uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags) { umass_bbb_cbw_t cbw; umass_bbb_csw_t csw; struct libusb20_transfer *xfer_io; uint32_t actlen; uint32_t timeout; int error; memset(&cbw, 0, sizeof(cbw)); USETDW(cbw.dCBWSignature, xfer_wrapper_sig); USETDW(cbw.dCBWTag, xfer_current_id); xfer_current_id++; USETDW(cbw.dCBWDataTransferLength, datalen); cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT); cbw.bCBWLUN = lun; cbw.bCDBLength = cmdlen; bcopy(pcmd, cbw.CBWCDB, cmdlen); actlen = 0; timeout = ((datalen + 299999) / 300000) * 1000; timeout += 5000; if ((error = libusb20_tr_bulk_intr_sync(xfer_out, &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) { printf("ERROR: CBW reception: %d\n", error); do_msc_reset(lun); return (1); } if (actlen != sizeof(cbw)) { printf("ERROR: CBW length: %d != %d\n", actlen, (int)sizeof(cbw)); do_msc_reset(lun); return (1); } if (flags & 1) datalen /= 2; if (datalen != 0) { xfer_io = isread ? xfer_in : xfer_out; if ((error = libusb20_tr_bulk_intr_sync(xfer_io, pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) { printf("ERROR: Data transfer: %d\n", error); do_msc_reset(lun); return (1); } if ((actlen != datalen) && (!isshort)) { printf("ERROR: Short data: %d of %d bytes\n", actlen, datalen); do_msc_reset(lun); return (1); } } actlen = 0; timeout = 8; do { error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { if (error == LIBUSB20_TRANSFER_TIMED_OUT) { printf("TIMEOUT: Trying to get CSW again. " "%d tries left.\n", timeout); } else { break; } } else { break; } } while (--timeout); if (error) { libusb20_tr_clear_stall_sync(xfer_in); error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { libusb20_tr_clear_stall_sync(xfer_in); printf("ERROR: Could not read CSW: Stalled or " "timeout (%d).\n", error); do_msc_reset(lun); return (1); } } if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) { printf("ERROR: Wrong CSW signature\n"); do_msc_reset(lun); return (1); } if (actlen != sizeof(csw)) { printf("ERROR: Wrong CSW length: %d != %d\n", actlen, (int)sizeof(csw)); do_msc_reset(lun); return (1); } if (csw.bCSWStatus != 0) { printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus); return (1); } else { stats.xfer_success++; return (0); } }
static void cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct cdce_softc *sc = usbd_xfer_softc(xfer); struct usb_cdc_notification req; struct usb_page_cache *pc; uint32_t speed; int actlen; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTF("Transferred %d bytes\n", actlen); switch (sc->sc_notify_state) { case CDCE_NOTIFY_NETWORK_CONNECTION: sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE; break; case CDCE_NOTIFY_SPEED_CHANGE: sc->sc_notify_state = CDCE_NOTIFY_DONE; break; default: break; } /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: /* * Inform host about connection. Required according to USB CDC * specification and communicating to Mac OS X USB host stack. * Some of the values seems ignored by Mac OS X though. */ if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) { req.bmRequestType = UCDC_NOTIFICATION; req.bNotification = UCDC_N_NETWORK_CONNECTION; req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wValue, 1); /* Connected */ USETW(req.wLength, 0); pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_in(pc, 0, &req, sizeof(req)); usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); usbd_xfer_set_frames(xfer, 1); usbd_transfer_submit(xfer); } else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) { req.bmRequestType = UCDC_NOTIFICATION; req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE; req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wValue, 0); USETW(req.wLength, 8); /* Peak theoretical bulk trasfer rate in bits/s */ if (usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_FULL) speed = (13 * 512 * 8 * 1000 * 8); else speed = (19 * 64 * 1 * 1000 * 8); USETDW(req.data + 0, speed); /* Upstream bit rate */ USETDW(req.data + 4, speed); /* Downstream bit rate */ pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_in(pc, 0, &req, sizeof(req)); usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); usbd_xfer_set_frames(xfer, 1); usbd_transfer_submit(xfer); } break; default: /* Error */ if (error != USB_ERR_CANCELLED) { if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { /* start clear stall */ usbd_xfer_set_stall(xfer); } goto tr_setup; } break; } }