svn commit: r187994 - in head: lib/libusbhid sys/dev/usb2/bluetooth sys/dev/usb2/core sys/dev/usb2/include sys/dev/usb2/input sys/dev/usb2/serial usr.bin/usbhidaction usr.bin/usbhidctl

Alfred Perlstein alfred at FreeBSD.org
Sun Feb 1 16:49:40 PST 2009


Author: alfred
Date: Mon Feb  2 00:49:39 2009
New Revision: 187994
URL: http://svn.freebsd.org/changeset/base/187994

Log:
  src/usr.bin/usbhidaction/usbhidaction.c
  src/usr.bin/usbhidctl/usbhid.c
  src/sys/dev/usb2/include/usb2_hid.h
  src/sys/dev/usb2/input/uhid2.c
  src/lib/libusbhid/Makefile
  src/lib/libusbhid/descr.c
  src/lib/libusbhid/descr_compat.c
  src/lib/libusbhid/usbhid.3
  src/lib/libusbhid/usbhid.h
  src/lib/libusbhid/usbvar.h
  
  Patches to make libusbhid and HID userland utilities compatible with
  the new USB stack. All HID ioctls should go through the libusbhid
  library to ensure compatibility. I have found at least one piece of
  software in /usr/ports which needs to get updated before USB HID
  devices will work. This is the X joystick input driver.
  
  Reported and tested by:
  
  Daichi GOTO and Masanori OZAWA.
  
  src/sys/dev/usb2/core/usb2_process.c
  
  Correct USB process names.
  
  Reported by:
  
  Andre Guibert de Bruet
  
  src/sys/dev/usb2/serial/uftdi2.c
  
  Integrate changes from old USB stack.
  
  Submitted by:	hps

Added:
  head/lib/libusbhid/descr_compat.c   (contents, props changed)
Modified:
  head/lib/libusbhid/Makefile
  head/lib/libusbhid/descr.c
  head/lib/libusbhid/usbhid.3
  head/lib/libusbhid/usbhid.h
  head/lib/libusbhid/usbvar.h
  head/sys/dev/usb2/bluetooth/ubtbcmfw2.c
  head/sys/dev/usb2/core/usb2_process.c
  head/sys/dev/usb2/include/usb2_hid.h
  head/sys/dev/usb2/input/uhid2.c
  head/sys/dev/usb2/serial/uftdi2.c
  head/usr.bin/usbhidaction/usbhidaction.c
  head/usr.bin/usbhidctl/usbhid.c

Modified: head/lib/libusbhid/Makefile
==============================================================================
--- head/lib/libusbhid/Makefile	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/lib/libusbhid/Makefile	Mon Feb  2 00:49:39 2009	(r187994)
@@ -15,7 +15,7 @@ MLINKS=	usbhid.3 libusbhid.3 usbhid.3 hi
 	usbhid.3 hid_init.3 \
 	usbhid.3 hid_get_data.3 usbhid.3 hid_set_data.3
 
-SRCS=	descr.c parse.c usage.c data.c
+SRCS=	descr.c descr_compat.c parse.c usage.c data.c
 
 INCS=	usbhid.h
 

Modified: head/lib/libusbhid/descr.c
==============================================================================
--- head/lib/libusbhid/descr.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/lib/libusbhid/descr.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -39,21 +39,83 @@ __FBSDID("$FreeBSD$");
 #include <sys/time.h>
 #include <sys/ioctl.h>
 
-#include <dev/usb/usb.h>
+#include <dev/usb2/include/usb2_ioctl.h>
 
 #include "usbhid.h"
 #include "usbvar.h"
 
+int
+hid_set_immed(int fd, int enable)
+{
+	int ret;
+	ret = ioctl(fd, USB_SET_IMMED, &enable);
+	if (ret < 0)
+		ret = hid_set_immed_compat7(fd, enable);
+	return (ret);
+}
+
+int
+hid_get_report_id(int fd)
+{
+	int temp = -1;
+	int ret;
+
+	ret = ioctl(fd, USB_GET_REPORT_ID, &temp);
+	if (ret < 0)
+		ret = hid_get_report_id_compat7(fd);
+	else
+		ret = temp;
+
+	return (ret);
+}
+
 report_desc_t
 hid_get_report_desc(int fd)
 {
-	struct usb_ctl_report_desc rep;
+	struct usb2_gen_descriptor ugd;
+	report_desc_t rep;
+	void *data;
+
+	memset(&ugd, 0, sizeof(ugd));
+
+	/* get actual length first */
+	ugd.ugd_data = NULL;
+	ugd.ugd_maxlen = 65535;
+	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
+		/* could not read descriptor */
+		/* try FreeBSD 7 compat code */
+		return (hid_get_report_desc_compat7(fd));
+	}
 
-	rep.ucrd_size = 0;
-	if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0)
+	/*
+	 * NOTE: The kernel will return a failure if 
+	 * "ugd_actlen" is zero.
+	 */
+	data = malloc(ugd.ugd_actlen);
+	if (data == NULL)
 		return (NULL);
 
-	return hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size);
+	/* fetch actual descriptor */
+	ugd.ugd_data = data;
+	ugd.ugd_maxlen = ugd.ugd_actlen;
+	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
+		/* could not read descriptor */
+		free(data);
+		return (NULL);
+	}
+
+	/* check END_COLLECTION */
+	if (((unsigned char *)ugd.ugd_data)[ugd.ugd_actlen -1] != 0xC0) {
+		/* invalid end byte */
+		free(data);
+		return (NULL);
+	}
+
+	rep = hid_use_report_desc(data, ugd.ugd_actlen);
+
+	free(data);
+
+	return (rep);
 }
 
 report_desc_t

Added: head/lib/libusbhid/descr_compat.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libusbhid/descr_compat.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 Lennart Augustsson <augustss at netbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This file contains fallback-compatibility code for the old FreeBSD
+ * USB stack.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <dev/usb/usb.h>
+
+#include "usbhid.h"
+#include "usbvar.h"
+
+int
+hid_set_immed_compat7(int fd, int enable)
+{
+	return (ioctl(fd, USB_SET_IMMED, &enable));
+}
+
+int
+hid_get_report_id_compat7(int fd)
+{
+	int temp = -1;
+
+	if (ioctl(fd, USB_GET_REPORT_ID, &temp) < 0)
+		return (-1);
+
+	return (temp);
+}
+
+report_desc_t
+hid_get_report_desc_compat7(int fd)
+{
+	struct usb_ctl_report_desc rep;
+
+	rep.ucrd_size = 0;
+	if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0)
+		return (NULL);
+
+	return (hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size));
+}

Modified: head/lib/libusbhid/usbhid.3
==============================================================================
--- head/lib/libusbhid/usbhid.3	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/lib/libusbhid/usbhid.3	Mon Feb  2 00:49:39 2009	(r187994)
@@ -26,12 +26,13 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 29, 2001
+.Dd January 27, 2009
 .Dt USBHID 3
 .Os
 .Sh NAME
 .Nm usbhid ,
 .Nm hid_get_report_desc ,
+.Nm hid_get_report_id ,
 .Nm hid_use_report_desc ,
 .Nm hid_dispose_report_desc ,
 .Nm hid_start_parse ,
@@ -51,6 +52,10 @@
 .In usbhid.h
 .Ft report_desc_t
 .Fn hid_get_report_desc "int file"
+.Ft int
+.Fn hid_get_report_id "int file"
+.Ft int
+.Fn hid_set_immed "int fd" "int enable"
 .Ft report_desc_t
 .Fn hid_use_report_desc "unsigned char *data" "unsigned int size"
 .Ft void
@@ -94,7 +99,15 @@ which contains the data layout informati
 The routines can be divided into four parts: extraction of the descriptor,
 parsing of the descriptor, translating to/from symbolic names, and
 data manipulation.
+.Ss Synchronous HID operation
+Synchronous HID operation can be enabled or disabled by a call to
+.Fn hid_set_immed .
+If the second argument is zero synchronous HID operation is disabled.
+Else synchronous HID operation is enabled.
+The function returns a negative value on failure.
 .Ss Descriptor Functions
+The report descriptor ID can be obtained by calling
+.Fn hid_get_report_id .
 A report descriptor can be obtained by calling
 .Fn hid_get_report_desc
 with a file descriptor obtained by opening a

Modified: head/lib/libusbhid/usbhid.h
==============================================================================
--- head/lib/libusbhid/usbhid.h	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/lib/libusbhid/usbhid.h	Mon Feb  2 00:49:39 2009	(r187994)
@@ -87,6 +87,8 @@ __BEGIN_DECLS
 report_desc_t hid_get_report_desc(int file);
 report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size);
 void hid_dispose_report_desc(report_desc_t);
+int hid_get_report_id(int file);
+int hid_set_immed(int fd, int enable);
 
 /* Parsing of a HID report descriptor, parse.c: */
 hid_data_t hid_start_parse(report_desc_t d, int kindset, int id);

Modified: head/lib/libusbhid/usbvar.h
==============================================================================
--- head/lib/libusbhid/usbvar.h	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/lib/libusbhid/usbvar.h	Mon Feb  2 00:49:39 2009	(r187994)
@@ -34,3 +34,8 @@ struct report_desc {
 	unsigned char data[1];
 };
 
+/* internal backwards compatibility functions */
+
+int	hid_set_immed_compat7(int fd, int enable);
+int	hid_get_report_id_compat7(int fd);
+report_desc_t	hid_get_report_desc_compat7(int fd);

Modified: head/sys/dev/usb2/bluetooth/ubtbcmfw2.c
==============================================================================
--- head/sys/dev/usb2/bluetooth/ubtbcmfw2.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/sys/dev/usb2/bluetooth/ubtbcmfw2.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -385,8 +385,8 @@ ubtbcmfw_open(struct usb2_fifo *fifo, in
 	else if (fflags & FWRITE)
 		xfer = sc->sc_xfer[UBTBCMFW_BULK_DT_WR];
 	else
-		return (EINVAL);	/* XXX can happen? */
-		
+		return (EINVAL);	/* should not happen */
+
 	if (usb2_fifo_alloc_buffer(fifo, xfer->max_data_length,
 			UBTBCMFW_IFQ_MAXLEN) != 0)
 		return (ENOMEM);

Modified: head/sys/dev/usb2/core/usb2_process.c
==============================================================================
--- head/sys/dev/usb2/core/usb2_process.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/sys/dev/usb2/core/usb2_process.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -184,11 +184,11 @@ usb2_proc_setup(struct usb2_process *up,
 
 	TAILQ_INIT(&up->up_qhead);
 
-	usb2_cv_init(&up->up_cv, "WMSG");
-	usb2_cv_init(&up->up_drain, "DMSG");
+	usb2_cv_init(&up->up_cv, "wmsg");
+	usb2_cv_init(&up->up_drain, "dmsg");
 
 	if (USB_THREAD_CREATE(&usb2_process, up,
-	    &up->up_ptr, "USBPROC")) {
+	    &up->up_ptr, "usbproc")) {
 		DPRINTFN(0, "Unable to create USB process.");
 		up->up_ptr = NULL;
 		goto error;

Modified: head/sys/dev/usb2/include/usb2_hid.h
==============================================================================
--- head/sys/dev/usb2/include/usb2_hid.h	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/sys/dev/usb2/include/usb2_hid.h	Mon Feb  2 00:49:39 2009	(r187994)
@@ -29,6 +29,8 @@
 #ifndef _USB2_HID_H_
 #define	_USB2_HID_H_
 
+#include <dev/usb2/include/usb2_endian.h>
+
 #define	UR_GET_HID_DESCRIPTOR	0x06
 #define	UDESC_HID		0x21
 #define	UDESC_REPORT		0x22

Modified: head/sys/dev/usb2/input/uhid2.c
==============================================================================
--- head/sys/dev/usb2/input/uhid2.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/sys/dev/usb2/input/uhid2.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -87,10 +87,9 @@ SYSCTL_INT(_hw_usb2_uhid, OID_AUTO, debu
 
 enum {
 	UHID_INTR_DT_RD,
-	UHID_INTR_CS_RD,
 	UHID_CTRL_DT_WR,
 	UHID_CTRL_DT_RD,
-	UHID_N_TRANSFER = 4,
+	UHID_N_TRANSFER,
 };
 
 struct uhid_softc {
@@ -114,7 +113,6 @@ struct uhid_softc {
 	uint8_t	sc_fid;
 	uint8_t	sc_flags;
 #define	UHID_FLAG_IMMED        0x01	/* set if read should be immediate */
-#define	UHID_FLAG_INTR_STALL   0x02	/* set if interrupt transfer stalled */
 #define	UHID_FLAG_STATIC_DESC  0x04	/* set if report descriptors are
 					 * static */
 };
@@ -130,7 +128,6 @@ static device_attach_t uhid_attach;
 static device_detach_t uhid_detach;
 
 static usb2_callback_t uhid_intr_callback;
-static usb2_callback_t uhid_intr_clear_stall_callback;
 static usb2_callback_t uhid_write_callback;
 static usb2_callback_t uhid_read_callback;
 
@@ -174,41 +171,25 @@ uhid_intr_callback(struct usb2_xfer *xfe
 		}
 
 	case USB_ST_SETUP:
-		if (sc->sc_flags & UHID_FLAG_INTR_STALL) {
-			usb2_transfer_start(sc->sc_xfer[UHID_INTR_CS_RD]);
-		} else {
-			if (usb2_fifo_put_bytes_max(
-			    sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
-				xfer->frlengths[0] = xfer->max_data_length;
-				usb2_start_hardware(xfer);
-			}
+re_submit:
+		if (usb2_fifo_put_bytes_max(
+		    sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
+			xfer->frlengths[0] = sc->sc_isize;
+			usb2_start_hardware(xfer);
 		}
 		return;
 
 	default:			/* Error */
 		if (xfer->error != USB_ERR_CANCELLED) {
 			/* try to clear stall first */
-			sc->sc_flags |= UHID_FLAG_INTR_STALL;
-			usb2_transfer_start(sc->sc_xfer[UHID_INTR_CS_RD]);
+			xfer->flags.stall_pipe = 1;
+			goto re_submit;
 		}
 		return;
 	}
 }
 
 static void
-uhid_intr_clear_stall_callback(struct usb2_xfer *xfer)
-{
-	struct uhid_softc *sc = xfer->priv_sc;
-	struct usb2_xfer *xfer_other = sc->sc_xfer[UHID_INTR_DT_RD];
-
-	if (usb2_clear_stall_callback(xfer, xfer_other)) {
-		DPRINTF("stall cleared\n");
-		sc->sc_flags &= ~UHID_FLAG_INTR_STALL;
-		usb2_transfer_start(xfer_other);
-	}
-}
-
-static void
 uhid_fill_set_report(struct usb2_device_request *req, uint8_t iface_no,
     uint8_t type, uint8_t id, uint16_t size)
 {
@@ -337,20 +318,10 @@ static const struct usb2_config uhid_con
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
 		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
-		.mh.bufsize = 0,	/* use wMaxPacketSize */
+		.mh.bufsize = UHID_BSIZE,
 		.mh.callback = &uhid_intr_callback,
 	},
 
-	[UHID_INTR_CS_RD] = {
-		.type = UE_CONTROL,
-		.endpoint = 0x00,	/* Control pipe */
-		.direction = UE_DIR_ANY,
-		.mh.bufsize = sizeof(struct usb2_device_request),
-		.mh.callback = &uhid_intr_clear_stall_callback,
-		.mh.timeout = 1000,	/* 1 second */
-		.mh.interval = 50,	/* 50ms */
-	},
-
 	[UHID_CTRL_DT_WR] = {
 		.type = UE_CONTROL,
 		.endpoint = 0x00,	/* Control pipe */
@@ -530,6 +501,8 @@ uhid_ioctl(struct usb2_fifo *fifo, u_lon
 			size = sc->sc_repdesc_size;
 		}
 		ugd->ugd_actlen = size;
+		if (ugd->ugd_data == NULL)
+			break;		/* descriptor length only */
 		error = copyout(sc->sc_repdesc_ptr, ugd->ugd_data, size);
 		break;
 

Modified: head/sys/dev/usb2/serial/uftdi2.c
==============================================================================
--- head/sys/dev/usb2/serial/uftdi2.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/sys/dev/usb2/serial/uftdi2.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -233,6 +233,7 @@ MODULE_DEPEND(uftdi, usb2_serial, 1, 1, 
 MODULE_DEPEND(uftdi, usb2_core, 1, 1, 1);
 
 static struct usb2_device_id uftdi_devs[] = {
+	{USB_VPI(USB_VENDOR_DRESDENELEKTRONIK, USB_PRODUCT_DRESDENELEKTRONIK_SENSORTERMINALBOARD, UFTDI_TYPE_8U232AM)},
 	{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_8U100AX, UFTDI_TYPE_SIO)},
 	{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_2232C, UFTDI_TYPE_8U232AM)},
 	{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_8U232AM, UFTDI_TYPE_8U232AM)},

Modified: head/usr.bin/usbhidaction/usbhidaction.c
==============================================================================
--- head/usr.bin/usbhidaction/usbhidaction.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/usr.bin/usbhidaction/usbhidaction.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -46,9 +46,7 @@
 #include <limits.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <sys/ioctl.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbhid.h>
+#include <dev/usb2/include/usb2_hid.h>
 #include <usbhid.h>
 #include <syslog.h>
 #include <signal.h>
@@ -155,8 +153,7 @@ main(int argc, char **argv)
 	fd = open(dev, O_RDWR);
 	if (fd < 0)
 		err(1, "%s", dev);
-	if (ioctl(fd, USB_GET_REPORT_ID, &reportid) < 0)
-		reportid = -1;
+	reportid = hid_get_report_id(fd);
 	repd = hid_get_report_desc(fd);
 	if (repd == NULL)
 		err(1, "hid_get_report_desc() failed");

Modified: head/usr.bin/usbhidctl/usbhid.c
==============================================================================
--- head/usr.bin/usbhidctl/usbhid.c	Sun Feb  1 23:28:52 2009	(r187993)
+++ head/usr.bin/usbhidctl/usbhid.c	Mon Feb  2 00:49:39 2009	(r187994)
@@ -42,14 +42,12 @@
 #include <string.h>
 #include <sys/types.h>
 #include <fcntl.h>
-#include <sys/ioctl.h>
 #include <unistd.h>
 #include <err.h>
 #include <ctype.h>
 #include <errno.h>
 #include <usbhid.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbhid.h>
+#include <dev/usb2/include/usb2_hid.h>
 
 int verbose = 0;
 int all = 0;
@@ -207,7 +205,6 @@ dumpdata(int f, report_desc_t rd, int lo
 	struct hid_item h, *hids, *n;
 	int r, dlen;
 	u_char *dbuf;
-	static int one = 1;
 	u_int32_t colls[100];
 	int sp = 0;
 	char namebuf[10000], *namep;
@@ -231,7 +228,7 @@ dumpdata(int f, report_desc_t rd, int lo
 	dlen = hid_report_size(rd, hid_input, 0);
 	dbuf = malloc(dlen);
 	if (!loop)
-		if (ioctl(f, USB_SET_IMMED, &one) < 0) {
+		if (hid_set_immed(f, 1) < 0) {
 			if (errno == EOPNOTSUPP)
 				warnx("device does not support immediate mode, only changes reported.");
 			else


More information about the svn-src-head mailing list