uslcom.c revision 188746
160786Sps/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */ 260786Sps 360786Sps#include <sys/cdefs.h> 460786Sps__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/uslcom2.c 188746 2009-02-18 06:33:10Z thompsa $"); 560786Sps 660786Sps/* 760786Sps * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> 860786Sps * 960786Sps * Permission to use, copy, modify, and distribute this software for any 1060786Sps * purpose with or without fee is hereby granted, provided that the above 1160786Sps * copyright notice and this permission notice appear in all copies. 1260786Sps * 1360786Sps * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1460786Sps * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1560786Sps * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1660786Sps * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1760786Sps * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1860786Sps * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1960786Sps * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2060786Sps */ 2160786Sps 2260786Sps#include "usbdevs.h" 2360786Sps#include <dev/usb2/include/usb2_standard.h> 2460786Sps#include <dev/usb2/include/usb2_mfunc.h> 2560786Sps#include <dev/usb2/include/usb2_error.h> 2660786Sps 2760786Sps#define USB_DEBUG_VAR uslcom_debug 2860786Sps 2960786Sps#include <dev/usb2/core/usb2_core.h> 3060786Sps#include <dev/usb2/core/usb2_debug.h> 3160786Sps#include <dev/usb2/core/usb2_process.h> 3260786Sps#include <dev/usb2/core/usb2_request.h> 3360786Sps#include <dev/usb2/core/usb2_lookup.h> 3460786Sps#include <dev/usb2/core/usb2_util.h> 3560786Sps#include <dev/usb2/core/usb2_busdma.h> 3660786Sps 3760786Sps#include <dev/usb2/serial/usb2_serial.h> 3860786Sps 3960786Sps#if USB_DEBUG 4060786Spsstatic int uslcom_debug = 0; 4160786Sps 4260786SpsSYSCTL_NODE(_hw_usb2, OID_AUTO, uslcom, CTLFLAG_RW, 0, "USB uslcom"); 4360786SpsSYSCTL_INT(_hw_usb2_uslcom, OID_AUTO, debug, CTLFLAG_RW, 4460786Sps &uslcom_debug, 0, "Debug level"); 4560786Sps#endif 4660786Sps 4760786Sps#define USLCOM_BULK_BUF_SIZE 1024 4860786Sps#define USLCOM_CONFIG_INDEX 0 4960786Sps#define USLCOM_IFACE_INDEX 0 5060786Sps 5160786Sps#define USLCOM_SET_DATA_BITS(x) ((x) << 8) 5260786Sps 5360786Sps#define USLCOM_WRITE 0x41 5460786Sps#define USLCOM_READ 0xc1 5560786Sps 5660786Sps#define USLCOM_UART 0x00 5760786Sps#define USLCOM_BAUD_RATE 0x01 5860786Sps#define USLCOM_DATA 0x03 5960786Sps#define USLCOM_BREAK 0x05 6060786Sps#define USLCOM_CTRL 0x07 6160786Sps 6260786Sps#define USLCOM_UART_DISABLE 0x00 6360786Sps#define USLCOM_UART_ENABLE 0x01 6460786Sps 6560786Sps#define USLCOM_CTRL_DTR_ON 0x0001 6660786Sps#define USLCOM_CTRL_DTR_SET 0x0100 6760786Sps#define USLCOM_CTRL_RTS_ON 0x0002 6860786Sps#define USLCOM_CTRL_RTS_SET 0x0200 6960786Sps#define USLCOM_CTRL_CTS 0x0010 7060786Sps#define USLCOM_CTRL_DSR 0x0020 7160786Sps#define USLCOM_CTRL_DCD 0x0080 7260786Sps 7360786Sps#define USLCOM_BAUD_REF 0x384000 7460786Sps 7560786Sps#define USLCOM_STOP_BITS_1 0x00 7660786Sps#define USLCOM_STOP_BITS_2 0x02 7760786Sps 7860786Sps#define USLCOM_PARITY_NONE 0x00 7960786Sps#define USLCOM_PARITY_ODD 0x10 8060786Sps#define USLCOM_PARITY_EVEN 0x20 8160786Sps 8260786Sps#define USLCOM_PORT_NO 0xFFFF /* XXX think this should be 0 --hps */ 8360786Sps 8460786Sps#define USLCOM_BREAK_OFF 0x00 8560786Sps#define USLCOM_BREAK_ON 0x01 8660786Sps 8760786Spsenum { 8860786Sps USLCOM_BULK_DT_WR, 8960786Sps USLCOM_BULK_DT_RD, 9060786Sps USLCOM_N_TRANSFER, 9160786Sps}; 9260786Sps 9360786Spsstruct uslcom_softc { 9460786Sps struct usb2_com_super_softc sc_super_ucom; 9560786Sps struct usb2_com_softc sc_ucom; 9660786Sps 9760786Sps struct usb2_xfer *sc_xfer[USLCOM_N_TRANSFER]; 9860786Sps struct usb2_device *sc_udev; 9960786Sps 10060786Sps uint8_t sc_msr; 10160786Sps uint8_t sc_lsr; 10260786Sps}; 10360786Sps 10460786Spsstatic device_probe_t uslcom_probe; 10560786Spsstatic device_attach_t uslcom_attach; 10660786Spsstatic device_detach_t uslcom_detach; 10760786Sps 10860786Spsstatic usb2_callback_t uslcom_write_callback; 10960786Spsstatic usb2_callback_t uslcom_read_callback; 11060786Sps 11160786Spsstatic void uslcom_open(struct usb2_com_softc *); 11260786Spsstatic void uslcom_close(struct usb2_com_softc *); 11360786Spsstatic void uslcom_set_dtr(struct usb2_com_softc *, uint8_t); 11460786Spsstatic void uslcom_set_rts(struct usb2_com_softc *, uint8_t); 11560786Spsstatic void uslcom_set_break(struct usb2_com_softc *, uint8_t); 11660786Spsstatic int uslcom_pre_param(struct usb2_com_softc *, struct termios *); 11760786Spsstatic void uslcom_param(struct usb2_com_softc *, struct termios *); 11860786Spsstatic void uslcom_get_status(struct usb2_com_softc *, uint8_t *, uint8_t *); 11960786Spsstatic void uslcom_start_read(struct usb2_com_softc *); 12060786Spsstatic void uslcom_stop_read(struct usb2_com_softc *); 12160786Spsstatic void uslcom_start_write(struct usb2_com_softc *); 12260786Spsstatic void uslcom_stop_write(struct usb2_com_softc *); 12360786Sps 12460786Spsstatic const struct usb2_config uslcom_config[USLCOM_N_TRANSFER] = { 12560786Sps 12660786Sps [USLCOM_BULK_DT_WR] = { 12760786Sps .type = UE_BULK, 12860786Sps .endpoint = UE_ADDR_ANY, 12960786Sps .direction = UE_DIR_OUT, 13060786Sps .mh.bufsize = USLCOM_BULK_BUF_SIZE, 13160786Sps .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 13260786Sps .mh.callback = &uslcom_write_callback, 13360786Sps }, 13460786Sps 13560786Sps [USLCOM_BULK_DT_RD] = { 13660786Sps .type = UE_BULK, 13760786Sps .endpoint = UE_ADDR_ANY, 13860786Sps .direction = UE_DIR_IN, 13960786Sps .mh.bufsize = USLCOM_BULK_BUF_SIZE, 14060786Sps .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 14160786Sps .mh.callback = &uslcom_read_callback, 14260786Sps }, 14360786Sps}; 14460786Sps 14560786Spsstruct usb2_com_callback uslcom_callback = { 14660786Sps .usb2_com_cfg_open = &uslcom_open, 14760786Sps .usb2_com_cfg_close = &uslcom_close, 14860786Sps .usb2_com_cfg_get_status = &uslcom_get_status, 14960786Sps .usb2_com_cfg_set_dtr = &uslcom_set_dtr, 15060786Sps .usb2_com_cfg_set_rts = &uslcom_set_rts, 15160786Sps .usb2_com_cfg_set_break = &uslcom_set_break, 15260786Sps .usb2_com_cfg_param = &uslcom_param, 15360786Sps .usb2_com_pre_param = &uslcom_pre_param, 15460786Sps .usb2_com_start_read = &uslcom_start_read, 15560786Sps .usb2_com_stop_read = &uslcom_stop_read, 15660786Sps .usb2_com_start_write = &uslcom_start_write, 15760786Sps .usb2_com_stop_write = &uslcom_stop_write, 15860786Sps}; 15960786Sps 16060786Spsstatic const struct usb2_device_id uslcom_devs[] = { 16160786Sps { USB_VPI(USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER, 0) }, 16260786Sps { USB_VPI(USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD, 0) }, 16360786Sps { USB_VPI(USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B, 0) }, 16460786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP, 0) }, 16560786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128, 0) }, 16660786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREE, 0) }, 16760786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BURNSIDE, 0) }, 16860786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_HELICOM, 0) }, 16960786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP, 0) }, 17060786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG, 0) }, 17160786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN, 0) }, 17260786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU, 0) }, 17360786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP2102, 0) }, 17460786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2, 0) }, 17560786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUUNTO, 0) }, 17660786Sps { USB_VPI(USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TRAQMATE, 0) }, 17760786Sps { USB_VPI(USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE, 0) }, 17860786Sps { USB_VPI(USB_VENDOR_USI, USB_PRODUCT_USI_MC60, 0) }, 17960786Sps}; 18060786Sps 18160786Spsstatic device_method_t uslcom_methods[] = { 18260786Sps DEVMETHOD(device_probe, uslcom_probe), 18360786Sps DEVMETHOD(device_attach, uslcom_attach), 18460786Sps DEVMETHOD(device_detach, uslcom_detach), 18560786Sps {0, 0} 18660786Sps}; 18760786Sps 18860786Spsstatic devclass_t uslcom_devclass; 18960786Sps 19060786Spsstatic driver_t uslcom_driver = { 19160786Sps .name = "uslcom", 19260786Sps .methods = uslcom_methods, 19360786Sps .size = sizeof(struct uslcom_softc), 19460786Sps}; 19560786Sps 19660786SpsDRIVER_MODULE(uslcom, ushub, uslcom_driver, uslcom_devclass, NULL, 0); 19760786SpsMODULE_DEPEND(uslcom, usb2_serial, 1, 1, 1); 19860786SpsMODULE_DEPEND(uslcom, usb2_core, 1, 1, 1); 19960786SpsMODULE_VERSION(uslcom, 1); 20060786Sps 20160786Spsstatic int 20260786Spsuslcom_probe(device_t dev) 20360786Sps{ 20460786Sps struct usb2_attach_arg *uaa = device_get_ivars(dev); 20560786Sps 20660786Sps DPRINTFN(11, "\n"); 20760786Sps 20860786Sps if (uaa->usb2_mode != USB_MODE_HOST) { 20960786Sps return (ENXIO); 21060786Sps } 21160786Sps if (uaa->info.bConfigIndex != USLCOM_CONFIG_INDEX) { 21260786Sps return (ENXIO); 21360786Sps } 21460786Sps if (uaa->info.bIfaceIndex != USLCOM_IFACE_INDEX) { 21560786Sps return (ENXIO); 21660786Sps } 21760786Sps return (usb2_lookup_id_by_uaa(uslcom_devs, sizeof(uslcom_devs), uaa)); 21860786Sps} 21960786Sps 22060786Spsstatic int 22160786Spsuslcom_attach(device_t dev) 22260786Sps{ 22360786Sps struct usb2_attach_arg *uaa = device_get_ivars(dev); 22460786Sps struct uslcom_softc *sc = device_get_softc(dev); 22560786Sps int error; 22660786Sps 22760786Sps DPRINTFN(11, "\n"); 22860786Sps 22960786Sps device_set_usb2_desc(dev); 23060786Sps 23160786Sps sc->sc_udev = uaa->device; 23260786Sps 23360786Sps error = usb2_transfer_setup(uaa->device, 23460786Sps &uaa->info.bIfaceIndex, sc->sc_xfer, uslcom_config, 23560786Sps USLCOM_N_TRANSFER, sc, &Giant); 23660786Sps if (error) { 23760786Sps DPRINTF("one or more missing USB endpoints, " 23860786Sps "error=%s\n", usb2_errstr(error)); 23960786Sps goto detach; 24060786Sps } 24160786Sps /* clear stall at first run */ 24260786Sps usb2_transfer_set_stall(sc->sc_xfer[USLCOM_BULK_DT_WR]); 24360786Sps usb2_transfer_set_stall(sc->sc_xfer[USLCOM_BULK_DT_RD]); 24460786Sps 24560786Sps error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 24660786Sps &uslcom_callback, &Giant); 24760786Sps if (error) { 24860786Sps goto detach; 24960786Sps } 25060786Sps return (0); 25160786Sps 25260786Spsdetach: 25360786Sps uslcom_detach(dev); 25460786Sps return (ENXIO); 25560786Sps} 25660786Sps 25760786Spsstatic int 25860786Spsuslcom_detach(device_t dev) 25960786Sps{ 26060786Sps struct uslcom_softc *sc = device_get_softc(dev); 26160786Sps 26260786Sps DPRINTF("sc=%p\n", sc); 26360786Sps 26460786Sps usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 26560786Sps 26660786Sps usb2_transfer_unsetup(sc->sc_xfer, USLCOM_N_TRANSFER); 26760786Sps 26860786Sps return (0); 26960786Sps} 27060786Sps 27160786Spsstatic void 27260786Spsuslcom_open(struct usb2_com_softc *ucom) 27360786Sps{ 27460786Sps struct uslcom_softc *sc = ucom->sc_parent; 27560786Sps struct usb2_device_request req; 27660786Sps 27760786Sps req.bmRequestType = USLCOM_WRITE; 27860786Sps req.bRequest = USLCOM_UART; 27960786Sps USETW(req.wValue, USLCOM_UART_ENABLE); 28060786Sps USETW(req.wIndex, USLCOM_PORT_NO); 28160786Sps USETW(req.wLength, 0); 28260786Sps 28360786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 28460786Sps &req, NULL, 0, 1000)) { 28560786Sps DPRINTF("UART enable failed (ignored)\n"); 28660786Sps } 28760786Sps} 28860786Sps 28960786Spsstatic void 29060786Spsuslcom_close(struct usb2_com_softc *ucom) 29160786Sps{ 29260786Sps struct uslcom_softc *sc = ucom->sc_parent; 29360786Sps struct usb2_device_request req; 29460786Sps 29560786Sps req.bmRequestType = USLCOM_WRITE; 29660786Sps req.bRequest = USLCOM_UART; 29760786Sps USETW(req.wValue, USLCOM_UART_DISABLE); 29860786Sps USETW(req.wIndex, USLCOM_PORT_NO); 29960786Sps USETW(req.wLength, 0); 30060786Sps 30160786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 30260786Sps &req, NULL, 0, 1000)) { 30360786Sps DPRINTF("UART disable failed (ignored)\n"); 30460786Sps } 30560786Sps} 30660786Sps 30760786Spsstatic void 30860786Spsuslcom_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff) 30960786Sps{ 31060786Sps struct uslcom_softc *sc = ucom->sc_parent; 31160786Sps struct usb2_device_request req; 31260786Sps uint16_t ctl; 31360786Sps 31460786Sps DPRINTF("onoff = %d\n", onoff); 31560786Sps 31660786Sps ctl = onoff ? USLCOM_CTRL_DTR_ON : 0; 31760786Sps ctl |= USLCOM_CTRL_DTR_SET; 31860786Sps 31960786Sps req.bmRequestType = USLCOM_WRITE; 32060786Sps req.bRequest = USLCOM_CTRL; 32160786Sps USETW(req.wValue, ctl); 32260786Sps USETW(req.wIndex, USLCOM_PORT_NO); 32360786Sps USETW(req.wLength, 0); 32460786Sps 32560786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 32660786Sps &req, NULL, 0, 1000)) { 32760786Sps DPRINTF("Setting DTR failed (ignored)\n"); 32860786Sps } 32960786Sps} 33060786Sps 33160786Spsstatic void 33260786Spsuslcom_set_rts(struct usb2_com_softc *ucom, uint8_t onoff) 33360786Sps{ 33460786Sps struct uslcom_softc *sc = ucom->sc_parent; 33560786Sps struct usb2_device_request req; 33660786Sps uint16_t ctl; 33760786Sps 33860786Sps DPRINTF("onoff = %d\n", onoff); 33960786Sps 34060786Sps ctl = onoff ? USLCOM_CTRL_RTS_ON : 0; 34160786Sps ctl |= USLCOM_CTRL_RTS_SET; 34260786Sps 34360786Sps req.bmRequestType = USLCOM_WRITE; 34460786Sps req.bRequest = USLCOM_CTRL; 34560786Sps USETW(req.wValue, ctl); 34660786Sps USETW(req.wIndex, USLCOM_PORT_NO); 34760786Sps USETW(req.wLength, 0); 34860786Sps 34960786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 35060786Sps &req, NULL, 0, 1000)) { 35160786Sps DPRINTF("Setting DTR failed (ignored)\n"); 35260786Sps } 35360786Sps} 35460786Sps 35560786Spsstatic int 35660786Spsuslcom_pre_param(struct usb2_com_softc *ucom, struct termios *t) 35760786Sps{ 35860786Sps if (t->c_ospeed <= 0 || t->c_ospeed > 921600) 35960786Sps return (EINVAL); 36060786Sps return (0); 36160786Sps} 36260786Sps 36360786Spsstatic void 36460786Spsuslcom_param(struct usb2_com_softc *ucom, struct termios *t) 36560786Sps{ 36660786Sps struct uslcom_softc *sc = ucom->sc_parent; 36760786Sps struct usb2_device_request req; 36860786Sps uint16_t data; 36960786Sps 37060786Sps DPRINTF("\n"); 37160786Sps 37260786Sps req.bmRequestType = USLCOM_WRITE; 37360786Sps req.bRequest = USLCOM_BAUD_RATE; 37460786Sps USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed); 37560786Sps USETW(req.wIndex, USLCOM_PORT_NO); 37660786Sps USETW(req.wLength, 0); 37760786Sps 37860786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 37960786Sps &req, NULL, 0, 1000)) { 38060786Sps DPRINTF("Set baudrate failed (ignored)\n"); 38160786Sps } 38260786Sps 38360786Sps if (t->c_cflag & CSTOPB) 38460786Sps data = USLCOM_STOP_BITS_2; 38560786Sps else 38660786Sps data = USLCOM_STOP_BITS_1; 38760786Sps if (t->c_cflag & PARENB) { 38860786Sps if (t->c_cflag & PARODD) 38960786Sps data |= USLCOM_PARITY_ODD; 39060786Sps else 39160786Sps data |= USLCOM_PARITY_EVEN; 39260786Sps } else 39360786Sps data |= USLCOM_PARITY_NONE; 39460786Sps switch (t->c_cflag & CSIZE) { 39560786Sps case CS5: 39660786Sps data |= USLCOM_SET_DATA_BITS(5); 39760786Sps break; 39860786Sps case CS6: 39960786Sps data |= USLCOM_SET_DATA_BITS(6); 40060786Sps break; 40160786Sps case CS7: 40260786Sps data |= USLCOM_SET_DATA_BITS(7); 40360786Sps break; 40460786Sps case CS8: 40560786Sps data |= USLCOM_SET_DATA_BITS(8); 40660786Sps break; 40760786Sps } 40860786Sps 40960786Sps req.bmRequestType = USLCOM_WRITE; 41060786Sps req.bRequest = USLCOM_DATA; 41160786Sps USETW(req.wValue, data); 41260786Sps USETW(req.wIndex, USLCOM_PORT_NO); 41360786Sps USETW(req.wLength, 0); 41460786Sps 41560786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 41660786Sps &req, NULL, 0, 1000)) { 41760786Sps DPRINTF("Set format failed (ignored)\n"); 41860786Sps } 41960786Sps return; 42060786Sps} 42160786Sps 42260786Spsstatic void 42360786Spsuslcom_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 42460786Sps{ 42560786Sps struct uslcom_softc *sc = ucom->sc_parent; 42660786Sps 42760786Sps DPRINTF("\n"); 42860786Sps 42960786Sps *lsr = sc->sc_lsr; 43060786Sps *msr = sc->sc_msr; 43160786Sps} 43260786Sps 43360786Spsstatic void 43460786Spsuslcom_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 43560786Sps{ 43660786Sps struct uslcom_softc *sc = ucom->sc_parent; 43760786Sps struct usb2_device_request req; 43860786Sps uint16_t brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF; 43960786Sps 44060786Sps req.bmRequestType = USLCOM_WRITE; 44160786Sps req.bRequest = USLCOM_BREAK; 44260786Sps USETW(req.wValue, brk); 44360786Sps USETW(req.wIndex, USLCOM_PORT_NO); 44460786Sps USETW(req.wLength, 0); 44560786Sps 44660786Sps if (usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 44760786Sps &req, NULL, 0, 1000)) { 44860786Sps DPRINTF("Set BREAK failed (ignored)\n"); 44960786Sps } 45060786Sps} 45160786Sps 45260786Spsstatic void 45360786Spsuslcom_write_callback(struct usb2_xfer *xfer) 45460786Sps{ 45560786Sps struct uslcom_softc *sc = xfer->priv_sc; 45660786Sps uint32_t actlen; 45760786Sps 45860786Sps switch (USB_GET_STATE(xfer)) { 45960786Sps case USB_ST_SETUP: 46060786Sps case USB_ST_TRANSFERRED: 46160786Spstr_setup: 46260786Sps if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 46360786Sps USLCOM_BULK_BUF_SIZE, &actlen)) { 46460786Sps 46560786Sps DPRINTF("actlen = %d\n", actlen); 46660786Sps 46760786Sps xfer->frlengths[0] = actlen; 46860786Sps usb2_start_hardware(xfer); 46960786Sps } 47060786Sps return; 47160786Sps 47260786Sps default: /* Error */ 47360786Sps if (xfer->error != USB_ERR_CANCELLED) { 47460786Sps /* try to clear stall first */ 47560786Sps xfer->flags.stall_pipe = 1; 47660786Sps goto tr_setup; 47760786Sps } 47860786Sps return; 47960786Sps } 48060786Sps} 48160786Sps 48260786Spsstatic void 48360786Spsuslcom_read_callback(struct usb2_xfer *xfer) 48460786Sps{ 48560786Sps struct uslcom_softc *sc = xfer->priv_sc; 48660786Sps 48760786Sps switch (USB_GET_STATE(xfer)) { 48860786Sps case USB_ST_TRANSFERRED: 48960786Sps usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen); 49060786Sps 49160786Sps case USB_ST_SETUP: 49260786Spstr_setup: 49360786Sps xfer->frlengths[0] = xfer->max_data_length; 49460786Sps usb2_start_hardware(xfer); 49560786Sps return; 49660786Sps 49760786Sps default: /* Error */ 49860786Sps if (xfer->error != USB_ERR_CANCELLED) { 49960786Sps /* try to clear stall first */ 50060786Sps xfer->flags.stall_pipe = 1; 50160786Sps goto tr_setup; 50260786Sps } 50360786Sps return; 50460786Sps } 50560786Sps} 50660786Sps 50760786Spsstatic void 50860786Spsuslcom_start_read(struct usb2_com_softc *ucom) 50960786Sps{ 51060786Sps struct uslcom_softc *sc = ucom->sc_parent; 51160786Sps 51260786Sps /* start read endpoint */ 51360786Sps usb2_transfer_start(sc->sc_xfer[USLCOM_BULK_DT_RD]); 51460786Sps} 51560786Sps 51660786Spsstatic void 51760786Spsuslcom_stop_read(struct usb2_com_softc *ucom) 51860786Sps{ 51960786Sps struct uslcom_softc *sc = ucom->sc_parent; 52060786Sps 52160786Sps /* stop read endpoint */ 52260786Sps usb2_transfer_stop(sc->sc_xfer[USLCOM_BULK_DT_RD]); 52360786Sps} 52460786Sps 52560786Spsstatic void 52660786Spsuslcom_start_write(struct usb2_com_softc *ucom) 52760786Sps{ 52860786Sps struct uslcom_softc *sc = ucom->sc_parent; 52960786Sps 53060786Sps usb2_transfer_start(sc->sc_xfer[USLCOM_BULK_DT_WR]); 53160786Sps} 53260786Sps 53360786Spsstatic void 53460786Spsuslcom_stop_write(struct usb2_com_softc *ucom) 53560786Sps{ 53660786Sps struct uslcom_softc *sc = ucom->sc_parent; 53760786Sps 53860786Sps usb2_transfer_stop(sc->sc_xfer[USLCOM_BULK_DT_WR]); 53960786Sps} 54060786Sps