Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * HID driver for Maltron L90
0004  *
0005  * Copyright (c) 1999 Andreas Gal
0006  * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
0007  * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
0008  * Copyright (c) 2008 Jiri Slaby
0009  * Copyright (c) 2012 David Dillow <dave@thedillows.org>
0010  * Copyright (c) 2006-2013 Jiri Kosina
0011  * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
0012  * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
0013  * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
0014  * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
0015  * Copyright (c) 2018 William Whistler <wtbw@wtbw.co.uk>
0016  */
0017 
0018 #include <linux/device.h>
0019 #include <linux/hid.h>
0020 #include <linux/module.h>
0021 
0022 #include "hid-ids.h"
0023 
0024 /* The original buggy USB descriptor */
0025 static u8 maltron_rdesc_o[] = {
0026     0x05, 0x01,        /* Usage Page (Generic Desktop Ctrls) */
0027     0x09, 0x80,        /* Usage (Sys Control)                */
0028     0xA1, 0x01,        /* Collection (Application)           */
0029     0x85, 0x02,        /*   Report ID (2)                    */
0030     0x75, 0x01,        /*   Report Size (1)                  */
0031     0x95, 0x01,        /*   Report Count (1)                 */
0032     0x15, 0x00,        /*   Logical Minimum (0)              */
0033     0x25, 0x01,        /*   Logical Maximum (1)              */
0034     0x09, 0x82,        /*   Usage (Sys Sleep)                */
0035     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0036     0x09, 0x82,        /*   Usage (Sys Sleep)                */
0037     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0038     0x09, 0x83,        /*   Usage (Sys Wake Up)              */
0039     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0040     0x75, 0x05,        /*   Report Size (5)                  */
0041     0x81, 0x01,        /*   Input (Const,Array,Abs)          */
0042     0xC0,              /* End Collection                     */
0043     0x05, 0x0C,        /* Usage Page (Consumer)              */
0044     0x09, 0x01,        /* Usage (Consumer Control)           */
0045     0xA1, 0x01,        /* Collection (Application)           */
0046     0x85, 0x03,        /*   Report ID (3)                    */
0047     0x95, 0x01,        /*   Report Count (1)                 */
0048     0x75, 0x10,        /*   Report Size (16)                 */
0049     0x19, 0x00,        /*   Usage Minimum (Unassigned)       */
0050     0x2A, 0xFF, 0x7F,  /*   Usage Maximum (0x7FFF)           */
0051     0x81, 0x00,        /*   Input (Data,Array,Abs)           */
0052     0xC0,              /* End Collection                     */
0053     0x06, 0x7F, 0xFF,  /* Usage Page (Vendor Defined 0xFF7F) */
0054     0x09, 0x01,        /* Usage (0x01)                       */
0055     0xA1, 0x01,        /* Collection (Application)           */
0056     0x85, 0x04,        /*   Report ID (4)                    */
0057     0x95, 0x01,        /*   Report Count (1)                 */
0058     0x75, 0x10,        /*   Report Size (16)                 */
0059     0x19, 0x00,        /*   Usage Minimum (0x00)             */
0060     0x2A, 0xFF, 0x7F,  /*   Usage Maximum (0x7FFF)           */
0061     0x81, 0x00,        /*   Input (Data,Array,Abs)           */
0062     0x75, 0x02,        /*   Report Size (2)                  */
0063     0x25, 0x02,        /*   Logical Maximum (2)              */
0064     0x09, 0x90,        /*   Usage (0x90)                     */
0065     0xB1, 0x02,        /*   Feature (Data,Var,Abs)           */
0066     0x75, 0x06,        /*   Report Size (6)                  */
0067     0xB1, 0x01,        /*   Feature (Const,Array,Abs)        */
0068     0x75, 0x01,        /*   Report Size (1)                  */
0069     0x25, 0x01,        /*   Logical Maximum (1)              */
0070     0x05, 0x08,        /*   Usage Page (LEDs)                */
0071     0x09, 0x2A,        /*   Usage (On-Line)                  */
0072     0x91, 0x02,        /*   Output (Data,Var,Abs)            */
0073     0x09, 0x4B,        /*   Usage (Generic Indicator)        */
0074     0x91, 0x02,        /*   Output (Data,Var,Abs)            */
0075     0x75, 0x06,        /*   Report Size (6)                  */
0076     0x95, 0x01,        /*   Report Count (1)                 */
0077     0x91, 0x01,        /*   Output (Const,Array,Abs)         */
0078     0xC0               /* End Collection                     */
0079 };
0080 
0081 /* The patched descriptor, allowing media key events to be accepted as valid */
0082 static u8 maltron_rdesc[] = {
0083     0x05, 0x01,        /* Usage Page (Generic Desktop Ctrls) */
0084     0x09, 0x80,        /* Usage (Sys Control)                */
0085     0xA1, 0x01,        /* Collection (Application)           */
0086     0x85, 0x02,        /*   Report ID (2)                    */
0087     0x75, 0x01,        /*   Report Size (1)                  */
0088     0x95, 0x01,        /*   Report Count (1)                 */
0089     0x15, 0x00,        /*   Logical Minimum (0)              */
0090     0x25, 0x01,        /*   Logical Maximum (1)              */
0091     0x09, 0x82,        /*   Usage (Sys Sleep)                */
0092     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0093     0x09, 0x82,        /*   Usage (Sys Sleep)                */
0094     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0095     0x09, 0x83,        /*   Usage (Sys Wake Up)              */
0096     0x81, 0x06,        /*   Input (Data,Var,Rel)             */
0097     0x75, 0x05,        /*   Report Size (5)                  */
0098     0x81, 0x01,        /*   Input (Const,Array,Abs)          */
0099     0xC0,              /* End Collection                     */
0100     0x05, 0x0C,        /* Usage Page (Consumer)              */
0101     0x09, 0x01,        /* Usage (Consumer Control)           */
0102     0xA1, 0x01,        /* Collection (Application)           */
0103     0x85, 0x03,        /*   Report ID (3)                    */
0104     0x15, 0x00,        /*   Logical Minimum (0)              - changed */
0105     0x26, 0xFF, 0x7F,  /*   Logical Maximum (32767)          - changed */
0106     0x95, 0x01,        /*   Report Count (1)                 */
0107     0x75, 0x10,        /*   Report Size (16)                 */
0108     0x19, 0x00,        /*   Usage Minimum (Unassigned)       */
0109     0x2A, 0xFF, 0x7F,  /*   Usage Maximum (0x7FFF)           */
0110     0x81, 0x00,        /*   Input (Data,Array,Abs)           */
0111     0xC0,              /* End Collection                     */
0112     0x06, 0x7F, 0xFF,  /* Usage Page (Vendor Defined 0xFF7F) */
0113     0x09, 0x01,        /* Usage (0x01)                       */
0114     0xA1, 0x01,        /* Collection (Application)           */
0115     0x85, 0x04,        /*   Report ID (4)                    */
0116     0x95, 0x01,        /*   Report Count (1)                 */
0117     0x75, 0x10,        /*   Report Size (16)                 */
0118     0x19, 0x00,        /*   Usage Minimum (0x00)             */
0119     0x2A, 0xFF, 0x7F,  /*   Usage Maximum (0x7FFF)           */
0120     0x81, 0x00,        /*   Input (Data,Array,Abs)           */
0121     0x75, 0x02,        /*   Report Size (2)                  */
0122     0x25, 0x02,        /*   Logical Maximum (2)              */
0123     0x09, 0x90,        /*   Usage (0x90)                     */
0124     0xB1, 0x02,        /*   Feature (Data,Var,Abs)           */
0125     0x75, 0x06,        /*   Report Size (6)                  */
0126     0xB1, 0x01,        /*   Feature (Const,Array,Abs)        */
0127     0x75, 0x01,        /*   Report Size (1)                  */
0128     0x25, 0x01,        /*   Logical Maximum (1)              */
0129     0x05, 0x08,        /*   Usage Page (LEDs)                */
0130     0x09, 0x2A,        /*   Usage (On-Line)                  */
0131     0x91, 0x02,        /*   Output (Data,Var,Abs)            */
0132     0x09, 0x4B,        /*   Usage (Generic Indicator)        */
0133     0x91, 0x02,        /*   Output (Data,Var,Abs)            */
0134     0x75, 0x06,        /*   Report Size (6)                  */
0135     0x95, 0x01,        /*   Report Count (1)                 */
0136     0x91, 0x01,        /*   Output (Const,Array,Abs)         */
0137     0xC0               /* End Collection                     */
0138 };
0139 
0140 static __u8 *maltron_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0141                   unsigned int *rsize)
0142 {
0143     if (*rsize == sizeof(maltron_rdesc_o) &&
0144         !memcmp(maltron_rdesc_o, rdesc, sizeof(maltron_rdesc_o))) {
0145         hid_info(hdev, "Replacing Maltron L90 keyboard report descriptor\n");
0146         *rsize = sizeof(maltron_rdesc);
0147         return maltron_rdesc;
0148     }
0149     return rdesc;
0150 }
0151 
0152 static const struct hid_device_id maltron_devices[] = {
0153     { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_MALTRON_KB)},
0154     { }
0155 };
0156 MODULE_DEVICE_TABLE(hid, maltron_devices);
0157 
0158 static struct hid_driver maltron_driver = {
0159     .name = "maltron",
0160     .id_table = maltron_devices,
0161     .report_fixup = maltron_report_fixup
0162 };
0163 module_hid_driver(maltron_driver);
0164 
0165 MODULE_LICENSE("GPL");