changeset 11489:29bcdf3d8d8c

PSARC/2009/621 usbwcm: Wacom USB Tablet STREAMS module 6901884 usbwcm: Wacom USB Tablet STREAMS module
author Pengcheng Chen - Sun Microsystems - Beijing China <Pengcheng.Chen@Sun.COM>
date Thu, 14 Jan 2010 17:07:01 +0800
parents f39a595c0193
children f88657db64df
files usr/src/pkgdefs/SUNWusb/prototype_i386 usr/src/pkgdefs/SUNWusb/prototype_sparc usr/src/pkgdefs/SUNWusbu/prototype_com usr/src/uts/common/Makefile.files usr/src/uts/common/Makefile.rules usr/src/uts/common/io/usb/clients/usbinput/usbwcm/usbwcm.c usr/src/uts/common/sys/Makefile usr/src/uts/common/sys/Makefile.syshdrs usr/src/uts/common/sys/usb/clients/usbinput/usbwcm/usbwcm.h usr/src/uts/intel/Makefile.intel.shared usr/src/uts/intel/usbwcm/Makefile usr/src/uts/sparc/Makefile.sparc.shared usr/src/uts/sparc/usbwcm/Makefile
diffstat 13 files changed, 2405 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/pkgdefs/SUNWusb/prototype_i386	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/pkgdefs/SUNWusb/prototype_i386	Thu Jan 14 17:07:01 2010 +0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -68,6 +68,7 @@
 f none kernel/misc/hwa1480_fw 0755 root sys
 f none kernel/strmod/usbkbm 0755 root sys
 f none kernel/strmod/usbms 0755 root sys
+f none kernel/strmod/usbwcm 0755 root sys
 f none kernel/strmod/usb_ah 0755 root sys
 d none kernel/dacf/amd64 0755 root sys
 d none kernel/drv/amd64 0755 root sys
@@ -94,4 +95,5 @@
 d none kernel/strmod/amd64 0755 root sys
 f none kernel/strmod/amd64/usbkbm 0755 root sys
 f none kernel/strmod/amd64/usbms 0755 root sys
+f none kernel/strmod/amd64/usbwcm 0755 root sys
 f none kernel/strmod/amd64/usb_ah 0755 root sys
--- a/usr/src/pkgdefs/SUNWusb/prototype_sparc	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/pkgdefs/SUNWusb/prototype_sparc	Thu Jan 14 17:07:01 2010 +0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -72,4 +72,5 @@
 d none kernel/strmod/sparcv9 0755 root sys
 f none kernel/strmod/sparcv9/usbkbm 0755 root sys
 f none kernel/strmod/sparcv9/usbms 0755 root sys
+f none kernel/strmod/sparcv9/usbwcm 0755 root sys
 f none kernel/strmod/sparcv9/usb_ah 0755 root sys
--- a/usr/src/pkgdefs/SUNWusbu/prototype_com	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/pkgdefs/SUNWusbu/prototype_com	Thu Jan 14 17:07:01 2010 +0800
@@ -20,7 +20,7 @@
 #
 #
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -57,6 +57,8 @@
 d none usr/include/sys/usb/clients/mass_storage 755 root bin
 d none usr/include/sys/usb/clients/printer 755 root bin
 d none usr/include/sys/usb/clients/usbcdc 755 root bin
+d none usr/include/sys/usb/clients/usbinput 755 root bin
+d none usr/include/sys/usb/clients/usbinput/usbwcm 755 root bin
 d none usr/include/sys/usb/clients/video 755 root bin
 d none usr/include/sys/usb/clients/video/usbvc 755 root bin
 d none usr/include/sys/uwb 755 root bin
@@ -72,6 +74,7 @@
 f none usr/include/sys/usb/clients/mass_storage/usb_cbi.h 644 root bin
 f none usr/include/sys/usb/clients/printer/usb_printer.h 644 root bin
 f none usr/include/sys/usb/clients/usbcdc/usb_cdc.h 644 root bin
+f none usr/include/sys/usb/clients/usbinput/usbwcm/usbwcm.h 644 root bin
 f none usr/include/sys/usb/clients/video/usbvc/usbvc.h 644 root bin
 f none usr/include/sys/uwb/uwb.h 644 root bin
 f none usr/include/sys/uwb/uwbai.h 644 root bin
--- a/usr/src/uts/common/Makefile.files	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/common/Makefile.files	Thu Jan 14 17:07:01 2010 +0800
@@ -728,6 +728,8 @@
 
 USBKBM_OBJS += usbkbm.o
 
+USBWCM_OBJS += usbwcm.o
+
 BOFI_OBJS += bofi.o
 
 HID_OBJS += hid.o
--- a/usr/src/uts/common/Makefile.rules	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/common/Makefile.rules	Thu Jan 14 17:07:01 2010 +0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # uts/common/Makefile.rules
@@ -1142,6 +1142,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/common/io/usb/clients/usbinput/usbwcm/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/io/usb/clients/ugen/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -2321,6 +2325,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/usb/clients/usbms/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/usb/clients/usbinput/usbwcm/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/usb/clients/ugen/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/usb/clients/usbinput/usbwcm/usbwcm.c	Thu Jan 14 17:07:01 2010 +0800
@@ -0,0 +1,1709 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2007, 2008 Bartosz Fabianowski <freebsd@chillt.de>
+ * All rights reserved.
+ *
+ * Financed by the "Irish Research Council for Science, Engineering and
+ * Technology: funded by the National Development Plan"
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/stropts.h>
+#include <sys/strsun.h>
+#include <sys/termios.h>
+#include <sys/termio.h>
+#include <sys/strtty.h>
+#include <sys/systm.h>
+
+#include <sys/usb/usba/usbai_version.h>
+#include <sys/usb/usba.h>
+#include <sys/usb/usba/usbai_private.h>
+#include <sys/usb/clients/hid/hid.h>
+#include <sys/usb/clients/usbinput/usbwcm/usbwcm.h>
+
+/* debugging information */
+uint_t	usbwcm_errmask = (uint_t)PRINT_MASK_ALL;
+uint_t	usbwcm_errlevel = USB_LOG_L2;
+static usb_log_handle_t usbwcm_log_handle;
+
+static void
+uwacom_event(usbwcm_state_t *usbwcmp, uint_t type, uint_t idx, int val)
+{
+	struct uwacom_softc	*sc = &usbwcmp->usbwcm_softc;
+	mblk_t			*mp;
+
+	switch (type) {
+	case EVT_SYN:
+		if (sc->sc_sync)
+			return;
+		break;
+
+	case EVT_BTN:
+		if (sc->sc_btn[idx] == val)
+			return;
+
+		sc->sc_btn[idx] = val;
+		break;
+
+	case EVT_ABS:
+		if (sc->sc_abs[idx].fuzz) {
+			int dist = abs(val - sc->sc_abs[idx].value);
+
+			if (dist < sc->sc_abs[idx].fuzz >> 1) {
+				return;
+			} else if (dist < sc->sc_abs[idx].fuzz) {
+				val = (7 * sc->sc_abs[idx].value + val) >> 3;
+			} else if (dist < sc->sc_abs[idx].fuzz << 1) {
+				val = (sc->sc_abs[idx].value + val) >> 1;
+			}
+		}
+		if (sc->sc_abs[idx].value == val) {
+			return;
+		}
+
+		sc->sc_abs[idx].value = val;
+		break;
+
+	case EVT_REL:
+		if (!val)
+			return;
+		break;
+
+	case EVT_MSC:
+		break;
+
+	default:
+		return;
+	}
+
+	if ((mp = allocb(sizeof (struct event_input), BPRI_HI)) != NULL) {
+		struct event_input *ev = (struct event_input *)mp->b_wptr;
+
+		ev->type = (uint16_t)type;
+		ev->code = (uint16_t)idx;
+		ev->value = (int32_t)val;
+		uniqtime32(&ev->time);
+
+		mp->b_wptr += sizeof (struct event_input);
+		putnext(usbwcmp->usbwcm_rq, mp);
+	} else {
+		return;
+	}
+
+	sc->sc_sync = (type == EVT_SYN);
+}
+
+static void
+uwacom_pos_events_graphire(usbwcm_state_t *usbwcmp, int x, int y)
+{
+	uwacom_event(usbwcmp, EVT_ABS, ABS_X, x);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_Y, y);
+}
+
+static void
+uwacom_pen_events_graphire(usbwcm_state_t *usbwcmp, int prs, int stl1, int stl2)
+{
+	uwacom_event(usbwcmp, EVT_ABS, ABS_PRESSURE, prs);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_TIP, prs);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_1, stl1);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_2, stl2);
+}
+
+static void
+uwacom_mouse_events_graphire(usbwcm_state_t *usbwcmp, int left, int middle,
+    int right, int wheel, int distance)
+{
+	uwacom_event(usbwcmp, EVT_BTN, BTN_LEFT, left);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MIDDLE, middle);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_RIGHT, right);
+	uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, wheel);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_DISTANCE, distance);
+}
+
+static void
+uwacom_tool_events_graphire(usbwcm_state_t *usbwcmp, int idx, int proximity)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	uwacom_event(usbwcmp, EVT_BTN, sc->sc_tool[idx], proximity);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_MISC, sc->sc_tool_id[idx]);
+	if (sc->sc_serial[idx]) {
+		uwacom_event(usbwcmp, EVT_MSC, MSC_SERIAL, sc->sc_serial[idx]);
+	}
+
+	uwacom_event(usbwcmp, EVT_SYN, SYN_REPORT, 0);
+}
+
+static void
+uwacom_pad_events_graphire4(usbwcm_state_t *usbwcmp, int b0, int b1, int b4,
+    int b5, int rel, int abs)
+{
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
+	uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, rel);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_WHEEL, abs);
+	uwacom_tool_events_graphire(usbwcmp, 1, b0 | b1 | b4 | b5 | rel | abs);
+}
+
+static void
+usbwcm_input_graphire(usbwcm_state_t *usbwcmp, mblk_t *mp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+	uint8_t *packet = mp->b_rptr;
+
+	if (PACKET_BITS(0, 0, 8) != 0x02) {
+		USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
+		    "unknown report type %02x received\n",
+		    PACKET_BITS(0, 0, 8));
+		return;
+	}
+
+	/* Tool in proximity */
+	if (PACKET_BIT(1, 7)) {
+		uwacom_pos_events_graphire(usbwcmp,
+		    (PACKET_BITS(3, 0, 8) << 8) | PACKET_BITS(2, 0, 8),
+		    (PACKET_BITS(5, 0, 8) << 8) | PACKET_BITS(4, 0, 8));
+
+		if (!PACKET_BIT(1, 6)) {
+			if (!PACKET_BIT(1, 5)) {
+				sc->sc_tool[0] = BTN_TOOL_PEN;
+				sc->sc_tool_id[0] = TOOL_ID_PEN;
+			} else {
+				sc->sc_tool[0] = BTN_TOOL_ERASER;
+				sc->sc_tool_id[0] = TOOL_ID_ERASER;
+			}
+
+			uwacom_pen_events_graphire(usbwcmp,
+			    (PACKET_BIT(7, 0) << 8) | PACKET_BITS(6, 0, 8),
+			    PACKET_BIT(1, 1), PACKET_BIT(1, 2));
+		} else {
+			int wheel, distance;
+
+			if (sc->sc_type->protocol == GRAPHIRE) {
+				wheel = (PACKET_BIT(1, 5) ?
+				    0 : -(int8_t)PACKET_BITS(6, 0, 8));
+				distance = PACKET_BITS(7, 0, 6);
+			} else {
+				wheel = (PACKET_BIT(7, 2) << 2) -
+				    PACKET_BITS(7, 0, 2);
+				distance = PACKET_BITS(6, 0, 6);
+			}
+
+			sc->sc_tool[0] = BTN_TOOL_MOUSE;
+			sc->sc_tool_id[0] = TOOL_ID_MOUSE;
+
+			uwacom_mouse_events_graphire(usbwcmp, PACKET_BIT(1, 0),
+			    PACKET_BIT(1, 2), PACKET_BIT(1, 1), wheel,
+			    distance);
+		}
+
+		uwacom_tool_events_graphire(usbwcmp, 0, 1);
+
+		/* Tool leaving proximity */
+	} else if (sc->sc_tool_id[0]) {
+		uwacom_pos_events_graphire(usbwcmp, 0, 0);
+
+		if (sc->sc_tool[0] == BTN_TOOL_MOUSE)
+			uwacom_mouse_events_graphire(usbwcmp, 0, 0, 0, 0, 0);
+		else
+			uwacom_pen_events_graphire(usbwcmp, 0, 0, 0);
+
+		sc->sc_tool_id[0] = 0;
+		uwacom_tool_events_graphire(usbwcmp, 0, 0);
+	}
+
+	/* Finger on pad: Graphire4 */
+	if ((sc->sc_type->protocol == GRAPHIRE4) && PACKET_BITS(7, 3, 5)) {
+		sc->sc_tool_id[1] = TOOL_ID_PAD;
+		uwacom_pad_events_graphire4(usbwcmp, PACKET_BIT(7, 6), 0,
+		    PACKET_BIT(7, 7), 0,
+		    PACKET_BITS(7, 3, 2) - (PACKET_BIT(7, 5) << 2), 0);
+
+	/* Finger on pad: MyOffice */
+	} else if ((sc->sc_type->protocol == MYOFFICE) &&
+	    (PACKET_BITS(7, 3, 4) || PACKET_BITS(8, 0, 8))) {
+		sc->sc_tool_id[1] = TOOL_ID_PAD;
+		uwacom_pad_events_graphire4(usbwcmp, PACKET_BIT(7, 3),
+		    PACKET_BIT(7, 4), PACKET_BIT(7, 5), PACKET_BIT(7, 6), 0,
+		    PACKET_BITS(8, 0, 7));
+
+	/* Finger leaving pad */
+	} else if (sc->sc_tool_id[1]) {
+		sc->sc_tool_id[1] = 0;
+		uwacom_pad_events_graphire4(usbwcmp, 0, 0, 0, 0, 0, 0);
+	}
+}
+
+static void
+uwacom_pos_events_intuos(usbwcm_state_t *usbwcmp, int x, int y, int distance)
+{
+	uwacom_event(usbwcmp, EVT_ABS, ABS_X, x);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_Y, y);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_DISTANCE, distance);
+}
+
+static void
+uwacom_pen_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+	int press, tilt_x, tilt_y, stl1, stl2;
+
+	switch (sc->sc_type->protocol) {
+	case INTUOS4S:
+	case INTUOS4L:
+		press = PACKET_BITS(7, 6, 10) << 1 | PACKET_BIT(1, 0);
+		break;
+	default:
+		press = PACKET_BITS(7, 6, 10);
+		break;
+	}
+
+	tilt_x = PACKET_BITS(8, 7, 7);
+	tilt_y = PACKET_BITS(8, 0, 7);
+	stl1 = PACKET_BIT(1, 1);
+	stl2 = PACKET_BIT(1, 2);
+
+	uwacom_event(usbwcmp, EVT_ABS, ABS_PRESSURE, press);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_TILT_X, tilt_x);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_TILT_Y, tilt_y);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_TIP, press);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_1, stl1);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_2, stl2);
+}
+
+static void
+uwacom_mouse_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+	int left, middle, right, extra, side, wheel;
+
+	switch (sc->sc_type->protocol) {
+	case INTUOS4S:
+	case INTUOS4L:
+		left = PACKET_BIT(6, 0);
+		middle = PACKET_BIT(6, 1);
+		right = PACKET_BIT(6, 2);
+		side = PACKET_BIT(6, 3);
+		extra = PACKET_BIT(6, 4);
+		wheel = PACKET_BIT(7, 7) - PACKET_BIT(7, 6);
+		break;
+
+	default:
+		left = PACKET_BIT(8, 2);
+		middle = PACKET_BIT(8, 3);
+		right = PACKET_BIT(8, 4);
+		extra = PACKET_BIT(8, 5);
+		side = PACKET_BIT(8, 6);
+		wheel = PACKET_BIT(8, 0) - PACKET_BIT(8, 1);
+		break;
+	}
+
+	uwacom_event(usbwcmp, EVT_BTN, BTN_LEFT, left);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_MIDDLE, middle);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_RIGHT, right);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_EXTRA, extra);
+	uwacom_event(usbwcmp, EVT_BTN, BTN_SIDE, side);
+	uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, wheel);
+}
+
+static void
+uwacom_tool_events_intuos(usbwcm_state_t *usbwcmp, int idx, int proximity)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	uwacom_event(usbwcmp, EVT_BTN, sc->sc_tool[idx], proximity);
+	uwacom_event(usbwcmp, EVT_ABS, ABS_MISC, sc->sc_tool_id[idx]);
+	uwacom_event(usbwcmp, EVT_MSC, MSC_SERIAL, sc->sc_serial[idx]);
+	uwacom_event(usbwcmp, EVT_SYN, SYN_REPORT, 0);
+}
+
+static void
+uwacom_pad_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+	int b0, b1, b2, b3, b4, b5, b6, b7;
+	int rx, ry, prox;
+	int b8, whl, rot;
+
+	switch (sc->sc_type->protocol) {
+	case INTUOS4L:
+		b7 = PACKET_BIT(3, 6);
+		b8 = PACKET_BIT(3, 7);
+
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_7, b7);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_8, b8);
+	/*FALLTHRU*/
+	case INTUOS4S:
+		b0 = PACKET_BIT(2, 0);
+		b1 = PACKET_BIT(3, 0);
+		b2 = PACKET_BIT(3, 1);
+		b3 = PACKET_BIT(3, 2);
+		b4 = PACKET_BIT(3, 3);
+		b5 = PACKET_BIT(3, 4);
+		b6 = PACKET_BIT(3, 5);
+
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_2, b2);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_3, b3);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_6, b6);
+
+		whl = PACKET_BIT(1, 7);
+		if (whl) {
+			rot = PACKET_BITS(1, 0, 7);
+			uwacom_event(usbwcmp, EVT_ABS, ABS_WHEEL, rot);
+		}
+
+		prox = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | whl;
+		uwacom_tool_events_intuos(usbwcmp, 1, prox);
+
+		break;
+
+	default:
+		b0 = PACKET_BIT(5, 0);
+		b1 = PACKET_BIT(5, 1);
+		b2 = PACKET_BIT(5, 2);
+		b3 = PACKET_BIT(5, 3);
+		b4 = PACKET_BIT(6, 0);
+		b5 = PACKET_BIT(6, 1);
+		b6 = PACKET_BIT(6, 2);
+		b7 = PACKET_BIT(6, 3);
+		rx = PACKET_BITS(2, 0, 13);
+		ry = PACKET_BITS(4, 0, 13);
+
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_2, b2);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_3, b3);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_6, b6);
+		uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_7, b7);
+		uwacom_event(usbwcmp, EVT_ABS, ABS_RX, rx);
+		uwacom_event(usbwcmp, EVT_ABS, ABS_RY, ry);
+
+		prox = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | rx | ry;
+		uwacom_tool_events_intuos(usbwcmp, 1, prox);
+
+		break;
+	}
+}
+
+static void
+usbwcm_input_intuos(usbwcm_state_t *usbwcmp, mblk_t *mp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+	uint8_t *packet = mp->b_rptr;
+
+	switch (PACKET_BITS(0, 0, 8)) {
+	case 0x02:
+		switch (PACKET_BITS(1, 5, 2)) {
+		/* Tool entering proximity */
+		case 0x2:
+			sc->sc_tool_id[0] = PACKET_BITS(3, 4, 12);
+			sc->sc_serial[0] =
+			    (PACKET_BIT(1, 1) ? PACKET_BITS(7, 4, 32) : 0);
+
+			switch (sc->sc_tool_id[0]) {
+			case 0x802: /* Intuos4 Grip Pen */
+			case 0x804: /* Intuos4 Art Marker */
+			case 0x823: /* Intuos3 Grip Pen */
+			case 0x885: /* Intuos3 Art Marker */
+				sc->sc_tool[0] = BTN_TOOL_PEN;
+				break;
+			case 0x80a: /* Intuos4 Grip Pen eraser */
+			case 0x82b: /* Intuos3 Grip Pen eraser */
+				sc->sc_tool[0] = BTN_TOOL_ERASER;
+				break;
+			case 0x017: /* Intuos3 2D mouse */
+			case 0x806: /* Intuos4 2D mouse */
+				sc->sc_tool[0] = BTN_TOOL_MOUSE;
+				break;
+			default:
+				USB_DPRINTF_L1(PRINT_MASK_ALL,
+				    usbwcm_log_handle,
+				    "unknown tool ID %03x seen\n",
+				    sc->sc_tool_id[0]);
+				sc->sc_tool[0] = BTN_TOOL_PEN;
+			}
+			break;
+
+		/* Tool leaving proximity */
+		case 0x0:
+			uwacom_pos_events_intuos(usbwcmp, 0, 0, 0);
+
+			if (sc->sc_tool[0] == BTN_TOOL_MOUSE)
+				uwacom_mouse_events_intuos(usbwcmp, packet);
+			else
+				uwacom_pen_events_intuos(usbwcmp, packet);
+
+			sc->sc_tool_id[0] = 0;
+			uwacom_tool_events_intuos(usbwcmp, 0, 0);
+			break;
+
+		/* Tool motion, outbound */
+		case 0x1:
+		/* Outbound tracking is unreliable on the Cintiq */
+			if (sc->sc_type->protocol == CINTIQ)
+			break;
+
+		/* Tool motion */
+		/*FALLTHRU*/
+		case 0x3:
+			uwacom_pos_events_intuos(usbwcmp,
+			    (PACKET_BITS(3, 0, 16) << 1) | PACKET_BIT(9, 1),
+			    (PACKET_BITS(5, 0, 16) << 1) | PACKET_BIT(9, 0),
+			    PACKET_BITS(9, 2, 6));
+
+			if (PACKET_BITS(1, 3, 2) == 0) {
+				uwacom_pen_events_intuos(usbwcmp, packet);
+
+			} else if (PACKET_BITS(1, 1, 4) == 0x5) {
+				int angle = 450 - PACKET_BITS(7, 6, 10);
+
+				if (PACKET_BIT(7, 5)) {
+					angle = (angle > 0 ? 900 : -900) -
+					    angle;
+				}
+
+				uwacom_event(usbwcmp, EVT_ABS, ABS_Z, angle);
+				break;
+			} else if (PACKET_BITS(1, 1, 4) == 0x8) {
+				uwacom_mouse_events_intuos(usbwcmp, packet);
+			} else {
+				USB_DPRINTF_L1(PRINT_MASK_ALL,
+				    usbwcm_log_handle,
+				    "unsupported motion packet type %x "
+				    "received\n", PACKET_BITS(1, 1, 4));
+			}
+
+			uwacom_tool_events_intuos(usbwcmp, 0, 1);
+			break;
+		}
+
+		break;
+
+	case 0x0c:
+		uwacom_pad_events_intuos(usbwcmp, packet);
+		break;
+
+	default:
+		USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
+		    "unknown report type %02x received\n",
+		    PACKET_BITS(0, 0, 8));
+	}
+}
+
+static void
+uwacom_init_abs(usbwcm_state_t *usbwcmp, int axis, int32_t min, int32_t max,
+    int32_t fuzz, int32_t flat)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	sc->sc_abs[axis].min = min;
+	sc->sc_abs[axis].max = max;
+	sc->sc_abs[axis].fuzz = fuzz;
+	sc->sc_abs[axis].flat = flat;
+}
+
+static void
+uwacom_init_graphire4(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[0], EVT_MSC);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_0);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PAD);
+	BM_SET_BIT(sc->sc_bm[4], MSC_SERIAL);
+
+	sc->sc_tool[1] = BTN_TOOL_PAD;
+	sc->sc_serial[1] = SERIAL_PAD_GRAPHIRE4;
+}
+
+static void
+uwacom_init_myoffice(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_1);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
+	BM_SET_BIT(sc->sc_bm[3], ABS_WHEEL);
+
+	uwacom_init_abs(usbwcmp, ABS_WHEEL, 0, 71, 0, 0);
+}
+
+static void
+uwacom_init_intuos(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[0], EVT_MSC);
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_0);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_1);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_2);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_3);
+	BM_SET_BIT(sc->sc_bm[1], BTN_SIDE);
+	BM_SET_BIT(sc->sc_bm[1], BTN_EXTRA);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PAD);
+
+	BM_SET_BIT(sc->sc_bm[3], ABS_TILT_X);
+	BM_SET_BIT(sc->sc_bm[3], ABS_TILT_Y);
+
+	BM_SET_BIT(sc->sc_bm[4], MSC_SERIAL);
+
+	sc->sc_tool[1] = BTN_TOOL_PAD;
+	sc->sc_tool_id[1] = TOOL_ID_PAD;
+	sc->sc_serial[1] = SERIAL_PAD_INTUOS;
+}
+
+static void
+uwacom_init_intuos3(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[3], ABS_Z);
+	BM_SET_BIT(sc->sc_bm[3], ABS_RX);
+
+	uwacom_init_abs(usbwcmp, ABS_Z, -900,  899, 0, 0);
+	uwacom_init_abs(usbwcmp, ABS_RX, 0, 4096, 0, 0);
+}
+
+static void
+uwacom_init_intuos3_large(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_6);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_7);
+
+	BM_SET_BIT(sc->sc_bm[3], ABS_RY);
+
+	uwacom_init_abs(usbwcmp, ABS_RY, 0, 4096, 0, 0);
+}
+
+static void
+uwacom_init_intuos4(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_6);
+
+	BM_SET_BIT(sc->sc_bm[3], ABS_Z);
+
+	uwacom_init_abs(usbwcmp, ABS_Z, -900,  899, 0, 0);
+}
+static void
+uwacom_init_intuos4_large(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_7);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MISC_8);
+}
+
+static int
+uwacom_init(usbwcm_state_t *usbwcmp)
+{
+	struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
+
+	sc->sc_id.bus = ID_BUS_USB;
+	sc->sc_id.vendor = usbwcmp->usbwcm_devid.VendorId;
+	sc->sc_id.product = usbwcmp->usbwcm_devid.ProductId;
+
+	sc->sc_id.version = 0;
+
+	for (int i = 0; i < EVT_USED; ++i)
+		sc->sc_bm[i] = kmem_zalloc(bm_size[i], KM_SLEEP);
+
+	sc->sc_btn = kmem_zalloc(BTN_USED * sizeof (int), KM_SLEEP);
+	sc->sc_abs = kmem_zalloc(ABS_USED * sizeof (struct event_abs_axis),
+	    KM_SLEEP);
+
+	BM_SET_BIT(sc->sc_bm[0], EVT_SYN);
+	BM_SET_BIT(sc->sc_bm[0], EVT_BTN);
+	BM_SET_BIT(sc->sc_bm[0], EVT_REL);
+	BM_SET_BIT(sc->sc_bm[0], EVT_ABS);
+
+	BM_SET_BIT(sc->sc_bm[1], BTN_LEFT);
+	BM_SET_BIT(sc->sc_bm[1], BTN_RIGHT);
+	BM_SET_BIT(sc->sc_bm[1], BTN_MIDDLE);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PEN);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_ERASER);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_MOUSE);
+	BM_SET_BIT(sc->sc_bm[1], BTN_TIP);
+	BM_SET_BIT(sc->sc_bm[1], BTN_STYLUS_1);
+	BM_SET_BIT(sc->sc_bm[1], BTN_STYLUS_2);
+
+	BM_SET_BIT(sc->sc_bm[2], REL_WHEEL);
+
+	BM_SET_BIT(sc->sc_bm[3], ABS_X);
+	BM_SET_BIT(sc->sc_bm[3], ABS_Y);
+	BM_SET_BIT(sc->sc_bm[3], ABS_PRESSURE);
+	BM_SET_BIT(sc->sc_bm[3], ABS_DISTANCE);
+	BM_SET_BIT(sc->sc_bm[3], ABS_MISC);
+
+	uwacom_init_abs(usbwcmp, ABS_X, 0, sc->sc_type->x_max, 4, 0);
+	uwacom_init_abs(usbwcmp, ABS_Y, 0, sc->sc_type->y_max, 4, 0);
+	uwacom_init_abs(usbwcmp, ABS_PRESSURE, 0, sc->sc_type->pressure_max,
+	    0, 0);
+	uwacom_init_abs(usbwcmp, ABS_DISTANCE, 0,
+	    uwacom_protocols[sc->sc_type->protocol].distance_max, 0, 0);
+
+	switch (sc->sc_type->protocol) {
+		case CINTIQ:
+		case INTUOS3L:
+			uwacom_init_intuos3_large(usbwcmp);
+		/*FALLTHRU*/
+		case INTUOS3S:
+			uwacom_init_intuos3(usbwcmp);
+			uwacom_init_intuos(usbwcmp);
+			break;
+
+		case INTUOS4L:
+			uwacom_init_intuos4_large(usbwcmp);
+		/*FALLTHRU*/
+		case INTUOS4S:
+			uwacom_init_intuos4(usbwcmp);
+			uwacom_init_intuos(usbwcmp);
+			break;
+		case MYOFFICE:
+			uwacom_init_myoffice(usbwcmp);
+		/*FALLTHRU*/
+		case GRAPHIRE4:
+			uwacom_init_graphire4(usbwcmp);
+		/*FALLTHRU*/
+		case GRAPHIRE:
+			break;
+	}
+
+	return (0);
+}
+
+/*
+ * usbwcm_match() :
+ *	Match device with it's parameters.
+ */
+static const struct uwacom_type *
+usbwcm_match(uint16_t vid, uint16_t pid)
+{
+	const struct uwacom_type *dev;
+
+	dev = uwacom_devs;
+	while (dev->devno.vid != 0 && dev->devno.pid != 0) {
+		if (dev->devno.vid == vid && dev->devno.pid == pid) {
+			return (dev);
+		}
+		dev++;
+	}
+
+	return (NULL);
+}
+
+/*
+ * usbwcm_probe() :
+ *	Check the device type and protocol.
+ */
+static int
+usbwcm_probe(usbwcm_state_t *usbwcmp)
+{
+	queue_t		*q = usbwcmp->usbwcm_rq;
+	mblk_t		*mctl_ptr;
+	struct iocblk	mctlmsg;
+	hid_req_t	*featr;
+
+	/* check device IDs */
+	mctlmsg.ioc_cmd = HID_GET_VID_PID;
+	mctlmsg.ioc_count = 0;
+
+	mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
+	if (mctl_ptr == NULL) {
+		return (ENOMEM);
+	}
+
+	putnext(usbwcmp->usbwcm_wq, mctl_ptr);
+	usbwcmp->usbwcm_flags |= USBWCM_QWAIT;
+
+	while (usbwcmp->usbwcm_flags & USBWCM_QWAIT) {
+		if (qwait_sig(q) == 0) {
+			usbwcmp->usbwcm_flags = 0;
+			return (EINTR);
+		}
+	}
+
+	usbwcmp->usbwcm_softc.sc_type =
+	    usbwcm_match(usbwcmp->usbwcm_devid.VendorId,
+	    usbwcmp->usbwcm_devid.ProductId);
+	if (!usbwcmp->usbwcm_softc.sc_type) {
+		USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
+		    "unsupported tablet model\n");
+		return (ENXIO);
+	}
+
+	if (uwacom_init(usbwcmp) != 0) {
+		return (ENXIO);
+	}
+
+	/* set feature: tablet mode */
+	featr = kmem_zalloc(sizeof (hid_req_t), KM_SLEEP);
+	featr->hid_req_version_no = HID_VERSION_V_0;
+	featr->hid_req_wValue = REPORT_TYPE_FEATURE | 2;
+	featr->hid_req_wLength = sizeof (uint8_t) * 2;
+	featr->hid_req_data[0] = 2;
+	featr->hid_req_data[1] = 2;
+
+	mctlmsg.ioc_cmd = HID_SET_REPORT;
+	mctlmsg.ioc_count = sizeof (featr);
+	mctl_ptr = usba_mk_mctl(mctlmsg, featr, sizeof (hid_req_t));
+	if (mctl_ptr != NULL) {
+		putnext(usbwcmp->usbwcm_wq, mctl_ptr);
+
+		/*
+		 * Waiting for response of HID_SET_REPORT
+		 * mctl for setting the feature.
+		 */
+		usbwcmp->usbwcm_flags |= USBWCM_QWAIT;
+		while (usbwcmp->usbwcm_flags & USBWCM_QWAIT) {
+			qwait(q);
+		}
+	} else {
+		USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
+		    "enable tablet mode failed\n");
+	}
+
+	kmem_free(featr, sizeof (hid_req_t));
+
+	return (0);
+}
+
+/*
+ * usbwcm_copyreq() :
+ *	helper function for usbwcm ioctls
+ */
+static int
+usbwcm_copyreq(mblk_t *mp, uint_t pvtsize, uint_t state, uint_t reqsize,
+    uint_t contsize, uint_t copytype)
+{
+	usbwcm_copyin_t	*copystat;
+	mblk_t		*iocmp, *contmp;
+	struct copyreq	*cq;
+	struct copyresp	*cr;
+
+	if ((pvtsize == 0) && (state != 0)) {
+		cr = (struct copyresp *)mp->b_rptr;
+		iocmp = cr->cp_private;
+	}
+
+	cq = (struct copyreq *)mp->b_rptr;
+	if (mp->b_cont == NULL) {
+
+		return (EINVAL);
+	}
+
+	cq->cq_addr = *((caddr_t *)mp->b_cont->b_rptr);
+	cq->cq_size = reqsize;
+	cq->cq_flag = 0;
+
+	if (pvtsize) {
+		iocmp = (mblk_t *)allocb(pvtsize, BPRI_MED);
+		if (iocmp == NULL) {
+
+			return (EAGAIN);
+		}
+		cq->cq_private = iocmp;
+		iocmp = cq->cq_private;
+	} else {
+		/*
+		 * Here we need to set cq_private even if there's
+		 * no private data, otherwise its value will be
+		 * TRANSPARENT (-1) on 64bit systems because it
+		 * overlaps iocp->ioc_count. If user address (cq_addr)
+		 * is invalid, it would cause panic later in
+		 * usbwcm_copyin:
+		 * 	freemsg((mblk_t *)copyresp->cp_private);
+		 */
+		cq->cq_private = NULL;
+	}
+
+	if (state) {
+		copystat = (usbwcm_copyin_t *)iocmp->b_rptr;
+		copystat->state = state;
+		if (pvtsize) {  /* M_COPYIN */
+			copystat->addr = cq->cq_addr;
+		} else {
+			cq->cq_addr = copystat->addr;
+			cq->cq_private = iocmp;
+		}
+		iocmp->b_wptr = iocmp->b_rptr + sizeof (usbwcm_copyin_t);
+	}
+
+	if (contsize) {
+		contmp = (mblk_t *)allocb(contsize, BPRI_MED);
+		if (contmp == NULL) {
+
+			return (EAGAIN);
+		}
+		if (mp->b_cont) {
+			freemsg(mp->b_cont);
+			mp->b_cont = contmp;
+		}
+	}
+
+	mp->b_datap->db_type = (unsigned char)copytype;
+	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
+
+	return (0);
+}
+
+static void
+usbwcm_miocack(queue_t *q, mblk_t *mp, int rval)
+{
+	struct iocblk	*iocbp = (struct iocblk *)mp->b_rptr;
+
+	mp->b_datap->db_type = M_IOCACK;
+	mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
+
+	iocbp->ioc_error = 0;
+	iocbp->ioc_count = 0;
+	iocbp->ioc_rval = rval;
+
+	if (mp->b_cont != NULL) {
+		freemsg(mp->b_cont);
+		mp->b_cont = NULL;
+	}
+
+	qreply(q, mp);
+}
+
+/*
+ * usbwcm_iocpy() :
+ * M_IOCDATA processing for IOCTL's
+ */
+static void
+usbwcm_iocpy(queue_t *q, mblk_t *mp)
+{
+	usbwcm_state_t		*usbwcmp = (usbwcm_state_t *)q->q_ptr;
+	struct uwacom_softc	*sc = &usbwcmp->usbwcm_softc;
+	struct copyresp		*copyresp;
+	usbwcm_copyin_t 	*copystat;
+	mblk_t			*datap, *ioctmp;
+	struct iocblk		*iocbp;
+	int			err = 0;
+
+	copyresp = (struct copyresp *)mp->b_rptr;
+	iocbp = (struct iocblk *)mp->b_rptr;
+	if (copyresp->cp_rval) {
+		err = EAGAIN;
+
+		goto out;
+	}
+
+	switch (copyresp->cp_cmd) {
+	default: {
+		int num = copyresp->cp_cmd & 0xff;
+		int len = IOCPARM_MASK & (copyresp->cp_cmd >> 16);
+
+		if (((copyresp->cp_cmd >> 8) & 0xFF) != 'E') {
+			putnext(q, mp); /* pass it down the line */
+			return;
+
+		} else if ((copyresp->cp_cmd & IOC_INOUT) != IOC_OUT) {
+			err = EINVAL;
+			break;
+		}
+
+		switch (num) {
+		case EUWACOMGETVERSION:
+			ioctmp = copyresp->cp_private;
+			copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
+			if (copystat->state == USBWCM_GETSTRUCT) {
+				if (mp->b_cont == NULL) {
+					err = EINVAL;
+
+					break;
+				}
+				datap = (mblk_t *)mp->b_cont;
+
+				*(int *)datap->b_rptr = 0x00010000;
+
+				if (err = usbwcm_copyreq(mp, 0,
+				    USBWCM_GETRESULT, sizeof (int), 0,
+				    M_COPYOUT)) {
+
+					goto out;
+				}
+			} else if (copystat->state == USBWCM_GETRESULT) {
+				freemsg(ioctmp);
+				usbwcm_miocack(q, mp, 0);
+				return;
+			}
+			break;
+
+		case EUWACOMGETID:
+			ioctmp = copyresp->cp_private;
+			copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
+			if (copystat->state == USBWCM_GETSTRUCT) {
+				if (mp->b_cont == NULL) {
+					err = EINVAL;
+
+					break;
+				}
+				datap = (mblk_t *)mp->b_cont;
+
+				bcopy(&sc->sc_id, datap->b_rptr,
+				    sizeof (struct event_dev_id));
+
+				if (err = usbwcm_copyreq(mp, 0,
+				    USBWCM_GETRESULT,
+				    sizeof (struct event_dev_id), 0,
+				    M_COPYOUT)) {
+
+					goto out;
+				}
+			} else if (copystat->state == USBWCM_GETRESULT) {
+				freemsg(ioctmp);
+				usbwcm_miocack(q, mp, 0);
+				return;
+			}
+			break;
+
+		default:
+			if (num >= EUWACOMGETBM &&
+			    num < EUWACOMGETBM + EVT_USED) {
+				int idx = num - EUWACOMGETBM;
+				size_t length = min(bm_size[idx], len);
+
+				ioctmp = copyresp->cp_private;
+				copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
+				if (copystat->state == USBWCM_GETSTRUCT) {
+					if (mp->b_cont == NULL) {
+						err = EINVAL;
+
+						break;
+					}
+					datap = (mblk_t *)mp->b_cont;
+
+					bcopy(sc->sc_bm[idx], datap->b_rptr,
+					    length);
+
+					if (err = usbwcm_copyreq(mp, 0,
+					    USBWCM_GETRESULT, length, 0,
+					    M_COPYOUT)) {
+
+						goto out;
+					}
+
+				} else if (copystat->state ==
+				    USBWCM_GETRESULT) {
+					freemsg(ioctmp);
+					usbwcm_miocack(q, mp, length);
+					return;
+				}
+				break;
+
+			} else if (num >= EUWACOMGETABS &&
+			    num < EUWACOMGETABS + ABS_USED) {
+				int idx = num - EUWACOMGETABS;
+
+				ioctmp = copyresp->cp_private;
+				copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
+				if (copystat->state == USBWCM_GETSTRUCT) {
+					if (mp->b_cont == NULL) {
+						err = EINVAL;
+
+						break;
+					}
+					datap = (mblk_t *)mp->b_cont;
+
+					bcopy(&sc->sc_abs[idx], datap->b_rptr,
+					    sizeof (struct event_abs_axis));
+
+					if (err = usbwcm_copyreq(mp, 0,
+					    USBWCM_GETRESULT,
+					    sizeof (struct event_abs_axis), 0,
+					    M_COPYOUT)) {
+
+						goto out;
+					}
+
+				} else if (copystat->state ==
+				    USBWCM_GETRESULT) {
+					freemsg(ioctmp);
+					usbwcm_miocack(q, mp, 0);
+					return;
+				}
+				break;
+
+			} else {
+				err = EINVAL;
+				break;
+			}
+		}
+	}
+	}
+
+out:
+	if (err) {
+		mp->b_datap->db_type = M_IOCNAK;
+		if (mp->b_cont) {
+			freemsg(mp->b_cont);
+			mp->b_cont = (mblk_t *)NULL;
+		}
+		if (copyresp->cp_private) {
+			freemsg((mblk_t *)copyresp->cp_private);
+			copyresp->cp_private = (mblk_t *)NULL;
+		}
+		iocbp->ioc_count = 0;
+		iocbp->ioc_error = err;
+	}
+
+	qreply(q, mp);
+}
+
+/*
+ * usbwcm_ioctl() :
+ *	Process ioctls we recognize and own.  Otherwise, NAK.
+ */
+static void
+usbwcm_ioctl(queue_t *q, mblk_t *mp)
+{
+	usbwcm_state_t		*usbwcmp = (usbwcm_state_t *)q->q_ptr;
+	struct uwacom_softc	*sc;
+	mblk_t			*datap;
+	struct iocblk		*iocp;
+	int			err = 0;
+
+	if (usbwcmp == NULL) {
+		miocnak(q, mp, 0, EINVAL);
+		return;
+	}
+
+	sc = &usbwcmp->usbwcm_softc;
+	iocp = (struct iocblk *)mp->b_rptr;
+
+	switch (iocp->ioc_cmd) {
+	default: {
+		int num = iocp->ioc_cmd & 0xff;
+		int len = IOCPARM_MASK & (iocp->ioc_cmd >> 16);
+
+		if (((iocp->ioc_cmd >> 8) & 0xFF) != 'E') {
+			putnext(q, mp); /* pass it down the line */
+			return;
+
+		} else if ((iocp->ioc_cmd & IOC_INOUT) != IOC_OUT) {
+			err = EINVAL;
+			break;
+		}
+
+		switch (num) {
+		case EUWACOMGETVERSION:
+			if (iocp->ioc_count == TRANSPARENT) {
+				if (err = usbwcm_copyreq(mp,
+				    sizeof (usbwcm_copyin_t), USBWCM_GETSTRUCT,
+				    sizeof (int), 0, M_COPYIN)) {
+					break;
+				}
+				freemsg(mp->b_cont);
+				mp->b_cont = (mblk_t *)NULL;
+
+				qreply(q, mp);
+				return;
+			}
+
+			if (mp->b_cont == NULL ||
+			    iocp->ioc_count != sizeof (int)) {
+				err = EINVAL;
+				break;
+			}
+			datap = mp->b_cont;
+
+			*(int *)datap->b_rptr = 0x00010000;
+
+			break;
+
+		case EUWACOMGETID:
+			if (iocp->ioc_count == TRANSPARENT) {
+				if (err = usbwcm_copyreq(mp,
+				    sizeof (usbwcm_copyin_t), USBWCM_GETSTRUCT,
+				    sizeof (struct event_dev_id), 0,
+				    M_COPYIN)) {
+					break;
+				}
+				freemsg(mp->b_cont);
+				mp->b_cont = (mblk_t *)NULL;
+
+				qreply(q, mp);
+				return;
+			}
+
+			if (mp->b_cont == NULL ||
+			    iocp->ioc_count != sizeof (struct event_dev_id)) {
+				err = EINVAL;
+				break;
+			}
+			datap = mp->b_cont;
+
+			bcopy(&sc->sc_id, datap->b_rptr,
+			    sizeof (struct event_dev_id));
+
+			break;
+
+		default:
+			if (num >= EUWACOMGETBM &&
+			    num < EUWACOMGETBM + EVT_USED) {
+				int idx = num - EUWACOMGETBM;
+				size_t length = min(bm_size[idx], len);
+
+				if (iocp->ioc_count == TRANSPARENT) {
+					if (err = usbwcm_copyreq(mp,
+					    sizeof (usbwcm_copyin_t),
+					    USBWCM_GETSTRUCT, length, 0,
+					    M_COPYIN)) {
+						break;
+					}
+					freemsg(mp->b_cont);
+					mp->b_cont = (mblk_t *)NULL;
+
+					qreply(q, mp);
+					return;
+				}
+
+				if (mp->b_cont == NULL ||
+				    iocp->ioc_count != length) {
+					err = EINVAL;
+					break;
+				}
+				datap = mp->b_cont;
+
+				bcopy(sc->sc_bm[idx], datap->b_rptr, length);
+
+				break;
+
+			} else if (num >= EUWACOMGETABS &&
+			    num < EUWACOMGETABS + ABS_USED) {
+				int idx = num - EUWACOMGETABS;
+
+				if (iocp->ioc_count == TRANSPARENT) {
+					if (err = usbwcm_copyreq(mp,
+					    sizeof (usbwcm_copyin_t),
+					    USBWCM_GETSTRUCT,
+					    sizeof (struct event_abs_axis), 0,
+					    M_COPYIN)) {
+						break;
+					}
+					freemsg(mp->b_cont);
+					mp->b_cont = (mblk_t *)NULL;
+
+					qreply(q, mp);
+					return;
+				}
+
+				if (mp->b_cont == NULL ||
+				    iocp->ioc_count !=
+				    sizeof (struct event_abs_axis)) {
+					err = EINVAL;
+					break;
+				}
+				datap = mp->b_cont;
+
+				bcopy(&sc->sc_abs[idx], datap->b_rptr,
+				    sizeof (struct event_abs_axis));
+
+				break;
+
+			} else {
+				err = EINVAL;
+				break;
+			}
+		}
+	}
+	}
+
+	if (err != 0)
+		miocnak(q, mp, 0, err);
+	else {
+		iocp->ioc_rval = 0;
+		iocp->ioc_error = 0;
+		mp->b_datap->db_type = M_IOCACK;
+		qreply(q, mp);
+		/* REMOVE */
+	}
+
+	return;
+
+}
+
+/*
+ * usbwcm_input() :
+ *
+ *	Wacom input routine; process data received from a device and
+ *	assemble into a input event for the window system.
+ *
+ *	Watch out for overflow!
+ */
+static void
+usbwcm_input(usbwcm_state_t *usbwcmp, mblk_t *mp)
+{
+	struct uwacom_softc	*sc = &usbwcmp->usbwcm_softc;
+
+	switch (sc->sc_type->protocol) {
+	case GRAPHIRE:
+	case GRAPHIRE4:
+	case MYOFFICE:
+		usbwcm_input_graphire(usbwcmp, mp);
+		break;
+
+	case INTUOS3S:
+	case INTUOS3L:
+	case INTUOS4S:
+	case INTUOS4L:
+	case CINTIQ:
+		usbwcm_input_intuos(usbwcmp, mp);
+		break;
+	}
+}
+
+/*
+ * usbwcm_flush() :
+ *	Resets the soft state to default values
+ *	and sends M_FLUSH above.
+ */
+static void
+usbwcm_flush(usbwcm_state_t *usbwcmp)
+{
+	queue_t			*q;
+
+	if ((q = usbwcmp->usbwcm_rq) != NULL && q->q_next != NULL) {
+		(void) putnextctl1(q, M_FLUSH, FLUSHR);
+	}
+}
+
+/*
+ * usbwcm_mctl() :
+ *	Handle M_CTL messages from hid.  If
+ *	we don't understand the command, free message.
+ */
+static void
+usbwcm_mctl(queue_t *q, mblk_t *mp)
+{
+	usbwcm_state_t	*usbwcmp = (usbwcm_state_t *)q->q_ptr;
+	struct iocblk	*iocp;
+	caddr_t		data = NULL;
+	struct iocblk	mctlmsg;
+	mblk_t		*mctl_ptr;
+	hid_req_t	*featr;
+
+	iocp = (struct iocblk *)mp->b_rptr;
+	if (mp->b_cont != NULL)
+		data = (caddr_t)mp->b_cont->b_rptr;
+
+	switch (iocp->ioc_cmd) {
+	case HID_GET_VID_PID:
+		if ((data != NULL) &&
+		    (iocp->ioc_count == sizeof (hid_vid_pid_t)) &&
+		    (MBLKL(mp->b_cont) == iocp->ioc_count)) {
+			bcopy(data, &usbwcmp->usbwcm_devid, iocp->ioc_count);
+		}
+
+		freemsg(mp);
+		usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
+		break;
+
+	case HID_CONNECT_EVENT:
+		/* set feature: tablet mode */
+		featr = kmem_zalloc(sizeof (hid_req_t), KM_SLEEP);
+		featr->hid_req_version_no = HID_VERSION_V_0;
+		featr->hid_req_wValue = REPORT_TYPE_FEATURE | 2;
+		featr->hid_req_wLength = sizeof (uint8_t) * 2;
+		featr->hid_req_data[0] = 2;
+		featr->hid_req_data[1] = 2;
+
+		mctlmsg.ioc_cmd = HID_SET_REPORT;
+		mctlmsg.ioc_count = sizeof (featr);
+		mctl_ptr = usba_mk_mctl(mctlmsg, featr, sizeof (hid_req_t));
+		if (mctl_ptr != NULL) {
+			putnext(usbwcmp->usbwcm_wq, mctl_ptr);
+		} else {
+		USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
+		    "enable tablet mode failed\n");
+		}
+
+		kmem_free(featr, sizeof (hid_req_t));
+		freemsg(mp);
+		break;
+
+	case HID_SET_REPORT:
+		/* FALLTHRU */
+
+	case HID_SET_PROTOCOL:
+		usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
+		/* FALLTHRU */
+
+	default:
+		freemsg(mp);
+	}
+}
+
+/*
+ * usbwcm_open() :
+ *	open() entry point for the USB wacom module.
+ */
+/*ARGSUSED*/
+static int
+usbwcm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
+{
+	usbwcm_state_t	*usbwcmp;
+
+	/* Clone opens are not allowed */
+	if (sflag != MODOPEN)
+		return (EINVAL);
+
+	/* If the module is already open, just return */
+	if (q->q_ptr) {
+		return (0);
+	}
+
+	/* allocate usbwcm state structure */
+	usbwcmp = kmem_zalloc(sizeof (usbwcm_state_t), KM_SLEEP);
+
+	q->q_ptr = usbwcmp;
+	WR(q)->q_ptr = usbwcmp;
+
+	usbwcmp->usbwcm_rq = q;
+	usbwcmp->usbwcm_wq = WR(q);
+
+	qprocson(q);
+
+	if (usbwcm_probe(usbwcmp) != 0) {
+
+		qprocsoff(q);
+		kmem_free(usbwcmp, sizeof (usbwcm_state_t));
+
+		return (EINVAL);
+	}
+
+	usbwcm_flush(usbwcmp);
+
+	usbwcmp->usbwcm_flags |= USBWCM_OPEN;
+	return (0);
+}
+
+
+/*
+ * usbwcm_close() :
+ *	close() entry point for the USB wacom module.
+ */
+/*ARGSUSED*/
+static int
+usbwcm_close(queue_t *q, int flag, cred_t *credp)
+{
+	usbwcm_state_t		*usbwcmp = q->q_ptr;
+	struct uwacom_softc	*sc = &usbwcmp->usbwcm_softc;
+
+	qprocsoff(q);
+
+	if (usbwcmp->usbwcm_bufcall) {
+		qunbufcall(q, (bufcall_id_t)(long)usbwcmp->usbwcm_bufcall);
+		usbwcmp->usbwcm_bufcall = 0;
+	}
+
+	if (usbwcmp->usbwcm_mioctl != NULL) {
+		/*
+		 * We were holding an "ioctl" response pending the
+		 * availability of an "mblk" to hold data to be passed up;
+		 * another "ioctl" came through, which means that "ioctl"
+		 * must have timed out or been aborted.
+		 */
+		freemsg(usbwcmp->usbwcm_mioctl);
+		usbwcmp->usbwcm_mioctl = NULL;
+	}
+
+	for (int i = 0; i < EVT_USED; i++)
+		kmem_free(sc->sc_bm[i], bm_size[i]);
+
+	kmem_free(sc->sc_btn, BTN_USED * sizeof (int));
+	kmem_free(sc->sc_abs, ABS_USED * sizeof (struct event_abs_axis));
+	kmem_free(usbwcmp, sizeof (usbwcm_state_t));
+
+	q->q_ptr = WR(q)->q_ptr = NULL;
+	return (0);
+}
+
+/*
+ * usbwcm_wput() :
+ *	wput() routine for the wacom module.
+ *	Module below : hid, module above : consms
+ */
+static int
+usbwcm_wput(queue_t *q, mblk_t *mp)
+{
+	switch (mp->b_datap->db_type) {
+
+	case M_FLUSH:  /* Canonical flush handling */
+		if (*mp->b_rptr & FLUSHW) {
+			flushq(q, FLUSHDATA);
+		}
+		if (*mp->b_rptr & FLUSHR) {
+			flushq(RD(q), FLUSHDATA);
+		}
+		putnext(q, mp); /* pass it down the line. */
+		break;
+
+	case M_IOCTL:
+		usbwcm_ioctl(q, mp);
+		break;
+
+	case M_IOCDATA:
+		usbwcm_iocpy(q, mp);
+		break;
+
+	default:
+		putnext(q, mp); /* pass it down the line. */
+	}
+
+	return (0);
+}
+
+/*
+ * usbwcm_rput() :
+ *	Put procedure for input from driver end of stream (read queue).
+ */
+static void
+usbwcm_rput(queue_t *q, mblk_t *mp)
+{
+	usbwcm_state_t		*usbwcmp = q->q_ptr;
+	struct uwacom_softc	*sc = &usbwcmp->usbwcm_softc;
+	mblk_t			*mp0 = mp;
+	int			limit;
+
+	if (usbwcmp == 0) {
+		freemsg(mp);	/* nobody's listening */
+		return;
+	}
+
+	switch (mp->b_datap->db_type) {
+	case M_FLUSH:
+		if (*mp->b_rptr & FLUSHW)
+			flushq(WR(q), FLUSHDATA);
+
+		if (*mp->b_rptr & FLUSHR)
+			flushq(q, FLUSHDATA);
+
+		freemsg(mp);
+		return;
+
+	case M_BREAK:
+		/*
+		 * We don't have to handle this
+		 * because nothing is sent from the downstream
+		 */
+		freemsg(mp);
+		return;
+
+	case M_DATA:
+		if (!(usbwcmp->usbwcm_flags & USBWCM_OPEN)) {
+			freemsg(mp);	/* not ready to listen */
+
+			return;
+		}
+
+		/*
+		 * Make sure there are at least "limit" number of bytes.
+		 */
+		limit = uwacom_protocols[sc->sc_type->protocol].packet_size;
+		if (MBLKL(mp0) == limit) {	/* REMOVE */
+			do {
+				/* REMOVE */
+				usbwcm_input(usbwcmp, mp0);
+				mp0 = mp0->b_cont;
+			} while (mp0 != NULL);   /* next block, if any */
+		}
+
+		freemsg(mp);
+		break;
+
+	case M_CTL:
+		usbwcm_mctl(q, mp);
+		return;
+
+	case M_ERROR:
+		/* REMOVE */
+		usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
+
+		freemsg(mp);
+		return;
+	default:
+		putnext(q, mp);
+		return;
+	}
+}
+
+
+static struct module_info modinfo;
+
+/* STREAMS entry points */
+
+/* read side queue */
+static struct qinit rinit = {
+	(int (*)())usbwcm_rput,	/* put procedure not needed */
+	NULL, 			/* service procedure */
+	usbwcm_open,		/* called on startup */
+	usbwcm_close,		/* called on finish */
+	NULL,			/* for future use */
+	&modinfo,		/* module information structure */
+	NULL			/* module statistics structure */
+};
+
+/* write side queue */
+static struct qinit winit = {
+	usbwcm_wput,		/* put procedure */
+	NULL,			/* no service proecedure needed */
+	NULL,			/* open not used on write side */
+	NULL,			/* close not used on write side */
+	NULL,			/* for future use */
+	&modinfo,		/* module information structure */
+	NULL			/* module statistics structure */
+};
+
+/* STREAMS table */
+static struct streamtab strtab = {
+	&rinit,
+	&winit,
+	NULL,			/* not a MUX */
+	NULL			/* not a MUX */
+};
+
+/* Module linkage information */
+
+static struct fmodsw modsw = {
+	"usbwcm",
+	&strtab,
+	D_MP | D_MTPERMOD
+};
+
+
+static struct modlstrmod modlstr = {
+	&mod_strmodops,
+	"USB Wacom STRMOD",
+	&modsw
+};
+
+static struct modlinkage modlink = {
+	MODREV_1,
+	(void *)&modlstr,
+	NULL
+};
+
+static struct module_info modinfo = {
+	0x0ffff,		/* module id number */
+	"usbwcm",		/* module name */
+	0,			/* min packet size accepted */
+	INFPSZ,			/* max packet size accepted */
+	512,			/* hi-water mark */
+	128			/* lo-water mark */
+};
+
+
+/* Module entry points */
+
+int
+_init(void)
+{
+	int rval = mod_install(&modlink);
+
+	if (rval == 0) {
+		usbwcm_log_handle = usb_alloc_log_hdl(NULL, "usbwcm",
+		    &usbwcm_errlevel, &usbwcm_errmask, NULL, 0);
+	}
+
+	return (rval);
+}
+
+int
+_fini(void)
+{
+	int rval = mod_remove(&modlink);
+
+	if (rval == 0) {
+		usb_free_log_hdl(usbwcm_log_handle);
+	}
+
+	return (rval);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+
+	return (mod_info(&modlink, modinfop));
+}
--- a/usr/src/uts/common/sys/Makefile	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/common/sys/Makefile	Thu Jan 14 17:07:01 2010 +0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -1008,6 +1008,9 @@
 USBVIDHDRS=           \
 	usbvc.h
 
+USBWCMHDRS=		\
+	usbwcm.h
+
 UGENHDRS=           \
 	usb_ugen.h
 
@@ -1159,6 +1162,7 @@
 	$(USBPRNHDRS:%.h=usb/clients/printer/%.check)   \
 	$(USBCDCHDRS:%.h=usb/clients/usbcdc/%.check)	\
 	$(USBVIDHDRS:%.h=usb/clients/video/usbvc/%.check)   \
+	$(USBWCMHDRS:%.h=usb/clients/usbinput/usbwcm/%.check)	\
 	$(UGENHDRS:%.h=usb/clients/ugen/%.check)   \
 	$(USBHDRS:%.h=usb/%.check)                      \
 	$(UWBHDRS:%.h=uwb/%.check)                      \
@@ -1222,6 +1226,7 @@
 	$(ROOTUSBPRNHDRS)       \
 	$(ROOTUSBCDCHDRS)       \
 	$(ROOTUSBVIDHDRS)       \
+	$(ROOTUSBWCMHDRS)	\
 	$(ROOTUGENHDRS)		\
 	$(ROOT1394HDRS)         \
 	$(ROOTHOTPLUGHDRS)	\
@@ -1284,6 +1289,7 @@
 	$(ROOTUSBPRNHDRS)       \
 	$(ROOTUSBCDCHDRS)       \
 	$(ROOTUSBVIDHDRS)       \
+	$(ROOTUSBWCMHDRS)	\
 	$(ROOTUGENHDRS)		\
 	$(ROOT1394HDRS)         \
 	$(ROOTHOTPLUGHDRS)	\
--- a/usr/src/uts/common/sys/Makefile.syshdrs	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/common/sys/Makefile.syshdrs	Thu Jan 14 17:07:01 2010 +0800
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -131,9 +131,6 @@
 usb/clients/mass_storage/%.check:	usb/clients/mass_storage/%.h
 	$(DOT_H_CHECK)
 
-usb/clients/hid/%.check:	usb/clients/hid/%.h
-	$(DOT_H_CHECK)
-
 usb/clients/printer/%.check:  usb/clients/printer/%.h
 	$(DOT_H_CHECK)
 
@@ -143,6 +140,9 @@
 usb/clients/video/usbvc/%.check:  usb/clients/video/usbvc/%.h
 	$(DOT_H_CHECK)
 
+usb/clients/usbinput/usbwcm/%.check:	usb/clients/usbinput/usbwcm/%.h
+	$(DOT_H_CHECK)
+
 1394/%.check:         1394/%.h
 	$(DOT_H_CHECK)
 
@@ -210,6 +210,7 @@
 	$(ROOTDIR)/usb/clients/printer  \
 	$(ROOTDIR)/usb/clients/usbcdc  \
 	$(ROOTDIR)/usb/clients/video/usbvc  \
+	$(ROOTDIR)/usb/clients/usbinput/usbwcm \
 	$(ROOTDIR)/usb/clients/ugen  \
 	$(ROOTDIR)/uwb \
 	$(ROOTDIR)/uwb/uwba \
@@ -291,6 +292,7 @@
 ROOTUSBPRNHDRS= $(USBPRNHDRS:%=$(ROOTDIR)/usb/clients/printer/%)
 ROOTUSBCDCHDRS= $(USBCDCHDRS:%=$(ROOTDIR)/usb/clients/usbcdc/%)
 ROOTUSBVIDHDRS= $(USBVIDHDRS:%=$(ROOTDIR)/usb/clients/video/usbvc/%)
+ROOTUSBWCMHDRS= $(USBWCMHDRS:%=$(ROOTDIR)/usb/clients/usbinput/usbwcm/%)
 ROOTUGENHDRS= $(UGENHDRS:%=$(ROOTDIR)/usb/clients/ugen/%)
 
 ROOT1394HDRS= $(I1394HDRS:%=$(ROOTDIR)/1394/%)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/usb/clients/usbinput/usbwcm/usbwcm.h	Thu Jan 14 17:07:01 2010 +0800
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2007, 2008 Bartosz Fabianowski <freebsd@chillt.de>
+ * All rights reserved.
+ *
+ * Financed by the "Irish Research Council for Science, Engineering and
+ * Technology: funded by the National Development Plan"
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _SYS_USB_USBWCM_H
+#define	_SYS_USB_USBWCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/ioccom.h>
+#if defined(_LP64) || defined(_I32LPx)
+#include <sys/types32.h>
+#else
+#include <sys/types.h>
+#endif
+#include <sys/time.h>
+
+#define	EVTIOCGVERSION	_IOR('E', 0x1, int)
+#define	EVTIOCGDEVID	_IOR('E', 0x2, struct event_dev_id)
+#define	EVTIOCGBM(i, s)	_IORN('E', 0x20 + (i), (s))
+#define	EVTIOCGABS(i)	_IOR('E', 0x40 + (i), struct event_abs_axis)
+#define	EVTIOC		('E' << 8)
+
+struct event_dev_id {
+	uint16_t bus;
+#define	ID_BUS_USB 3
+	uint16_t vendor;
+	uint16_t product;
+	uint16_t version;
+};
+
+struct event_abs_axis {
+	int32_t value;
+	int32_t min;
+	int32_t max;
+	int32_t fuzz;
+	int32_t flat;
+};
+
+struct event_input {
+#if defined(_LP64) || defined(_I32LPx)
+	struct timeval32 time;
+#else
+	struct timeval time;
+#endif
+	uint16_t type;
+	uint16_t code;
+	int32_t value;
+};
+
+#define	EVT_SYN				0x0000
+#define	EVT_BTN				0x0001
+#define	EVT_REL				0x0002
+#define	EVT_ABS				0x0003
+#define	EVT_MSC				0x0004
+#define	EVT_USED			0x0005
+#define	EVT_MAX				0x001f
+
+#define	SYN_REPORT			0x0000
+
+#define	BTN_MISC_0			0x0100
+#define	BTN_MISC_1			0x0101
+#define	BTN_MISC_2			0x0102
+#define	BTN_MISC_3			0x0103
+#define	BTN_MISC_4			0x0104
+#define	BTN_MISC_5			0x0105
+#define	BTN_MISC_6			0x0106
+#define	BTN_MISC_7			0x0107
+#define	BTN_MISC_8			0x0108
+
+#define	BTN_LEFT			0x0110
+#define	BTN_RIGHT			0x0111
+#define	BTN_MIDDLE			0x0112
+#define	BTN_SIDE			0x0113
+#define	BTN_EXTRA			0x0114
+#define	BTN_TOOL_PEN			0x0140
+#define	BTN_TOOL_ERASER			0x0141
+#define	BTN_TOOL_PAD			0x0145
+#define	BTN_TOOL_MOUSE			0x0146
+#define	BTN_TIP				0x014a
+#define	BTN_STYLUS_1			0x014b
+#define	BTN_STYLUS_2			0x014c
+#define	BTN_USED			0x014d
+#define	BTN_MISC_UND			0x01ff
+#define	BTN_MAX				0x01ff
+
+#define	REL_WHEEL			0x0008
+#define	REL_MAX				0x000f
+
+#define	ABS_X				0x0000
+#define	ABS_Y				0x0001
+#define	ABS_Z				0x0002
+#define	ABS_RX				0x0003
+#define	ABS_RY				0x0004
+#define	ABS_RZ				0x0005
+
+#define	ABS_WHEEL			0x0008
+#define	ABS_PRESSURE			0x0018
+#define	ABS_DISTANCE			0x0019
+#define	ABS_TILT_X			0x001a
+#define	ABS_TILT_Y			0x001b
+#define	ABS_MISC			0x0028
+#define	ABS_USED			0x0029
+#define	ABS_MAX				0x003f
+
+#define	MSC_SERIAL			0x0000
+#define	MSC_MAX				0x0007
+
+#ifdef _KERNEL
+/* USB IDs */
+#define	USB_VENDOR_WACOM			0x056a
+
+#define	USB_PRODUCT_WACOM_GRAPHIRE		0x0010
+#define	USB_PRODUCT_WACOM_GRAPHIRE2_4X5		0x0011
+#define	USB_PRODUCT_WACOM_GRAPHIRE2_5X7		0x0012
+#define	USB_PRODUCT_WACOM_GRAPHIRE3_4X5		0x0013
+#define	USB_PRODUCT_WACOM_GRAPHIRE3_6X8		0x0014
+#define	USB_PRODUCT_WACOM_GRAPHIRE4_4X5		0x0015
+#define	USB_PRODUCT_WACOM_GRAPHIRE4_6X8		0x0016
+#define	USB_PRODUCT_WACOM_BAMBOO_FUN_4X5	0x0017
+#define	USB_PRODUCT_WACOM_BAMBOO_FUN_6X8	0x0018
+#define	USB_PRODUCT_WACOM_BAMBOO_ONE_6X8	0x0019
+#define	USB_PRODUCT_WACOM_CINTIQ_21UX		0x003f
+#define	USB_PRODUCT_WACOM_VOLITO		0x0060
+#define	USB_PRODUCT_WACOM_PENSTATION2		0x0061
+#define	USB_PRODUCT_WACOM_VOLITO2_4X5		0x0062
+#define	USB_PRODUCT_WACOM_VOLITO2_2X3		0x0063
+#define	USB_PRODUCT_WACOM_PENPARTNER2		0x0064
+#define	USB_PRODUCT_WACOM_BAMBOO		0x0065
+#define	USB_PRODUCT_WACOM_BAMBOO_ONE_4X5	0x0069
+#define	USB_PRODUCT_WACOM_INTUOS3_4X5		0x00b0
+#define	USB_PRODUCT_WACOM_INTUOS3_6X8		0x00b1
+#define	USB_PRODUCT_WACOM_INTUOS3_9X12		0x00b2
+#define	USB_PRODUCT_WACOM_INTUOS3_12X12		0x00b3
+#define	USB_PRODUCT_WACOM_INTUOS3_12X19		0x00b4
+#define	USB_PRODUCT_WACOM_INTUOS3_6X11		0x00b5
+#define	USB_PRODUCT_WACOM_INTUOS3_4X6		0x00b7
+
+#define	USB_PRODUCT_WACOM_INTUOS4_4X6		0x00b8
+#define	USB_PRODUCT_WACOM_INTUOS4_6X9		0x00b9
+#define	USB_PRODUCT_WACOM_INTUOS4_8X13		0x00ba
+#define	USB_PRODUCT_WACOM_INTUOS4_12X19		0x00bb
+
+#define	TOOL_ID_PEN	0x0002
+#define	TOOL_ID_MOUSE	0x0006
+#define	TOOL_ID_ERASER	0x000a
+#define	TOOL_ID_PAD	0x000f
+
+#define	SERIAL_PAD_INTUOS	0xffffffff
+#define	SERIAL_PAD_GRAPHIRE4	0x000000f0
+
+#define	EUWACOMGETVERSION		0x01
+#define	EUWACOMGETID			0x02
+#define	EUWACOMGETBM			0x20
+#define	EUWACOMGETABS			0x40
+
+/* Protocols */
+struct uwacom_protocol_type {
+	int packet_size;
+	int distance_max;
+};
+
+enum uwacom_protocol {
+	/* Graphire family */
+	GRAPHIRE = 0,
+	GRAPHIRE4,
+	MYOFFICE,
+
+	/* Intuos family */
+	INTUOS3S,
+	INTUOS3L,
+	INTUOS4S,
+	INTUOS4L,
+	CINTIQ
+};
+
+struct uwacom_id {
+	uint16_t	vid;
+	uint16_t	pid;
+};
+
+/* Models */
+struct uwacom_type {
+	struct uwacom_id	devno;
+	enum uwacom_protocol	protocol;
+	int			x_max;
+	int			y_max;
+	int			pressure_max;
+};
+
+static const struct uwacom_protocol_type uwacom_protocols[] = {
+	{ 8, 63},
+	{ 8, 63},
+	{ 9, 63},
+	{10, 63},
+	{10, 63},
+	{10, 63},
+	{10, 63},
+	{10, 63}
+};
+
+struct uwacom_softc {
+	const struct uwacom_type	*sc_type;
+	struct event_dev_id		sc_id;
+	unsigned long			*sc_bm[EVT_USED];
+
+	int				*sc_btn;
+	struct event_abs_axis		*sc_abs;
+	int				sc_tool[2];
+	int				sc_tool_id[2];
+	unsigned int			sc_serial[2];
+	int				sc_sync;
+};
+
+typedef struct usbwcm_state {
+	queue_t		*usbwcm_rq;	/* pointer to read queue */
+	queue_t		*usbwcm_wq;	/* pointer to write queue */
+
+	int32_t		usbwcm_flags;	/* open/qwait status */
+#define	USBWCM_OPEN    0x00000001	/* opened for business */
+#define	USBWCM_QWAIT   0x00000002	/* waiting for a response */
+
+	/* software state */
+	struct uwacom_softc	usbwcm_softc;
+
+	/* device model data */
+	hid_vid_pid_t	usbwcm_devid;
+
+	/*
+	 * Is an ioctl fails because an mblk wasn't
+	 * available, the mlbk is saved here.
+	 */
+	mblk_t		*usbwcm_mioctl;
+	bufcall_id_t	usbwcm_bufcall;	/* id returned by bufcall() */
+} usbwcm_state_t;
+
+#define	abs(x)		((x) < 0 ? -(x) : (x))
+
+typedef struct usbwcm_copyin_s {
+	caddr_t	addr;
+	int	state;
+#define	USBWCM_GETSTRUCT 1
+#define	USBWCM_GETRESULT 2
+} usbwcm_copyin_t;
+
+static const struct uwacom_type uwacom_devs[] = {
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE},
+		GRAPHIRE, 10206, 7422, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE2_4X5},
+		GRAPHIRE, 10206, 7422, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE2_5X7},
+		GRAPHIRE, 13918, 10206, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE3_4X5},
+		GRAPHIRE, 10208, 7424, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE3_6X8},
+		GRAPHIRE, 16704, 12064, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE4_4X5},
+		GRAPHIRE4, 10208, 7424, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE4_6X8},
+		GRAPHIRE4, 16704, 12064, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_BAMBOO_FUN_4X5},
+		MYOFFICE, 14760, 9225, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_BAMBOO_FUN_6X8},
+		MYOFFICE, 21648, 13530, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_BAMBOO_ONE_6X8},
+		GRAPHIRE, 16704, 12064, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_CINTIQ_21UX},
+		CINTIQ, 87200, 65600, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_VOLITO},
+		GRAPHIRE, 5104, 3712, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_PENSTATION2},
+		GRAPHIRE, 3250, 2320, 255
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_VOLITO2_4X5},
+		GRAPHIRE, 5104, 3712, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_VOLITO2_2X3},
+		GRAPHIRE, 3248, 2320, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_PENPARTNER2},
+		GRAPHIRE, 3250, 2320, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_BAMBOO},
+		MYOFFICE, 14760, 9225, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_BAMBOO_ONE_4X5},
+		GRAPHIRE, 5104, 3712, 511
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_4X5},
+		INTUOS3S, 25400, 20320, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_6X8},
+		INTUOS3L, 40640, 30480, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_9X12},
+		INTUOS3L, 60960, 45720, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_12X12},
+		INTUOS3L, 60960, 60960, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_12X19},
+		INTUOS3L, 97536, 60960, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_6X11},
+		INTUOS3L, 54204, 31750, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS3_4X6},
+		INTUOS3S, 31496, 19685, 1023
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS4_4X6},
+		INTUOS4S, 31496, 19685, 2047
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS4_6X9},
+		INTUOS4L, 44704, 27940, 2047
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS4_8X13},
+		INTUOS4L, 65024, 40640, 2047
+	},
+	{
+		{USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS4_12X19},
+		INTUOS4L, 97536, 60960, 2047
+	},
+	{{0, 0},    0,  0, 0, 0}
+};
+
+#define	PACKET_BIT(b, s)		((packet[b] >> (s)) & 1)
+#define	PACKET_BITS(b, s, n) \
+	((((s) + (n) > 32 ? ((packet[(b) - 4]) << (32 - (s))) : 0) | \
+	((s) + (n) > 24 ? ((packet[(b) - 3]) << (24 - (s))) : 0) | \
+	((s) + (n) > 16 ? ((packet[(b) - 2]) << (16 - (s))) : 0) | \
+	((s) + (n) >  8 ? ((packet[(b) - 1]) << (8 - (s))) : 0) | \
+	((packet[(b)]) >> (s))) & \
+	((n) == 32 ? 0xffffffff : (1 << (n)) - 1))
+
+#define	BM_SIZE(x) \
+	(((x) / (sizeof (long) * 8) + 1) * sizeof (long))
+#define	BM_SET_BIT(x, y) \
+	((x)[(y) / (sizeof (long) * 8)] |= (1ul << ((y) % (sizeof (long) * 8))))
+
+static const size_t bm_size[EVT_USED] = {
+	BM_SIZE(EVT_MAX),
+	BM_SIZE(BTN_MAX),
+	BM_SIZE(REL_MAX),
+	BM_SIZE(ABS_MAX),
+	BM_SIZE(MSC_MAX),
+};
+
+#define	PRINT_MASK_ALL	0xFFFFFFFF
+
+#endif	/* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SYS_USB_USBWCM_H */
--- a/usr/src/uts/intel/Makefile.intel.shared	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/intel/Makefile.intel.shared	Thu Jan 14 17:07:01 2010 +0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -547,6 +547,7 @@
 STRMOD_KMODS	+= tirdwr ttcompat
 STRMOD_KMODS	+= usbkbm
 STRMOD_KMODS	+= usbms
+STRMOD_KMODS	+= usbwcm
 STRMOD_KMODS	+= usb_ah
 STRMOD_KMODS	+= drcompat
 STRMOD_KMODS	+= cryptmod
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/usbwcm/Makefile	Thu Jan 14 17:07:01 2010 +0800
@@ -0,0 +1,98 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# uts/intel/usbwcm/Makefile
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+#	This makefile drives the production of the usbwcm kernel module.
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= usbwcm
+OBJECTS		= $(USBWCM_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(USBWCM_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_STRMOD_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
+
+#
+#	Override defaults to build a unique, local modstubs.o.
+#
+MODSTUBS_DIR	 = $(OBJS_DIR)
+CLEANFILES	+= $(MODSTUBS_O)
+
+#
+# depends on misc/usba
+#
+LDFLAGS         += -dy -Nmisc/usba
+
+#
+# For now, disable these lint checks; maintainers should endeavor
+# to investigate and remove these for maximum lint coverage.
+# Please do not carry these forward to new Makefiles.
+#
+LINTTAGS	+= -erroff=E_BAD_PTR_CAST_ALIGN
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
+
--- a/usr/src/uts/sparc/Makefile.sparc.shared	Wed Jan 13 19:48:54 2010 -0800
+++ b/usr/src/uts/sparc/Makefile.sparc.shared	Thu Jan 14 17:07:01 2010 +0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #	This makefile contains the common definitions for all sparc
@@ -376,7 +376,7 @@
 STRMOD_KMODS	+= pipemod ptem redirmod rpcmod rlmod telmod timod
 STRMOD_KMODS	+= spppasyn spppcomp
 STRMOD_KMODS	+= tirdwr ttcompat
-STRMOD_KMODS	+= usbkbm usbms usb_ah
+STRMOD_KMODS	+= usbkbm usbms usbwcm usb_ah
 STRMOD_KMODS	+= drcompat
 STRMOD_KMODS	+= cryptmod
 STRMOD_KMODS	+= vuid3ps2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sparc/usbwcm/Makefile	Thu Jan 14 17:07:01 2010 +0800
@@ -0,0 +1,97 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# uts/sparc/usbwcm/Makefile
+
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+#	This makefile drives the production of the usbwcm streams module.
+#
+#	sparc architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= usbwcm
+OBJECTS		= $(USBWCM_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(USBWCM_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_STRMOD_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/sparc/Makefile.sparc
+
+# 
+# lint pass one enforcement 
+# 
+CFLAGS += $(CCVERBOSE) 
+
+#
+# depends on misc/usba
+#
+LDFLAGS         += -dy -Nmisc/usba
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
+
+#
+# For now, disable these lint checks; maintainers should endeavor
+# to investigate and remove these for maximum lint coverage.
+# Please do not carry these forward to new Makefiles.
+#
+LINTTAGS	+= -erroff=E_BAD_PTR_CAST_ALIGN
+
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/sparc/Makefile.targ