diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-input.c | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6c03dcc5760a..b12c07e64fbd 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -68,39 +68,49 @@ 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 | ||
71 | static inline int match_scancode(unsigned int code, unsigned int scancode) | 71 | static 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 | ||
79 | static inline int match_keycode(unsigned int code, unsigned int keycode) | 77 | static bool match_keycode(struct hid_usage *usage, |
78 | unsigned int cur_idx, unsigned int keycode) | ||
80 | { | 79 | { |
81 | if (keycode == 0) | 80 | return usage->code == keycode; |
82 | return 1; | 81 | } |
83 | 82 | ||
84 | return code == keycode; | 83 | static bool match_index(struct hid_usage *usage, |
84 | unsigned int cur_idx, unsigned int idx) | ||
85 | { | ||
86 | return cur_idx == idx; | ||
85 | } | 87 | } |
86 | 88 | ||
89 | typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage, | ||
90 | unsigned int cur_idx, unsigned int val); | ||
91 | |||
87 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, | 92 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, |
88 | unsigned int scancode, | 93 | hid_usage_cmp_t match, |
89 | unsigned int keycode) | 94 | unsigned int value, |
95 | unsigned int *usage_idx) | ||
90 | { | 96 | { |
91 | int i, j, k; | 97 | unsigned int i, j, k, cur_idx = 0; |
92 | struct hid_report *report; | 98 | struct hid_report *report; |
93 | struct hid_usage *usage; | 99 | struct hid_usage *usage; |
94 | 100 | ||
95 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | 101 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { |
96 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 102 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
97 | for (i = 0; i < report->maxfield; i++) { | 103 | for (i = 0; i < report->maxfield; i++) { |
98 | for ( j = 0; j < report->field[i]->maxusage; j++) { | 104 | for (j = 0; j < report->field[i]->maxusage; j++) { |
99 | usage = report->field[i]->usage + j; | 105 | usage = report->field[i]->usage + j; |
100 | if (usage->type == EV_KEY && | 106 | if (usage->type == EV_KEY) { |
101 | match_scancode(usage->hid, scancode) && | 107 | if (match(usage, cur_idx, value)) { |
102 | match_keycode(usage->code, keycode)) | 108 | if (usage_idx) |
103 | return usage; | 109 | *usage_idx = cur_idx; |
110 | return usage; | ||
111 | } | ||
112 | cur_idx++; | ||
113 | } | ||
104 | } | 114 | } |
105 | } | 115 | } |
106 | } | 116 | } |
@@ -108,39 +118,66 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, | |||
108 | return NULL; | 118 | return NULL; |
109 | } | 119 | } |
110 | 120 | ||
121 | static struct hid_usage *hidinput_locate_usage(struct hid_device *hid, | ||
122 | const struct input_keymap_entry *ke, | ||
123 | unsigned int *index) | ||
124 | { | ||
125 | struct hid_usage *usage; | ||
126 | unsigned int scancode; | ||
127 | |||
128 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) | ||
129 | usage = hidinput_find_key(hid, match_index, ke->index, index); | ||
130 | else if (input_scancode_to_scalar(ke, &scancode) == 0) | ||
131 | usage = hidinput_find_key(hid, match_scancode, scancode, index); | ||
132 | else | ||
133 | usage = NULL; | ||
134 | |||
135 | return usage; | ||
136 | } | ||
137 | |||
111 | static int hidinput_getkeycode(struct input_dev *dev, | 138 | static int hidinput_getkeycode(struct input_dev *dev, |
112 | unsigned int scancode, unsigned int *keycode) | 139 | struct input_keymap_entry *ke) |
113 | { | 140 | { |
114 | struct hid_device *hid = input_get_drvdata(dev); | 141 | struct hid_device *hid = input_get_drvdata(dev); |
115 | struct hid_usage *usage; | 142 | struct hid_usage *usage; |
143 | unsigned int scancode, index; | ||
116 | 144 | ||
117 | usage = hidinput_find_key(hid, scancode, 0); | 145 | usage = hidinput_locate_usage(hid, ke, &index); |
118 | if (usage) { | 146 | if (usage) { |
119 | *keycode = usage->code; | 147 | ke->keycode = usage->code; |
148 | ke->index = index; | ||
149 | scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE); | ||
150 | ke->len = sizeof(scancode); | ||
151 | memcpy(ke->scancode, &scancode, sizeof(scancode)); | ||
120 | return 0; | 152 | return 0; |
121 | } | 153 | } |
154 | |||
122 | return -EINVAL; | 155 | return -EINVAL; |
123 | } | 156 | } |
124 | 157 | ||
125 | static int hidinput_setkeycode(struct input_dev *dev, | 158 | static int hidinput_setkeycode(struct input_dev *dev, |
126 | unsigned int scancode, unsigned int keycode) | 159 | const struct input_keymap_entry *ke, |
160 | unsigned int *old_keycode) | ||
127 | { | 161 | { |
128 | struct hid_device *hid = input_get_drvdata(dev); | 162 | struct hid_device *hid = input_get_drvdata(dev); |
129 | struct hid_usage *usage; | 163 | struct hid_usage *usage; |
130 | int old_keycode; | ||
131 | 164 | ||
132 | usage = hidinput_find_key(hid, scancode, 0); | 165 | usage = hidinput_locate_usage(hid, ke, NULL); |
133 | if (usage) { | 166 | if (usage) { |
134 | old_keycode = usage->code; | 167 | *old_keycode = usage->code; |
135 | usage->code = keycode; | 168 | usage->code = ke->keycode; |
136 | 169 | ||
137 | clear_bit(old_keycode, dev->keybit); | 170 | clear_bit(*old_keycode, dev->keybit); |
138 | set_bit(usage->code, dev->keybit); | 171 | set_bit(usage->code, dev->keybit); |
139 | dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); | 172 | 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 | 173 | usage->code, usage->hid); |
141 | * by another key */ | 174 | |
142 | if (hidinput_find_key (hid, 0, old_keycode)) | 175 | /* |
143 | set_bit(old_keycode, dev->keybit); | 176 | * Set the keybit for the old keycode if the old keycode is used |
177 | * by another key | ||
178 | */ | ||
179 | if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL)) | ||
180 | set_bit(*old_keycode, dev->keybit); | ||
144 | 181 | ||
145 | return 0; | 182 | return 0; |
146 | } | 183 | } |
@@ -748,8 +785,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
748 | hid->ll_driver->hidinput_input_event; | 785 | hid->ll_driver->hidinput_input_event; |
749 | input_dev->open = hidinput_open; | 786 | input_dev->open = hidinput_open; |
750 | input_dev->close = hidinput_close; | 787 | input_dev->close = hidinput_close; |
751 | input_dev->setkeycode = hidinput_setkeycode; | 788 | input_dev->setkeycode_new = hidinput_setkeycode; |
752 | input_dev->getkeycode = hidinput_getkeycode; | 789 | input_dev->getkeycode_new = hidinput_getkeycode; |
753 | 790 | ||
754 | input_dev->name = hid->name; | 791 | input_dev->name = hid->name; |
755 | input_dev->phys = hid->phys; | 792 | input_dev->phys = hid->phys; |