aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-input.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 10:59:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 10:59:01 -0400
commit3a99c6319064af3f2e18eb929f638d555dbf7a62 (patch)
treee611927f41142123dc8efed7e07a3a91151edb01 /drivers/hid/hid-input.c
parent1dfd166e93f98892aa4427069a23ed73259983c8 (diff)
parent49327ad2bbbaf1945d5ba431522201574219d150 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (75 commits) Input: wacom - specify Cinitq supported tools Input: ab8500-ponkey - fix IRQ freeing in error path Input: adp5588-keys - use more obvious i2c_device_id name string Input: ad7877 - switch to using threaded IRQ Input: ad7877 - use attribute group to control visibility of attributes Input: serio - add support for PS2Mult multiplexer protocol Input: wacom - properly enable runtime PM Input: ad7877 - filter events where pressure is beyond the maximum Input: ad7877 - implement EV_KEY:BTN_TOUCH reporting Input: ad7877 - implement specified chip select behavior Input: hp680_ts_input - use cancel_delayed_work_sync() Input: mousedev - correct lockdep annotation Input: ads7846 - switch to using threaded IRQ Input: serio - support multiple child devices per single parent Input: synaptics - simplify pass-through port handling Input: add ROHM BU21013 touch panel controller support Input: omap4-keypad - wake-up on events & long presses Input: omap4-keypad - fix interrupt line configuration Input: omap4-keypad - SYSCONFIG register configuration Input: omap4-keypad - use platform device helpers ...
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r--drivers/hid/hid-input.c108
1 files changed, 75 insertions, 33 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 834ef47b76d6..bb0b3659437b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -68,39 +68,52 @@ static const struct {
68#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ 68#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
69 &max, EV_KEY, (c)) 69 &max, EV_KEY, (c))
70 70
71static inline int match_scancode(unsigned int code, unsigned int scancode) 71static bool match_scancode(struct hid_usage *usage,
72 unsigned int cur_idx, unsigned int scancode)
72{ 73{
73 if (scancode == 0) 74 return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
74 return 1;
75
76 return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
77} 75}
78 76
79static inline int match_keycode(unsigned int code, unsigned int keycode) 77static bool match_keycode(struct hid_usage *usage,
78 unsigned int cur_idx, unsigned int keycode)
80{ 79{
81 if (keycode == 0) 80 /*
82 return 1; 81 * We should exclude unmapped usages when doing lookup by keycode.
82 */
83 return (usage->type == EV_KEY && usage->code == keycode);
84}
83 85
84 return code == keycode; 86static bool match_index(struct hid_usage *usage,
87 unsigned int cur_idx, unsigned int idx)
88{
89 return cur_idx == idx;
85} 90}
86 91
92typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
93 unsigned int cur_idx, unsigned int val);
94
87static struct hid_usage *hidinput_find_key(struct hid_device *hid, 95static struct hid_usage *hidinput_find_key(struct hid_device *hid,
88 unsigned int scancode, 96 hid_usage_cmp_t match,
89 unsigned int keycode) 97 unsigned int value,
98 unsigned int *usage_idx)
90{ 99{
91 int i, j, k; 100 unsigned int i, j, k, cur_idx = 0;
92 struct hid_report *report; 101 struct hid_report *report;
93 struct hid_usage *usage; 102 struct hid_usage *usage;
94 103
95 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { 104 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
96 list_for_each_entry(report, &hid->report_enum[k].report_list, list) { 105 list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
97 for (i = 0; i < report->maxfield; i++) { 106 for (i = 0; i < report->maxfield; i++) {
98 for ( j = 0; j < report->field[i]->maxusage; j++) { 107 for (j = 0; j < report->field[i]->maxusage; j++) {
99 usage = report->field[i]->usage + j; 108 usage = report->field[i]->usage + j;
100 if (usage->type == EV_KEY && 109 if (usage->type == EV_KEY || usage->type == 0) {
101 match_scancode(usage->hid, scancode) && 110 if (match(usage, cur_idx, value)) {
102 match_keycode(usage->code, keycode)) 111 if (usage_idx)
103 return usage; 112 *usage_idx = cur_idx;
113 return usage;
114 }
115 cur_idx++;
116 }
104 } 117 }
105 } 118 }
106 } 119 }
@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
108 return NULL; 121 return NULL;
109} 122}
110 123
124static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
125 const struct input_keymap_entry *ke,
126 unsigned int *index)
127{
128 struct hid_usage *usage;
129 unsigned int scancode;
130
131 if (ke->flags & INPUT_KEYMAP_BY_INDEX)
132 usage = hidinput_find_key(hid, match_index, ke->index, index);
133 else if (input_scancode_to_scalar(ke, &scancode) == 0)
134 usage = hidinput_find_key(hid, match_scancode, scancode, index);
135 else
136 usage = NULL;
137
138 return usage;
139}
140
111static int hidinput_getkeycode(struct input_dev *dev, 141static int hidinput_getkeycode(struct input_dev *dev,
112 unsigned int scancode, unsigned int *keycode) 142 struct input_keymap_entry *ke)
113{ 143{
114 struct hid_device *hid = input_get_drvdata(dev); 144 struct hid_device *hid = input_get_drvdata(dev);
115 struct hid_usage *usage; 145 struct hid_usage *usage;
146 unsigned int scancode, index;
116 147
117 usage = hidinput_find_key(hid, scancode, 0); 148 usage = hidinput_locate_usage(hid, ke, &index);
118 if (usage) { 149 if (usage) {
119 *keycode = usage->code; 150 ke->keycode = usage->type == EV_KEY ?
151 usage->code : KEY_RESERVED;
152 ke->index = index;
153 scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
154 ke->len = sizeof(scancode);
155 memcpy(ke->scancode, &scancode, sizeof(scancode));
120 return 0; 156 return 0;
121 } 157 }
158
122 return -EINVAL; 159 return -EINVAL;
123} 160}
124 161
125static int hidinput_setkeycode(struct input_dev *dev, 162static int hidinput_setkeycode(struct input_dev *dev,
126 unsigned int scancode, unsigned int keycode) 163 const struct input_keymap_entry *ke,
164 unsigned int *old_keycode)
127{ 165{
128 struct hid_device *hid = input_get_drvdata(dev); 166 struct hid_device *hid = input_get_drvdata(dev);
129 struct hid_usage *usage; 167 struct hid_usage *usage;
130 int old_keycode;
131 168
132 usage = hidinput_find_key(hid, scancode, 0); 169 usage = hidinput_locate_usage(hid, ke, NULL);
133 if (usage) { 170 if (usage) {
134 old_keycode = usage->code; 171 *old_keycode = usage->type == EV_KEY ?
135 usage->code = keycode; 172 usage->code : KEY_RESERVED;
173 usage->code = ke->keycode;
136 174
137 clear_bit(old_keycode, dev->keybit); 175 clear_bit(*old_keycode, dev->keybit);
138 set_bit(usage->code, dev->keybit); 176 set_bit(usage->code, dev->keybit);
139 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); 177 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
140 /* Set the keybit for the old keycode if the old keycode is used 178 usage->code, usage->hid);
141 * by another key */ 179
142 if (hidinput_find_key (hid, 0, old_keycode)) 180 /*
143 set_bit(old_keycode, dev->keybit); 181 * Set the keybit for the old keycode if the old keycode is used
182 * by another key
183 */
184 if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
185 set_bit(*old_keycode, dev->keybit);
144 186
145 return 0; 187 return 0;
146 } 188 }
@@ -835,8 +877,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
835 hid->ll_driver->hidinput_input_event; 877 hid->ll_driver->hidinput_input_event;
836 input_dev->open = hidinput_open; 878 input_dev->open = hidinput_open;
837 input_dev->close = hidinput_close; 879 input_dev->close = hidinput_close;
838 input_dev->setkeycode = hidinput_setkeycode; 880 input_dev->setkeycode_new = hidinput_setkeycode;
839 input_dev->getkeycode = hidinput_getkeycode; 881 input_dev->getkeycode_new = hidinput_getkeycode;
840 882
841 input_dev->name = hid->name; 883 input_dev->name = hid->name;
842 input_dev->phys = hid->phys; 884 input_dev->phys = hid->phys;