Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 May 2009 17:56:37 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 162165 for review
Message-ID:  <200905161756.n4GHub4e055534@repoman.freebsd.org>

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

Change 162165 by hselasky@hselasky_laptop001 on 2009/05/16 17:55:40

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

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/usbhid.h#8 edit

Differences ...

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

@@ -113,12 +113,13 @@
 #define	MOD_WIN_R	0x80
 	uint8_t	reserved;
 	uint8_t	keycode[UKBD_NKEYCODE];
-} __packed;
+	uint8_t exten[8];
+};
 
 enum {
 	UKBD_INTR_DT,
 	UKBD_CTRL_LED,
-	UKBD_N_TRANSFER = 3,
+	UKBD_N_TRANSFER,
 };
 
 struct ukbd_softc {
@@ -126,6 +127,8 @@
 	keymap_t sc_keymap;
 	accentmap_t sc_accmap;
 	fkeytab_t sc_fkeymap[UKBD_NFKEY];
+	struct hid_location sc_loc_apple_eject;
+	struct hid_location sc_loc_apple_fn;
 	struct usb2_callout sc_callout;
 	struct ukbd_data sc_ndata;
 	struct ukbd_data sc_odata;
@@ -143,11 +146,14 @@
 	uint32_t sc_buffered_char[2];
 #endif
 	uint32_t sc_flags;		/* flags */
-#define	UKBD_FLAG_COMPOSE    0x0001
-#define	UKBD_FLAG_POLLING    0x0002
-#define	UKBD_FLAG_SET_LEDS   0x0004
-#define	UKBD_FLAG_ATTACHED   0x0010
-#define	UKBD_FLAG_GONE       0x0020
+#define	UKBD_FLAG_COMPOSE	0x0001
+#define	UKBD_FLAG_POLLING	0x0002
+#define	UKBD_FLAG_SET_LEDS	0x0004
+#define	UKBD_FLAG_ATTACHED	0x0010
+#define	UKBD_FLAG_GONE		0x0020
+#define	UKBD_FLAG_APPLE_EJECT	0x0040
+#define	UKBD_FLAG_APPLE_FN	0x0080
+#define	UKBD_FLAG_APPLE_SWAP	0x0100
 
 	int32_t	sc_mode;		/* input mode (K_XLATE,K_RAW,K_CODE) */
 	int32_t	sc_state;		/* shift/lock key state */
@@ -450,6 +456,28 @@
 	usb2_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc);
 }
 
+static uint8_t
+ukbd_apple_fn(uint8_t keycode) {
+	switch (keycode) {
+	case 0x2a: return 0x4c; /* BACKSPACE -> DEL */
+	case 0x2c: return 0x49; /* SPACE -> INSERT */
+	case 0x50: return 0x4a; /* LEFT ARROW -> HOME */
+	case 0x4f: return 0x4d; /* RIGHT ARROW -> END */
+	case 0x52: return 0x4b; /* UP ARROW -> PGUP */
+	case 0x51: return 0x4e; /* DOWN ARROW -> PGDN */
+	default: return keycode;
+	}
+}
+
+static uint8_t
+ukbd_apple_swap(uint8_t keycode) {
+	switch (keycode) {
+	case 0x35: return 0x64; /* 5 -> d */
+	case 0x64: return 0x35; /* d -> 5 */
+	default: return keycode;
+	}
+}
+
 static void
 ukbd_intr_callback(struct usb2_xfer *xfer)
 {
@@ -457,26 +485,58 @@
 	uint16_t len = xfer->actlen;
 	uint8_t i;
 	uint8_t offset;
+	uint8_t id;
+	uint8_t apple_fn;
+	uint8_t apple_eject;
 
 	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 */
+		if (len == 0) {
+			DPRINTF("zero length data\n");
+			goto tr_setup;
+		}
+
+		if (sc->sc_hid_id != 0) {
+			/* check and remove HID ID byte */
+			usb2_copy_out(xfer->frbuffers, 0, &id, 1);
+			if (id != sc->sc_hid_id) {
+				DPRINTF("wrong HID ID\n");
+				goto tr_setup;
+			}
 			offset = 1;
 			len--;
 		} else {
 			offset = 0;
 		}
+
 		if (len > sizeof(sc->sc_ndata)) {
 			len = sizeof(sc->sc_ndata);
 		}
+
 		if (len) {
 			memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
 			usb2_copy_out(xfer->frbuffers, offset, 
 			    &sc->sc_ndata, len);
+
+			if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) &&
+			    hid_get_data((uint8_t *)&sc->sc_ndata,
+				len, &sc->sc_loc_apple_eject))
+				apple_eject = 1;
+			else
+				apple_eject = 0;
+
+			if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) &&
+			    hid_get_data((uint8_t *)&sc->sc_ndata,
+				len, &sc->sc_loc_apple_fn))
+				apple_fn = 1;
+			else
+				apple_fn = 0;
 #if USB_DEBUG
+			DPRINTF("apple_eject=%u apple_fn=%u\n",
+			    apple_eject, apple_fn);
+
 			if (sc->sc_ndata.modifiers) {
 				DPRINTF("mod: 0x%04x\n", sc->sc_ndata.modifiers);
 			}
@@ -486,6 +546,21 @@
 				}
 			}
 #endif					/* USB_DEBUG */
+
+			if (apple_fn) {
+				for (i = 0; i < UKBD_NKEYCODE; i++) {
+					sc->sc_ndata.keycode[i] = 
+					    ukbd_apple_fn(sc->sc_ndata.keycode[i]);
+				}
+			}
+
+			if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) {
+				for (i = 0; i < UKBD_NKEYCODE; i++) {
+					sc->sc_ndata.keycode[i] = 
+					    ukbd_apple_swap(sc->sc_ndata.keycode[i]);
+				}
+			}
+
 			ukbd_interrupt(sc);
 		}
 	case USB_ST_SETUP:
@@ -604,6 +679,7 @@
 	keyboard_t *kbd = &sc->sc_kbd;
 	void *hid_ptr = NULL;
 	usb2_error_t err;
+	uint32_t flags;
 	uint16_t n;
 	uint16_t hid_len;
 
@@ -657,7 +733,30 @@
 	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);
+		/* investigate if this is an Apple Keyboard */
+		if (hid_locate(hid_ptr, hid_len,
+		    HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT),
+		    hid_input, 0, &sc->sc_loc_apple_eject, &flags,
+		    &sc->sc_hid_id)) {
+			if (flags & HIO_VARIABLE)
+				sc->sc_flags |= UKBD_FLAG_APPLE_EJECT | 
+				    UKBD_FLAG_APPLE_SWAP;
+			if (hid_locate(hid_ptr, hid_len,
+			    HID_USAGE2(0xFFFF, 0x0003),
+			    hid_input, 0, &sc->sc_loc_apple_fn, &flags,
+			    &sc->sc_hid_id)) {
+				if (flags & HIO_VARIABLE)
+					sc->sc_flags |= UKBD_FLAG_APPLE_FN |
+					    UKBD_FLAG_APPLE_SWAP;
+			}
+		} else {
+			/* 
+			 * Assume the first HID ID contains the
+			 * keyboard data
+			 */
+			hid_report_size(hid_ptr, hid_len,
+			    hid_input, &sc->sc_hid_id);
+		}
 		free(hid_ptr, M_TEMP);
 	}
 

==== //depot/projects/usb/src/sys/dev/usb/usbhid.h#8 (text+ko) ====

@@ -128,6 +128,7 @@
 #define	HUG_SYSTEM_MENU_LEFT	0x008b
 #define	HUG_SYSTEM_MENU_UP	0x008c
 #define	HUG_SYSTEM_MENU_DOWN	0x008d
+#define	HUG_APPLE_EJECT		0x00b8
 
 /* Usages Digitizers */
 #define	HUD_UNDEFINED		0x0000



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