Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 940824b0 authored by Vojtech Pavlik's avatar Vojtech Pavlik Committed by Dmitry Torokhov
Browse files

Input: HID - add support for Cherry Cymotion keyboard



The Cherry Cymotion is a special Linux keyboard made by Cherry, with
only one little problem: it doesn't work with Linux. This patch
(originally by hexten.net, cleaned up by me) makes it work including
all the special keys.

Signed-off-by: default avatarVojtech Pavlik <vojtech@suse.cz>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 3dd01a83
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE		0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE	0x0304

#define USB_VENDOR_ID_CHERRY		0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023

/*
 * Alphabetically sorted blacklist by quirk type.
 */
@@ -1580,6 +1583,8 @@ static const struct hid_blacklist {
	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },

	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },

	{ 0, 0 }
};

@@ -1626,6 +1631,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
		usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}

/*
 * Cherry Cymotion keyboard have an invalid HID report descriptor,
 * that needs fixing before we can parse it.
 */

static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
{
	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
		info("Fixing up Cherry Cymotion report descriptor");
		rdesc[11] = rdesc[16] = 0xff;
		rdesc[12] = rdesc[17] = 0x03;
	}
}

static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1673,6 +1692,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
		return NULL;
	}

	if ((quirks & HID_QUIRK_CYMOTION))
		hid_fixup_cymotion_descriptor(rdesc, rsize);

#ifdef DEBUG_DATA
	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
	for (n = 0; n < rsize; n++)
+8 −0
Original line number Diff line number Diff line
@@ -289,11 +289,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case 0x226: map_key_clear(KEY_STOP);		break;
				case 0x227: map_key_clear(KEY_REFRESH);		break;
				case 0x22a: map_key_clear(KEY_BOOKMARKS);	break;
				case 0x233: map_key_clear(KEY_SCROLLUP);	break;
				case 0x234: map_key_clear(KEY_SCROLLDOWN);	break;
				case 0x238: map_rel(REL_HWHEEL);		break;
				case 0x279: map_key_clear(KEY_REDO);		break;
				case 0x289: map_key_clear(KEY_REPLY);		break;
				case 0x28b: map_key_clear(KEY_FORWARDMAIL);	break;
				case 0x28c: map_key_clear(KEY_SEND);		break;

				/* Reported on a Cherry Cymotion keyboard */
				case 0x301: map_key_clear(KEY_PROG1);		break;
				case 0x302: map_key_clear(KEY_PROG2);		break;
				case 0x303: map_key_clear(KEY_PROG3);		break;

				default:    goto ignore;
			}
			break;
+1 −0
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x200
#define HID_QUIRK_2WHEEL_POWERMOUSE		0x400
#define HID_QUIRK_CYMOTION			0x800

/*
 * This is the global environment of the parser. This information is