Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 May 2009 06:25:47 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 162145 for review
Message-ID:  <200905160625.n4G6PlBU049229@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=162145

Change 162145 by hselasky@hselasky_laptop001 on 2009/05/16 06:25:17

	
	USB input:
	  - patch for Apple MacBook Pro keyboard.
	
	Reported by: Christoph Langguth

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#5 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#5 (text+ko) ====

@@ -117,7 +117,6 @@
 
 enum {
 	UKBD_INTR_DT,
-	UKBD_INTR_CS,
 	UKBD_CTRL_LED,
 	UKBD_N_TRANSFER = 3,
 };
@@ -147,7 +146,6 @@
 #define	UKBD_FLAG_COMPOSE    0x0001
 #define	UKBD_FLAG_POLLING    0x0002
 #define	UKBD_FLAG_SET_LEDS   0x0004
-#define	UKBD_FLAG_INTR_STALL 0x0008
 #define	UKBD_FLAG_ATTACHED   0x0010
 #define	UKBD_FLAG_GONE       0x0020
 
@@ -162,6 +160,7 @@
 	uint8_t	sc_leds;		/* store for async led requests */
 	uint8_t	sc_iface_index;
 	uint8_t	sc_iface_no;
+	uint8_t sc_hid_id;
 };
 
 #define	KEY_ERROR	  0x01
@@ -452,35 +451,31 @@
 }
 
 static void
-ukbd_clear_stall_callback(struct usb2_xfer *xfer)
-{
-	struct ukbd_softc *sc = xfer->priv_sc;
-	struct usb2_xfer *xfer_other = sc->sc_xfer[UKBD_INTR_DT];
-
-	if (usb2_clear_stall_callback(xfer, xfer_other)) {
-		DPRINTF("stall cleared\n");
-		sc->sc_flags &= ~UKBD_FLAG_INTR_STALL;
-		usb2_transfer_start(xfer_other);
-	}
-}
-
-static void
 ukbd_intr_callback(struct usb2_xfer *xfer)
 {
 	struct ukbd_softc *sc = xfer->priv_sc;
 	uint16_t len = xfer->actlen;
 	uint8_t i;
+	uint8_t offset;
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 		DPRINTF("actlen=%d bytes\n", len);
 
+		if ((sc->sc_hid_id != 0) && (len != 0)) {
+			/* remove HID ID byte */
+			offset = 1;
+			len--;
+		} else {
+			offset = 0;
+		}
 		if (len > sizeof(sc->sc_ndata)) {
 			len = sizeof(sc->sc_ndata);
 		}
 		if (len) {
-			bzero(&sc->sc_ndata, sizeof(sc->sc_ndata));
-			usb2_copy_out(xfer->frbuffers, 0, &sc->sc_ndata, len);
+			memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
+			usb2_copy_out(xfer->frbuffers, offset, 
+			    &sc->sc_ndata, len);
 #if USB_DEBUG
 			if (sc->sc_ndata.modifiers) {
 				DPRINTF("mod: 0x%04x\n", sc->sc_ndata.modifiers);
@@ -494,27 +489,24 @@
 			ukbd_interrupt(sc);
 		}
 	case USB_ST_SETUP:
-		if (sc->sc_flags & UKBD_FLAG_INTR_STALL) {
-			usb2_transfer_start(sc->sc_xfer[UKBD_INTR_CS]);
-			return;
-		}
+tr_setup:
 		if (sc->sc_inputs < UKBD_IN_BUF_FULL) {
 			xfer->frlengths[0] = xfer->max_data_length;
 			usb2_start_hardware(xfer);
 		} else {
 			DPRINTF("input queue is full!\n");
 		}
-		return;
+		break;
 
 	default:			/* Error */
 		DPRINTF("error=%s\n", usb2_errstr(xfer->error));
 
 		if (xfer->error != USB_ERR_CANCELLED) {
 			/* try to clear stall first */
-			sc->sc_flags |= UKBD_FLAG_INTR_STALL;
-			usb2_transfer_start(sc->sc_xfer[UKBD_INTR_CS]);
+			xfer->flags.stall_pipe = 1;
+			goto tr_setup;
 		}
-		return;
+		break;
 	}
 }
 
@@ -567,16 +559,6 @@
 		.callback = &ukbd_intr_callback,
 	},
 
-	[UKBD_INTR_CS] = {
-		.type = UE_CONTROL,
-		.endpoint = 0x00,	/* Control pipe */
-		.direction = UE_DIR_ANY,
-		.bufsize = sizeof(struct usb2_device_request),
-		.callback = &ukbd_clear_stall_callback,
-		.timeout = 1000,	/* 1 second */
-		.interval = 50,	/* 50ms */
-	},
-
 	[UKBD_CTRL_LED] = {
 		.type = UE_CONTROL,
 		.endpoint = 0x00,	/* Control pipe */
@@ -620,8 +602,10 @@
 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
 	int32_t unit = device_get_unit(dev);
 	keyboard_t *kbd = &sc->sc_kbd;
+	void *hid_ptr = NULL;
 	usb2_error_t err;
 	uint16_t n;
+	uint16_t hid_len;
 
 	mtx_assert(&Giant, MA_OWNED);
 
@@ -669,6 +653,14 @@
 	 */
 	KBD_PROBE_DONE(kbd);
 
+	/* figure out if there is an ID byte in the data */
+	err = usb2_req_get_hid_desc(uaa->device, NULL, &hid_ptr,
+	    &hid_len, M_TEMP, uaa->info.bIfaceIndex);
+	if (err == 0) {
+		hid_report_size(hid_ptr, hid_len, hid_input, &sc->sc_hid_id);
+		free(hid_ptr, M_TEMP);
+	}
+
 	/* ignore if SETIDLE fails, hence it is not crucial */
 	err = usb2_req_set_idle(sc->sc_udev, &Giant, sc->sc_iface_index, 0, 0);
 



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