diff options
author | hselasky <hselasky@FreeBSD.org> | 2015-05-07 12:54:27 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2015-05-07 12:54:27 +0000 |
commit | 2f22788e3eb86bb4b2c2280959fbff4ff33c47d8 (patch) | |
tree | 4bf429fdcc5e4efcf53021f7b5a4b366f01ef79f /sys/dev/usb/usb_msctest.c | |
parent | b87b82a356ee530d5dfe2eeff2100d9bb6079e35 (diff) | |
download | FreeBSD-src-2f22788e3eb86bb4b2c2280959fbff4ff33c47d8.zip FreeBSD-src-2f22788e3eb86bb4b2c2280959fbff4ff33c47d8.tar.gz |
Add support for DYMO LabelWriter PnP.
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/usb/usb_msctest.c')
-rw-r--r-- | sys/dev/usb/usb_msctest.c | 190 |
1 files changed, 157 insertions, 33 deletions
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c index c77afd0..b99fd29 100644 --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -181,6 +181,7 @@ static usb_callback_t bbb_data_rd_cs_callback; static usb_callback_t bbb_data_write_callback; static usb_callback_t bbb_data_wr_cs_callback; static usb_callback_t bbb_status_callback; +static usb_callback_t bbb_raw_write_callback; static void bbb_done(struct bbb_transfer *, int); static void bbb_transfer_start(struct bbb_transfer *, uint8_t); @@ -188,7 +189,7 @@ static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t, uint8_t); static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t, void *, size_t, void *, size_t, usb_timeout_t); -static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t); +static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t, uint8_t); static void bbb_detach(struct bbb_transfer *); static const struct usb_config bbb_config[ST_MAX] = { @@ -251,6 +252,19 @@ static const struct usb_config bbb_config[ST_MAX] = { }, }; +static const struct usb_config bbb_raw_config[1] = { + + [0] = { + .type = UE_BULK_INTR, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = SCSI_MAX_LEN, + .flags = {.ext_buffer = 1,.proxy_buffer = 1,}, + .callback = &bbb_raw_write_callback, + .timeout = 1 * USB_MS_HZ, /* 1 second */ + }, +}; + static void bbb_done(struct bbb_transfer *sc, int error) { @@ -471,6 +485,47 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error) } } +static void +bbb_raw_write_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct bbb_transfer *sc = usbd_xfer_softc(xfer); + usb_frlength_t max_bulk = usbd_xfer_max_len(xfer); + int actlen, sumlen; + + usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + sc->data_rem -= actlen; + sc->data_ptr += actlen; + sc->actlen += actlen; + + if (actlen < sumlen) { + /* short transfer */ + sc->data_rem = 0; + } + case USB_ST_SETUP: + DPRINTF("max_bulk=%d, data_rem=%d\n", + max_bulk, sc->data_rem); + + if (sc->data_rem == 0) { + bbb_done(sc, 0); + break; + } + if (max_bulk > sc->data_rem) { + max_bulk = sc->data_rem; + } + usbd_xfer_set_timeout(xfer, sc->data_timeout); + usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk); + usbd_transfer_submit(xfer); + break; + + default: /* Error */ + bbb_done(sc, error); + break; + } +} + /*------------------------------------------------------------------------* * bbb_command_start - execute a SCSI command synchronously * @@ -506,13 +561,45 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun, return (sc->error); } +/*------------------------------------------------------------------------* + * bbb_raw_write - write a raw BULK message synchronously + * + * Return values + * 0: Success + * Else: Failure + *------------------------------------------------------------------------*/ +static int +bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len, + usb_timeout_t data_timeout) +{ + sc->data_ptr = __DECONST(void *, data_ptr); + sc->data_len = data_len; + sc->data_rem = data_len; + sc->data_timeout = (data_timeout + USB_MS_HZ); + sc->actlen = 0; + sc->error = 0; + + DPRINTFN(1, "BULK DATA = %*D\n", (int)data_len, + (const char *)data_ptr, ":"); + + mtx_lock(&sc->mtx); + usbd_transfer_start(sc->xfer[0]); + while (usbd_transfer_pending(sc->xfer[0])) + cv_wait(&sc->cv, &sc->mtx); + mtx_unlock(&sc->mtx); + return (sc->error); +} + static struct bbb_transfer * -bbb_attach(struct usb_device *udev, uint8_t iface_index) +bbb_attach(struct usb_device *udev, uint8_t iface_index, + uint8_t bInterfaceClass) { struct usb_interface *iface; struct usb_interface_descriptor *id; + const struct usb_config *pconfig; struct bbb_transfer *sc; usb_error_t err; + int nconfig; #if USB_HAVE_MSCTEST_DETACH uint8_t do_unlock; @@ -535,22 +622,39 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index) return (NULL); id = iface->idesc; - if (id == NULL || id->bInterfaceClass != UICLASS_MASS) + if (id == NULL || id->bInterfaceClass != bInterfaceClass) return (NULL); - switch (id->bInterfaceSubClass) { - case UISUBCLASS_SCSI: - case UISUBCLASS_UFI: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: + switch (id->bInterfaceClass) { + case UICLASS_MASS: + switch (id->bInterfaceSubClass) { + case UISUBCLASS_SCSI: + case UISUBCLASS_UFI: + case UISUBCLASS_SFF8020I: + case UISUBCLASS_SFF8070I: + break; + default: + return (NULL); + } + switch (id->bInterfaceProtocol) { + case UIPROTO_MASS_BBB_OLD: + case UIPROTO_MASS_BBB: + break; + default: + return (NULL); + } + pconfig = bbb_config; + nconfig = ST_MAX; break; - default: - return (NULL); - } - - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_BBB_OLD: - case UIPROTO_MASS_BBB: + case UICLASS_HID: + switch (id->bInterfaceSubClass) { + case 0: + break; + default: + return (NULL); + } + pconfig = bbb_raw_config; + nconfig = 1; break; default: return (NULL); @@ -560,22 +664,27 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index) mtx_init(&sc->mtx, "USB autoinstall", NULL, MTX_DEF); cv_init(&sc->cv, "WBBB"); - err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config, - ST_MAX, sc, &sc->mtx); + err = usbd_transfer_setup(udev, &iface_index, sc->xfer, pconfig, + nconfig, sc, &sc->mtx); if (err) { bbb_detach(sc); return (NULL); } - /* store pointer to DMA buffers */ - sc->buffer = usbd_xfer_get_frame_buffer( - sc->xfer[ST_DATA_RD], 0); - sc->buffer_size = - usbd_xfer_max_len(sc->xfer[ST_DATA_RD]); - sc->cbw = usbd_xfer_get_frame_buffer( - sc->xfer[ST_COMMAND], 0); - sc->csw = usbd_xfer_get_frame_buffer( - sc->xfer[ST_STATUS], 0); - + switch (id->bInterfaceClass) { + case UICLASS_MASS: + /* store pointer to DMA buffers */ + sc->buffer = usbd_xfer_get_frame_buffer( + sc->xfer[ST_DATA_RD], 0); + sc->buffer_size = + usbd_xfer_max_len(sc->xfer[ST_DATA_RD]); + sc->cbw = usbd_xfer_get_frame_buffer( + sc->xfer[ST_COMMAND], 0); + sc->csw = usbd_xfer_get_frame_buffer( + sc->xfer[ST_STATUS], 0); + break; + default: + break; + } return (sc); } @@ -604,7 +713,7 @@ usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index) uint8_t sid_type; int err; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (0); @@ -660,7 +769,7 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) uint8_t sid_type; int err; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (0); @@ -829,7 +938,7 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) struct bbb_transfer *sc; usb_error_t err; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (USB_ERR_INVAL); @@ -890,6 +999,21 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) } usb_error_t +usb_dymo_eject(struct usb_device *udev, uint8_t iface_index) +{ + static const uint8_t data[3] = { 0x1b, 0x5a, 0x01 }; + struct bbb_transfer *sc; + usb_error_t err; + + sc = bbb_attach(udev, iface_index, UICLASS_HID); + if (sc == NULL) + return (USB_ERR_INVAL); + err = bbb_raw_write(sc, data, sizeof(data), USB_MS_HZ); + bbb_detach(sc); + return (err); +} + +usb_error_t usb_msc_read_10(struct usb_device *udev, uint8_t iface_index, uint32_t lba, uint32_t blocks, void *buffer) { @@ -908,7 +1032,7 @@ usb_msc_read_10(struct usb_device *udev, uint8_t iface_index, cmd[8] = blocks; cmd[9] = 0; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (USB_ERR_INVAL); @@ -939,7 +1063,7 @@ usb_msc_write_10(struct usb_device *udev, uint8_t iface_index, cmd[8] = blocks; cmd[9] = 0; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (USB_ERR_INVAL); @@ -958,7 +1082,7 @@ usb_msc_read_capacity(struct usb_device *udev, uint8_t iface_index, struct bbb_transfer *sc; usb_error_t err; - sc = bbb_attach(udev, iface_index); + sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (USB_ERR_INVAL); |