1711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont/* 2711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * HID driver for TwinHan IR remote control 3711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 4711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Based on hid-gyration.c 5711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 6d36b691077dc59c74efec0d54ed21b86f7a2a21aAl Viro * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> 7711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont */ 8711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 9711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont/* 10711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * This program is free software; you can redistribute it and/or modify it 11711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * under the terms of the GNU General Public License as published by the Free 12711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Software Foundation; either version 2 of the License. 13711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont */ 14711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 15711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#include <linux/device.h> 16711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#include <linux/input.h> 17711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#include <linux/hid.h> 18711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#include <linux/module.h> 19711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 20711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#include "hid-ids.h" 21711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 22711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont/* Remote control key layout + listing: 23711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 24711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Full Screen Power 25711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_SCREEN KEY_POWER2 26711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 27711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 1 2 3 28711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_NUMERIC_1 KEY_NUMERIC_2 KEY_NUMERIC_3 29711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 30711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 4 5 6 31711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_NUMERIC_4 KEY_NUMERIC_5 KEY_NUMERIC_6 32711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 33711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 7 8 9 34711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_NUMERIC_7 KEY_NUMERIC_8 KEY_NUMERIC_9 35711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 36711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * REC 0 Favorite 37711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_RECORD KEY_NUMERIC_0 KEY_FAVORITES 38711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 39711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Rewind Forward 40711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_REWIND CH+ KEY_FORWARD 41711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_CHANNELUP 42711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 43711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * VOL- > VOL+ 44711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP 45711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 46711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * CH- 47711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_CHANNELDOWN 48711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Recall Stop 49711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_RESTART KEY_STOP 50711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 51711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Timeshift/Pause Mute Cancel 52711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_PAUSE KEY_MUTE KEY_CANCEL 53711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 54711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Capture Preview EPG 55711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_PRINT KEY_PROGRAM KEY_EPG 56711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * 57711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * Record List Tab Teletext 58711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * KEY_LIST KEY_TAB KEY_TEXT 59711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont */ 60711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 61711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont#define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ 62711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont EV_KEY, (c)) 63711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premontstatic int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi, 64711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont struct hid_field *field, struct hid_usage *usage, 65711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont unsigned long **bit, int *max) 66711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont{ 67711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD) 68711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont return 0; 69711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 70711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont switch (usage->hid & HID_USAGE) { 71711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont /* Map all keys from Twinhan Remote */ 72711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x004: th_map_key_clear(KEY_TEXT); break; 73711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x006: th_map_key_clear(KEY_RESTART); break; 74711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x008: th_map_key_clear(KEY_EPG); break; 75711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x00c: th_map_key_clear(KEY_REWIND); break; 76711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x00e: th_map_key_clear(KEY_PROGRAM); break; 77711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x00f: th_map_key_clear(KEY_LIST); break; 78711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x010: th_map_key_clear(KEY_MUTE); break; 79711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x011: th_map_key_clear(KEY_FORWARD); break; 80711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x013: th_map_key_clear(KEY_PRINT); break; 81711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x017: th_map_key_clear(KEY_PAUSE); break; 82711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x019: th_map_key_clear(KEY_FAVORITES); break; 83711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x01d: th_map_key_clear(KEY_SCREEN); break; 84711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x01e: th_map_key_clear(KEY_NUMERIC_1); break; 85711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x01f: th_map_key_clear(KEY_NUMERIC_2); break; 86711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x020: th_map_key_clear(KEY_NUMERIC_3); break; 87711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x021: th_map_key_clear(KEY_NUMERIC_4); break; 88711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x022: th_map_key_clear(KEY_NUMERIC_5); break; 89711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x023: th_map_key_clear(KEY_NUMERIC_6); break; 90711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x024: th_map_key_clear(KEY_NUMERIC_7); break; 91711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x025: th_map_key_clear(KEY_NUMERIC_8); break; 92711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x026: th_map_key_clear(KEY_NUMERIC_9); break; 93711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x027: th_map_key_clear(KEY_NUMERIC_0); break; 94711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x028: th_map_key_clear(KEY_PLAY); break; 95711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x029: th_map_key_clear(KEY_CANCEL); break; 96711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x02b: th_map_key_clear(KEY_TAB); break; 97711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */ 98711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x03f: th_map_key_clear(KEY_POWER2); break; 99711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x04a: th_map_key_clear(KEY_RECORD); break; 100711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x04b: th_map_key_clear(KEY_CHANNELUP); break; 101711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x04d: th_map_key_clear(KEY_STOP); break; 102711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break; 103711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont /* Volume down = 0x0e1 + 0x051 */ 104711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break; 105711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont /* Volume up = 0x0e1 + 0x052 */ 106711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x052: th_map_key_clear(KEY_VOLUMEUP); break; 107711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont /* Kill the extra keys used for multi-key "power" and "volume" keys 108711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont * as well as continuously to release CTRL,ALT,META,... keys */ 109711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e0: 110711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e1: 111711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e2: 112711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e3: 113711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e4: 114711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e5: 115711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e6: 116711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont case 0x0e7: 117711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont default: 118711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont return -1; 119711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont } 120711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont return 1; 121711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont} 122711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 123711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premontstatic const struct hid_device_id twinhan_devices[] = { 124711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, 125711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont { } 126711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont}; 127711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno PremontMODULE_DEVICE_TABLE(hid, twinhan_devices); 128711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 129711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premontstatic struct hid_driver twinhan_driver = { 130711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont .name = "twinhan", 131711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont .id_table = twinhan_devices, 132711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont .input_mapping = twinhan_input_mapping, 133711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont}; 134f425458eafd51b6b5ab64f407922e1198c567cb2H Hartley Sweetenmodule_hid_driver(twinhan_driver); 135711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno Premont 136711a680e35059bc5c7c28d3c4bd0bebd3b7bb6eeBruno PremontMODULE_LICENSE("GPL"); 137