From patchwork Fri Jan 28 11:50:52 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolai Kondrashov X-Patchwork-Id: 514621 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0SBpJOT032463 for ; Fri, 28 Jan 2011 12:08:43 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754594Ab1A1LvS (ORCPT ); Fri, 28 Jan 2011 06:51:18 -0500 Received: from mail-ew0-f46.google.com ([209.85.215.46]:33977 "EHLO mail-ew0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754749Ab1A1LvR (ORCPT ); Fri, 28 Jan 2011 06:51:17 -0500 Received: by mail-ew0-f46.google.com with SMTP id 5so1444229ewy.19 for ; Fri, 28 Jan 2011 03:51:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=scNJ4y4P5Sbe22oVRSPWxCF7MMpx/FCtNBKVHsqrt30=; b=oT/T1DK4Y67jY5OTSVwwIz3YfVKxDIfJAC7PKm106VVIDFDG6bSsYE4OYgW0hL94pY z8sFK9e2JJ/wvKw4s+yuYVP2SP3NYZDZ5dGzLrIAU6zOU9CU7dOwB5GHyJw7BP/K/PVe eg1qRLuzNjAWd593DJUS7QgadoRCnCd5MWqi8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=Ik2oCHm9SXa8cy4dLQDEpbyQaeW6/hJIJD4o8jChaB6zUay1npUGaB32pWSbzPZzXz wkSxI9DbzPazHQ5442AfDadFFKihAGgqgWge4UTgQZdumX7b7Wm+EPtZjYAkeOReYlju gQyG/gnC4Zllx0BEBtEoH0HxmV2UiUWztuMhs= Received: by 10.213.31.132 with SMTP id y4mr4712738ebc.1.1296215476782; Fri, 28 Jan 2011 03:51:16 -0800 (PST) Received: from pippin.ponomarevs.spb.ru (umbar.oktetlabs.ru [188.134.5.200]) by mx.google.com with ESMTPS id q52sm1196306eei.9.2011.01.28.03.51.15 (version=SSLv3 cipher=RC4-MD5); Fri, 28 Jan 2011 03:51:15 -0800 (PST) From: Nikolai Kondrashov To: Jiri Kosina Cc: Dmitry Torokhov , linux-input , Vladislav Naumov , Nikolai Kondrashov Subject: [PATCH 2/3] Input: add support for DragonRise PID 0011 gamepad Date: Fri, 28 Jan 2011 14:50:52 +0300 Message-Id: <1296215454-2586-3-git-send-email-spbnick@gmail.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1296215454-2586-1-git-send-email-spbnick@gmail.com> References: <1296215454-2586-1-git-send-email-spbnick@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 28 Jan 2011 12:08:45 +0000 (UTC) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d678cf3..75af1f8 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1328,6 +1328,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index afcf3d6..61eece4 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -145,6 +145,110 @@ static inline int drff_init(struct hid_device *hid) } #endif +/* + * The original descriptor of joystick with PID 0x0011, represented by DVTech PC + * JS19. It seems both copied from another device and a result of confusion + * either about the specification or about the program used to create the + * descriptor. In any case, it's a wonder it works on Windows. + * + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Joystik), ; Joystik (04h, application collection) + * Collection (Application), + * Collection (Logical), + * Report Size (8), + * Report Count (5), + * Logical Minimum (0), + * Logical Maximum (255), + * Physical Minimum (0), + * Physical Maximum (255), + * Usage (X), ; X (30h, dynamic value) + * Usage (X), ; X (30h, dynamic value) + * Usage (X), ; X (30h, dynamic value) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Input (Variable), + * Report Size (4), + * Report Count (1), + * Logical Maximum (7), + * Physical Maximum (315), + * Unit (Degrees), + * Usage (00h), + * Input (Variable, Null State), + * Unit, + * Report Size (1), + * Report Count (10), + * Logical Maximum (1), + * Physical Maximum (1), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (0Ah), + * Input (Variable), + * Usage Page (FF00h), ; FF00h, vendor-defined + * Report Size (1), + * Report Count (10), + * Logical Maximum (1), + * Physical Maximum (1), + * Usage (01h), + * Input (Variable), + * End Collection, + * Collection (Logical), + * Report Size (8), + * Report Count (4), + * Physical Maximum (255), + * Logical Maximum (255), + * Usage (02h), + * Output (Variable), + * End Collection, + * End Collection + */ + +/* Size of the original descriptor of the PID 0x0011 joystick */ +#define PID0011_RDESC_ORIG_SIZE 101 + +/* Fixed report descriptor for PID 0x011 joystick */ +static __u8 pid0011_rdesc_fixed[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x04, /* Usage (Joystik), */ + 0xA1, 0x01, /* Collection (Application), */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x14, /* Logical Minimum (0), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x01, /* Input (Constant), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x95, 0x02, /* Report Count (2), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x04, /* Report Count (4), */ + 0x81, 0x01, /* Input (Constant), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x0A, /* Report Count (10), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x0A, /* Usage Maximum (0Ah), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x0A, /* Report Count (10), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + switch (hdev->product) { + case 0x0011: + if (*rsize == PID0011_RDESC_ORIG_SIZE) { + rdesc = pid0011_rdesc_fixed; + *rsize = sizeof(pid0011_rdesc_fixed); + } + break; + } + return rdesc; +} + static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -163,7 +267,16 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err; } - drff_init(hdev); + switch (hdev->product) { + case 0x0006: + ret = drff_init(hdev); + if (ret) { + dev_err(&hdev->dev, "force feedback init failed\n"); + hid_hw_stop(hdev); + goto err; + } + break; + } return 0; err: @@ -172,6 +285,7 @@ err: static const struct hid_device_id dr_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), }, { } }; MODULE_DEVICE_TABLE(hid, dr_devices); @@ -179,6 +293,7 @@ MODULE_DEVICE_TABLE(hid, dr_devices); static struct hid_driver dr_driver = { .name = "dragonrise", .id_table = dr_devices, + .report_fixup = dr_report_fixup, .probe = dr_probe, };