17c2af0a1SNikolai Kondrashov // SPDX-License-Identifier: GPL-2.0+
27c2af0a1SNikolai Kondrashov /*
37c2af0a1SNikolai Kondrashov * HID driver for ViewSonic devices not fully compliant with HID standard
47c2af0a1SNikolai Kondrashov *
57c2af0a1SNikolai Kondrashov * Copyright (c) 2017 Nikolai Kondrashov
67c2af0a1SNikolai Kondrashov */
77c2af0a1SNikolai Kondrashov
87c2af0a1SNikolai Kondrashov /*
97c2af0a1SNikolai Kondrashov * This program is free software; you can redistribute it and/or modify it
107c2af0a1SNikolai Kondrashov * under the terms of the GNU General Public License as published by the Free
117c2af0a1SNikolai Kondrashov * Software Foundation; either version 2 of the License, or (at your option)
127c2af0a1SNikolai Kondrashov * any later version.
137c2af0a1SNikolai Kondrashov */
147c2af0a1SNikolai Kondrashov
157c2af0a1SNikolai Kondrashov #include <linux/device.h>
167c2af0a1SNikolai Kondrashov #include <linux/hid.h>
177c2af0a1SNikolai Kondrashov #include <linux/module.h>
187c2af0a1SNikolai Kondrashov
197c2af0a1SNikolai Kondrashov #include "hid-ids.h"
207c2af0a1SNikolai Kondrashov
217c2af0a1SNikolai Kondrashov /* Size of the original descriptor of PD1011 signature pad */
227c2af0a1SNikolai Kondrashov #define PD1011_RDESC_ORIG_SIZE 408
237c2af0a1SNikolai Kondrashov
247c2af0a1SNikolai Kondrashov /* Fixed report descriptor of PD1011 signature pad */
257c2af0a1SNikolai Kondrashov static __u8 pd1011_rdesc_fixed[] = {
267c2af0a1SNikolai Kondrashov 0x05, 0x0D, /* Usage Page (Digitizer), */
27*f7d8e387SNikolai Kondrashov 0x09, 0x01, /* Usage (Digitizer), */
287c2af0a1SNikolai Kondrashov 0xA1, 0x01, /* Collection (Application), */
297c2af0a1SNikolai Kondrashov 0x85, 0x02, /* Report ID (2), */
307c2af0a1SNikolai Kondrashov 0x09, 0x20, /* Usage (Stylus), */
317c2af0a1SNikolai Kondrashov 0xA0, /* Collection (Physical), */
327c2af0a1SNikolai Kondrashov 0x75, 0x10, /* Report Size (16), */
337c2af0a1SNikolai Kondrashov 0x95, 0x01, /* Report Count (1), */
347c2af0a1SNikolai Kondrashov 0xA4, /* Push, */
357c2af0a1SNikolai Kondrashov 0x05, 0x01, /* Usage Page (Desktop), */
367c2af0a1SNikolai Kondrashov 0x65, 0x13, /* Unit (Inch), */
377c2af0a1SNikolai Kondrashov 0x55, 0xFD, /* Unit Exponent (-3), */
387c2af0a1SNikolai Kondrashov 0x34, /* Physical Minimum (0), */
397c2af0a1SNikolai Kondrashov 0x09, 0x30, /* Usage (X), */
407c2af0a1SNikolai Kondrashov 0x46, 0x5D, 0x21, /* Physical Maximum (8541), */
417c2af0a1SNikolai Kondrashov 0x27, 0x80, 0xA9,
427c2af0a1SNikolai Kondrashov 0x00, 0x00, /* Logical Maximum (43392), */
437c2af0a1SNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
447c2af0a1SNikolai Kondrashov 0x09, 0x31, /* Usage (Y), */
457c2af0a1SNikolai Kondrashov 0x46, 0xDA, 0x14, /* Physical Maximum (5338), */
467c2af0a1SNikolai Kondrashov 0x26, 0xF0, 0x69, /* Logical Maximum (27120), */
477c2af0a1SNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
487c2af0a1SNikolai Kondrashov 0xB4, /* Pop, */
497c2af0a1SNikolai Kondrashov 0x14, /* Logical Minimum (0), */
507c2af0a1SNikolai Kondrashov 0x25, 0x01, /* Logical Maximum (1), */
517c2af0a1SNikolai Kondrashov 0x75, 0x01, /* Report Size (1), */
527c2af0a1SNikolai Kondrashov 0x95, 0x01, /* Report Count (1), */
537c2af0a1SNikolai Kondrashov 0x81, 0x03, /* Input (Constant, Variable), */
547c2af0a1SNikolai Kondrashov 0x09, 0x32, /* Usage (In Range), */
557c2af0a1SNikolai Kondrashov 0x09, 0x42, /* Usage (Tip Switch), */
567c2af0a1SNikolai Kondrashov 0x95, 0x02, /* Report Count (2), */
577c2af0a1SNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
587c2af0a1SNikolai Kondrashov 0x95, 0x05, /* Report Count (5), */
597c2af0a1SNikolai Kondrashov 0x81, 0x03, /* Input (Constant, Variable), */
607c2af0a1SNikolai Kondrashov 0x75, 0x10, /* Report Size (16), */
617c2af0a1SNikolai Kondrashov 0x95, 0x01, /* Report Count (1), */
627c2af0a1SNikolai Kondrashov 0x09, 0x30, /* Usage (Tip Pressure), */
637c2af0a1SNikolai Kondrashov 0x15, 0x05, /* Logical Minimum (5), */
647c2af0a1SNikolai Kondrashov 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */
657c2af0a1SNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
667c2af0a1SNikolai Kondrashov 0x75, 0x10, /* Report Size (16), */
677c2af0a1SNikolai Kondrashov 0x95, 0x01, /* Report Count (1), */
687c2af0a1SNikolai Kondrashov 0x81, 0x03, /* Input (Constant, Variable), */
697c2af0a1SNikolai Kondrashov 0xC0, /* End Collection, */
707c2af0a1SNikolai Kondrashov 0xC0 /* End Collection */
717c2af0a1SNikolai Kondrashov };
727c2af0a1SNikolai Kondrashov
viewsonic_report_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)737c2af0a1SNikolai Kondrashov static __u8 *viewsonic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
747c2af0a1SNikolai Kondrashov unsigned int *rsize)
757c2af0a1SNikolai Kondrashov {
767c2af0a1SNikolai Kondrashov switch (hdev->product) {
777c2af0a1SNikolai Kondrashov case USB_DEVICE_ID_VIEWSONIC_PD1011:
787c2af0a1SNikolai Kondrashov case USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011:
797c2af0a1SNikolai Kondrashov if (*rsize == PD1011_RDESC_ORIG_SIZE) {
807c2af0a1SNikolai Kondrashov rdesc = pd1011_rdesc_fixed;
817c2af0a1SNikolai Kondrashov *rsize = sizeof(pd1011_rdesc_fixed);
827c2af0a1SNikolai Kondrashov }
837c2af0a1SNikolai Kondrashov break;
847c2af0a1SNikolai Kondrashov }
857c2af0a1SNikolai Kondrashov
867c2af0a1SNikolai Kondrashov return rdesc;
877c2af0a1SNikolai Kondrashov }
887c2af0a1SNikolai Kondrashov
897c2af0a1SNikolai Kondrashov static const struct hid_device_id viewsonic_devices[] = {
907c2af0a1SNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_VIEWSONIC,
917c2af0a1SNikolai Kondrashov USB_DEVICE_ID_VIEWSONIC_PD1011) },
927c2af0a1SNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_SIGNOTEC,
937c2af0a1SNikolai Kondrashov USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011) },
947c2af0a1SNikolai Kondrashov { }
957c2af0a1SNikolai Kondrashov };
967c2af0a1SNikolai Kondrashov MODULE_DEVICE_TABLE(hid, viewsonic_devices);
977c2af0a1SNikolai Kondrashov
987c2af0a1SNikolai Kondrashov static struct hid_driver viewsonic_driver = {
997c2af0a1SNikolai Kondrashov .name = "viewsonic",
1007c2af0a1SNikolai Kondrashov .id_table = viewsonic_devices,
1017c2af0a1SNikolai Kondrashov .report_fixup = viewsonic_report_fixup,
1027c2af0a1SNikolai Kondrashov };
1037c2af0a1SNikolai Kondrashov module_hid_driver(viewsonic_driver);
1047c2af0a1SNikolai Kondrashov
1057c2af0a1SNikolai Kondrashov MODULE_LICENSE("GPL");
106