Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 May 2015 06:47:20 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
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
Message-ID:  <201505210647.t4L6lKKR094082@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505210647.t4L6lKKR094082>