From owner-svn-src-stable-10@FreeBSD.ORG Thu May 21 06:47:22 2015 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E7BC75E3; Thu, 21 May 2015 06:47:22 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D386E17F6; Thu, 21 May 2015 06:47:22 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t4L6lMji094091; Thu, 21 May 2015 06:47:22 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t4L6lKKR094082; Thu, 21 May 2015 06:47:20 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201505210647.t4L6lKKR094082@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Thu, 21 May 2015 06:47:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r283173 - in stable/10: share/man/man4 sys/dev/usb sys/dev/usb/quirk X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 May 2015 06:47:23 -0000 Author: hselasky Date: Thu May 21 06:47:20 2015 New Revision: 283173 URL: https://svnweb.freebsd.org/changeset/base/283173 Log: MFC r282577: Add support for DYMO LabelWriter PnP. Modified: stable/10/share/man/man4/usb_quirk.4 stable/10/sys/dev/usb/quirk/usb_quirk.c stable/10/sys/dev/usb/quirk/usb_quirk.h stable/10/sys/dev/usb/usb_device.c stable/10/sys/dev/usb/usb_msctest.c stable/10/sys/dev/usb/usb_msctest.h stable/10/sys/dev/usb/usbdevs Directory Properties: stable/10/ (props changed) Modified: stable/10/share/man/man4/usb_quirk.4 ============================================================================== --- stable/10/share/man/man4/usb_quirk.4 Thu May 21 06:34:06 2015 (r283172) +++ stable/10/share/man/man4/usb_quirk.4 Thu May 21 06:47:20 2015 (r283173) @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 21, 2013 +.Dd May 7, 2015 .Dt USB_QUIRK 4 .Os .Sh NAME @@ -170,6 +170,9 @@ ejects after Huawei SCSI command .It UQ_MSC_EJECT_TCT ejects after TCT SCSI command .Dv 0x06f504025270 +.It UQ_MSC_DYMO_EJECT +ejects after HID command +.Dv 0x1b5a01 .El .Pp See Modified: stable/10/sys/dev/usb/quirk/usb_quirk.c ============================================================================== --- stable/10/sys/dev/usb/quirk/usb_quirk.c Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/quirk/usb_quirk.c Thu May 21 06:47:20 2015 (r283173) @@ -523,6 +523,9 @@ static struct usb_quirk_entry usb_quirks USB_QUIRK(FEIYA, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY), USB_QUIRK(REALTEK, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY), USB_QUIRK(INITIO, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY), + + /* DYMO LabelManager Pnp */ + USB_QUIRK(DYMO, LABELMANAGERPNP, 0x0000, 0xffff, UQ_MSC_DYMO_EJECT), }; #undef USB_QUIRK_VP #undef USB_QUIRK @@ -592,6 +595,7 @@ static const char *usb_quirk_str[USB_QUI [UQ_BAD_MIDI] = "UQ_BAD_MIDI", [UQ_AU_VENDOR_CLASS] = "UQ_AU_VENDOR_CLASS", [UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI", + [UQ_MSC_DYMO_EJECT] = "UQ_MSC_DYMO_EJECT", }; /*------------------------------------------------------------------------* Modified: stable/10/sys/dev/usb/quirk/usb_quirk.h ============================================================================== --- stable/10/sys/dev/usb/quirk/usb_quirk.h Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/quirk/usb_quirk.h Thu May 21 06:47:20 2015 (r283173) @@ -108,6 +108,7 @@ enum { UQ_BAD_MIDI, /* device claims MIDI class, but isn't */ UQ_AU_VENDOR_CLASS, /* audio device uses vendor and not audio class */ UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */ + UQ_MSC_DYMO_EJECT, /* ejects Dymo MSC device */ USB_QUIRK_MAX }; Modified: stable/10/sys/dev/usb/usb_device.c ============================================================================== --- stable/10/sys/dev/usb/usb_device.c Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/usb_device.c Thu May 21 06:47:20 2015 (r283173) @@ -1346,6 +1346,12 @@ usb_probe_and_attach(struct usb_device * */ if (iface_index == USB_IFACE_INDEX_ANY) { + if (usb_test_quirk(&uaa, UQ_MSC_DYMO_EJECT) != 0 && + usb_dymo_eject(udev, 0) == 0) { + /* success, mark the udev as disappearing */ + uaa.dev_state = UAA_DEV_EJECTING; + } + EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa); if (uaa.dev_state != UAA_DEV_READY) { Modified: stable/10/sys/dev/usb/usb_msctest.c ============================================================================== --- stable/10/sys/dev/usb/usb_msctest.c Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/usb_msctest.c Thu May 21 06:47:20 2015 (r283173) @@ -177,6 +177,7 @@ static usb_callback_t bbb_data_rd_cs_cal 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); @@ -184,7 +185,7 @@ static void bbb_data_clear_stall_callbac 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] = { @@ -247,6 +248,19 @@ static const struct usb_config bbb_confi }, }; +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) { @@ -467,6 +481,47 @@ bbb_status_callback(struct usb_xfer *xfe } } +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 * @@ -502,13 +557,45 @@ bbb_command_start(struct bbb_transfer *s 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; uint8_t do_unlock; /* Prevent re-enumeration */ @@ -528,22 +615,39 @@ bbb_attach(struct usb_device *udev, uint 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); @@ -553,22 +657,27 @@ bbb_attach(struct usb_device *udev, uint 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); } @@ -597,7 +706,7 @@ usb_iface_is_cdrom(struct usb_device *ud 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); @@ -653,7 +762,7 @@ usb_msc_auto_quirk(struct usb_device *ud 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); @@ -822,7 +931,7 @@ usb_msc_eject(struct usb_device *udev, u 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); @@ -881,3 +990,19 @@ usb_msc_eject(struct usb_device *udev, u bbb_detach(sc); return (0); } + +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); +} + Modified: stable/10/sys/dev/usb/usb_msctest.h ============================================================================== --- stable/10/sys/dev/usb/usb_msctest.h Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/usb_msctest.h Thu May 21 06:47:20 2015 (r283173) @@ -43,5 +43,7 @@ usb_error_t usb_msc_eject(struct usb_dev uint8_t iface_index, int method); usb_error_t usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index); +usb_error_t usb_dymo_eject(struct usb_device *udev, + uint8_t iface_index); #endif /* _USB_MSCTEST_H_ */ Modified: stable/10/sys/dev/usb/usbdevs ============================================================================== --- stable/10/sys/dev/usb/usbdevs Thu May 21 06:34:06 2015 (r283172) +++ stable/10/sys/dev/usb/usbdevs Thu May 21 06:47:20 2015 (r283173) @@ -452,6 +452,7 @@ vendor GLOBESPAN 0x0915 Globespan vendor CONCORDCAMERA 0x0919 Concord Camera vendor GARMIN 0x091e Garmin International vendor GOHUBS 0x0921 GoHubs +vendor DYMO 0x0922 DYMO vendor XEROX 0x0924 Xerox vendor BIOMETRIC 0x0929 American Biometric Company vendor TOSHIBA 0x0930 Toshiba @@ -1670,6 +1671,9 @@ product DRESDENELEKTRONIK WIRELESSHANDHE product DRESDENELEKTRONIK DE_RFNODE 0x001c deRFnode product DRESDENELEKTRONIK LEVELSHIFTERSTICKLOWCOST 0x0022 Levelshifter Stick Low Cost +/* DYMO */ +product DYMO LABELMANAGERPNP 0x1001 DYMO LabelManager PnP + /* Dynastream Innovations */ product DYNASTREAM ANTDEVBOARD 0x1003 ANT dev board product DYNASTREAM ANT2USB 0x1004 ANT2USB