0001
0002
0003
0004
0005
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
0025
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
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
0071 case 0x04:
0072 zc_map_key_clear(KEY_RADIO);
0073 break;
0074
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
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");