Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003 *  HID driver for zydacron remote control
0004 *
0005 *  Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk>
0006 */
0007 
0008 /*
0009 */
0010 
0011 #include <linux/device.h>
0012 #include <linux/hid.h>
0013 #include <linux/module.h>
0014 
0015 #include "hid-ids.h"
0016 
0017 struct zc_device {
0018     struct input_dev    *input_ep81;
0019     unsigned short      last_key[4];
0020 };
0021 
0022 
0023 /*
0024 * Zydacron remote control has an invalid HID report descriptor,
0025 * that needs fixing before we can parse it.
0026 */
0027 static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0028     unsigned int *rsize)
0029 {
0030     if (*rsize >= 253 &&
0031         rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff &&
0032         rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff &&
0033         rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) {
0034             hid_info(hdev,
0035                 "fixing up zydacron remote control report descriptor\n");
0036             rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c;
0037             rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00;
0038         }
0039     return rdesc;
0040 }
0041 
0042 #define zc_map_key_clear(c) \
0043     hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
0044 
0045 static int zc_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0046     struct hid_field *field, struct hid_usage *usage,
0047     unsigned long **bit, int *max)
0048 {
0049     int i;
0050     struct zc_device *zc = hid_get_drvdata(hdev);
0051     zc->input_ep81 = hi->input;
0052 
0053     if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
0054         return 0;
0055 
0056     dbg_hid("zynacron input mapping event [0x%x]\n",
0057         usage->hid & HID_USAGE);
0058 
0059     switch (usage->hid & HID_USAGE) {
0060     /* report 2 */
0061     case 0x10:
0062         zc_map_key_clear(KEY_MODE);
0063         break;
0064     case 0x30:
0065         zc_map_key_clear(KEY_SCREEN);
0066         break;
0067     case 0x70:
0068         zc_map_key_clear(KEY_INFO);
0069         break;
0070     /* report 3 */
0071     case 0x04:
0072         zc_map_key_clear(KEY_RADIO);
0073         break;
0074     /* report 4 */
0075     case 0x0d:
0076         zc_map_key_clear(KEY_PVR);
0077         break;
0078     case 0x25:
0079         zc_map_key_clear(KEY_TV);
0080         break;
0081     case 0x47:
0082         zc_map_key_clear(KEY_AUDIO);
0083         break;
0084     case 0x49:
0085         zc_map_key_clear(KEY_AUX);
0086         break;
0087     case 0x4a:
0088         zc_map_key_clear(KEY_VIDEO);
0089         break;
0090     case 0x48:
0091         zc_map_key_clear(KEY_DVD);
0092         break;
0093     case 0x24:
0094         zc_map_key_clear(KEY_MENU);
0095         break;
0096     case 0x32:
0097         zc_map_key_clear(KEY_TEXT);
0098         break;
0099     default:
0100         return 0;
0101     }
0102 
0103     for (i = 0; i < 4; i++)
0104         zc->last_key[i] = 0;
0105 
0106     return 1;
0107 }
0108 
0109 static int zc_raw_event(struct hid_device *hdev, struct hid_report *report,
0110      u8 *data, int size)
0111 {
0112     struct zc_device *zc = hid_get_drvdata(hdev);
0113     int ret = 0;
0114     unsigned key;
0115     unsigned short index;
0116 
0117     if (report->id == data[0]) {
0118 
0119         /* break keys */
0120         for (index = 0; index < 4; index++) {
0121             key = zc->last_key[index];
0122             if (key) {
0123                 input_event(zc->input_ep81, EV_KEY, key, 0);
0124                 zc->last_key[index] = 0;
0125             }
0126         }
0127 
0128         key = 0;
0129         switch (report->id) {
0130         case 0x02:
0131         case 0x03:
0132             switch (data[1]) {
0133             case 0x10:
0134                 key = KEY_MODE;
0135                 index = 0;
0136                 break;
0137             case 0x30:
0138                 key = KEY_SCREEN;
0139                 index = 1;
0140                 break;
0141             case 0x70:
0142                 key = KEY_INFO;
0143                 index = 2;
0144                 break;
0145             case 0x04:
0146                 key = KEY_RADIO;
0147                 index = 3;
0148                 break;
0149             }
0150 
0151             if (key) {
0152                 input_event(zc->input_ep81, EV_KEY, key, 1);
0153                 zc->last_key[index] = key;
0154             }
0155 
0156             ret = 1;
0157             break;
0158         }
0159     }
0160 
0161     return ret;
0162 }
0163 
0164 static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
0165 {
0166     int ret;
0167     struct zc_device *zc;
0168 
0169     zc = devm_kzalloc(&hdev->dev, sizeof(*zc), GFP_KERNEL);
0170     if (zc == NULL) {
0171         hid_err(hdev, "can't alloc descriptor\n");
0172         return -ENOMEM;
0173     }
0174 
0175     hid_set_drvdata(hdev, zc);
0176 
0177     ret = hid_parse(hdev);
0178     if (ret) {
0179         hid_err(hdev, "parse failed\n");
0180         return ret;
0181     }
0182 
0183     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0184     if (ret) {
0185         hid_err(hdev, "hw start failed\n");
0186         return ret;
0187     }
0188 
0189     return 0;
0190 }
0191 
0192 static const struct hid_device_id zc_devices[] = {
0193     { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
0194     { }
0195 };
0196 MODULE_DEVICE_TABLE(hid, zc_devices);
0197 
0198 static struct hid_driver zc_driver = {
0199     .name = "zydacron",
0200     .id_table = zc_devices,
0201     .report_fixup = zc_report_fixup,
0202     .input_mapping = zc_input_mapping,
0203     .raw_event = zc_raw_event,
0204     .probe = zc_probe,
0205 };
0206 module_hid_driver(zc_driver);
0207 
0208 MODULE_LICENSE("GPL");