| Bruno Premont | 711a680 | 2009-07-13 14:19:58 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | * HID driver for TwinHan IR remote control | 
|  | 3 | * | 
|  | 4 | * Based on hid-gyration.c | 
|  | 5 | * | 
|  | 6 | * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> | 
|  | 7 | */ | 
|  | 8 |  | 
|  | 9 | /* | 
|  | 10 | * This program is free software; you can redistribute it and/or modify it | 
|  | 11 | * under the terms of the GNU General Public License as published by the Free | 
|  | 12 | * Software Foundation; either version 2 of the License. | 
|  | 13 | */ | 
|  | 14 |  | 
|  | 15 | #include <linux/device.h> | 
|  | 16 | #include <linux/input.h> | 
|  | 17 | #include <linux/hid.h> | 
|  | 18 | #include <linux/module.h> | 
|  | 19 |  | 
|  | 20 | #include "hid-ids.h" | 
|  | 21 |  | 
|  | 22 | /*	Remote control key layout + listing: | 
|  | 23 | * | 
|  | 24 | * 	Full Screen                              Power | 
|  | 25 | *	KEY_SCREEN                          KEY_POWER2 | 
|  | 26 | * | 
|  | 27 | *	1                     2                      3 | 
|  | 28 | *	KEY_NUMERIC_1   KEY_NUMERIC_2    KEY_NUMERIC_3 | 
|  | 29 | * | 
|  | 30 | *	4                     5                      6 | 
|  | 31 | *	KEY_NUMERIC_4   KEY_NUMERIC_5    KEY_NUMERIC_6 | 
|  | 32 | * | 
|  | 33 | *	7                     8                      9 | 
|  | 34 | *	KEY_NUMERIC_7   KEY_NUMERIC_8    KEY_NUMERIC_9 | 
|  | 35 | * | 
|  | 36 | *	REC                   0               Favorite | 
|  | 37 | *	KEY_RECORD      KEY_NUMERIC_0    KEY_FAVORITES | 
|  | 38 | * | 
|  | 39 | *	Rewind                                 Forward | 
|  | 40 | *	KEY_REWIND           CH+           KEY_FORWARD | 
|  | 41 | *	               KEY_CHANNELUP | 
|  | 42 | * | 
|  | 43 | *	VOL-                  >                   VOL+ | 
|  | 44 | *	KEY_VOLUMEDOWN    KEY_PLAY        KEY_VOLUMEUP | 
|  | 45 | * | 
|  | 46 | *	                     CH- | 
|  | 47 | *	              KEY_CHANNELDOWN | 
|  | 48 | *	Recall                                    Stop | 
|  | 49 | *	KEY_RESTART                           KEY_STOP | 
|  | 50 | * | 
|  | 51 | *	Timeshift/Pause     Mute                Cancel | 
|  | 52 | *	KEY_PAUSE         KEY_MUTE          KEY_CANCEL | 
|  | 53 | * | 
|  | 54 | *	Capture            Preview                 EPG | 
|  | 55 | *	KEY_PRINT        KEY_PROGRAM           KEY_EPG | 
|  | 56 | * | 
|  | 57 | *	Record List          Tab              Teletext | 
|  | 58 | *	KEY_LIST            KEY_TAB           KEY_TEXT | 
|  | 59 | */ | 
|  | 60 |  | 
|  | 61 | #define th_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \ | 
|  | 62 | EV_KEY, (c)) | 
|  | 63 | static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 
|  | 64 | struct hid_field *field, struct hid_usage *usage, | 
|  | 65 | unsigned long **bit, int *max) | 
|  | 66 | { | 
|  | 67 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD) | 
|  | 68 | return 0; | 
|  | 69 |  | 
|  | 70 | switch (usage->hid & HID_USAGE) { | 
|  | 71 | /* Map all keys from Twinhan Remote */ | 
|  | 72 | case 0x004: th_map_key_clear(KEY_TEXT);         break; | 
|  | 73 | case 0x006: th_map_key_clear(KEY_RESTART);      break; | 
|  | 74 | case 0x008: th_map_key_clear(KEY_EPG);          break; | 
|  | 75 | case 0x00c: th_map_key_clear(KEY_REWIND);       break; | 
|  | 76 | case 0x00e: th_map_key_clear(KEY_PROGRAM);      break; | 
|  | 77 | case 0x00f: th_map_key_clear(KEY_LIST);         break; | 
|  | 78 | case 0x010: th_map_key_clear(KEY_MUTE);         break; | 
|  | 79 | case 0x011: th_map_key_clear(KEY_FORWARD);      break; | 
|  | 80 | case 0x013: th_map_key_clear(KEY_PRINT);        break; | 
|  | 81 | case 0x017: th_map_key_clear(KEY_PAUSE);        break; | 
|  | 82 | case 0x019: th_map_key_clear(KEY_FAVORITES);    break; | 
|  | 83 | case 0x01d: th_map_key_clear(KEY_SCREEN);       break; | 
|  | 84 | case 0x01e: th_map_key_clear(KEY_NUMERIC_1);    break; | 
|  | 85 | case 0x01f: th_map_key_clear(KEY_NUMERIC_2);    break; | 
|  | 86 | case 0x020: th_map_key_clear(KEY_NUMERIC_3);    break; | 
|  | 87 | case 0x021: th_map_key_clear(KEY_NUMERIC_4);    break; | 
|  | 88 | case 0x022: th_map_key_clear(KEY_NUMERIC_5);    break; | 
|  | 89 | case 0x023: th_map_key_clear(KEY_NUMERIC_6);    break; | 
|  | 90 | case 0x024: th_map_key_clear(KEY_NUMERIC_7);    break; | 
|  | 91 | case 0x025: th_map_key_clear(KEY_NUMERIC_8);    break; | 
|  | 92 | case 0x026: th_map_key_clear(KEY_NUMERIC_9);    break; | 
|  | 93 | case 0x027: th_map_key_clear(KEY_NUMERIC_0);    break; | 
|  | 94 | case 0x028: th_map_key_clear(KEY_PLAY);         break; | 
|  | 95 | case 0x029: th_map_key_clear(KEY_CANCEL);       break; | 
|  | 96 | case 0x02b: th_map_key_clear(KEY_TAB);          break; | 
|  | 97 | /* Power       = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */ | 
|  | 98 | case 0x03f: th_map_key_clear(KEY_POWER2);       break; | 
|  | 99 | case 0x04a: th_map_key_clear(KEY_RECORD);       break; | 
|  | 100 | case 0x04b: th_map_key_clear(KEY_CHANNELUP);    break; | 
|  | 101 | case 0x04d: th_map_key_clear(KEY_STOP);         break; | 
|  | 102 | case 0x04e: th_map_key_clear(KEY_CHANNELDOWN);  break; | 
|  | 103 | /* Volume down = 0x0e1 + 0x051                 */ | 
|  | 104 | case 0x051: th_map_key_clear(KEY_VOLUMEDOWN);   break; | 
|  | 105 | /* Volume up   = 0x0e1 + 0x052                 */ | 
|  | 106 | case 0x052: th_map_key_clear(KEY_VOLUMEUP);     break; | 
|  | 107 | /* Kill the extra keys used for multi-key "power" and "volume" keys | 
|  | 108 | * as well as continuously to release CTRL,ALT,META,... keys */ | 
|  | 109 | case 0x0e0: | 
|  | 110 | case 0x0e1: | 
|  | 111 | case 0x0e2: | 
|  | 112 | case 0x0e3: | 
|  | 113 | case 0x0e4: | 
|  | 114 | case 0x0e5: | 
|  | 115 | case 0x0e6: | 
|  | 116 | case 0x0e7: | 
|  | 117 | default: | 
|  | 118 | return -1; | 
|  | 119 | } | 
|  | 120 | return 1; | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | static const struct hid_device_id twinhan_devices[] = { | 
|  | 124 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | 
|  | 125 | { } | 
|  | 126 | }; | 
|  | 127 | MODULE_DEVICE_TABLE(hid, twinhan_devices); | 
|  | 128 |  | 
|  | 129 | static struct hid_driver twinhan_driver = { | 
|  | 130 | .name = "twinhan", | 
|  | 131 | .id_table = twinhan_devices, | 
|  | 132 | .input_mapping = twinhan_input_mapping, | 
|  | 133 | }; | 
|  | 134 |  | 
| Peter Huewe | fa59530 | 2009-09-29 03:24:55 +0200 | [diff] [blame] | 135 | static int __init twinhan_init(void) | 
| Bruno Premont | 711a680 | 2009-07-13 14:19:58 +0200 | [diff] [blame] | 136 | { | 
|  | 137 | return hid_register_driver(&twinhan_driver); | 
|  | 138 | } | 
|  | 139 |  | 
| Peter Huewe | fa59530 | 2009-09-29 03:24:55 +0200 | [diff] [blame] | 140 | static void __exit twinhan_exit(void) | 
| Bruno Premont | 711a680 | 2009-07-13 14:19:58 +0200 | [diff] [blame] | 141 | { | 
|  | 142 | hid_unregister_driver(&twinhan_driver); | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | module_init(twinhan_init); | 
|  | 146 | module_exit(twinhan_exit); | 
|  | 147 | MODULE_LICENSE("GPL"); |