diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/sony-laptop.c | 190 |
1 files changed, 140 insertions, 50 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 5300cad9cd7f..af69b3bd01da 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -142,45 +142,124 @@ struct sony_laptop_keypress { | |||
142 | int key; | 142 | int key; |
143 | }; | 143 | }; |
144 | 144 | ||
145 | /* Correspondance table between sonypi events and input layer events */ | 145 | /* Correspondance table between sonypi events |
146 | static struct { | 146 | * and input layer indexes in the keymap |
147 | int sonypiev; | 147 | */ |
148 | int inputev; | 148 | static int sony_laptop_input_index[] = { |
149 | } sony_laptop_inputkeys[] = { | 149 | -1, /* no event */ |
150 | { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, | 150 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ |
151 | { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, | 151 | -1, /* SONYPI_EVENT_JOGDIAL_UP */ |
152 | { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, | 152 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ |
153 | { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, | 153 | -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ |
154 | { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, | 154 | -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ |
155 | { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, | 155 | -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ |
156 | { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, | 156 | 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ |
157 | { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, | 157 | 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ |
158 | { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, | 158 | 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ |
159 | { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, | 159 | 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ |
160 | { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, | 160 | 4, /* SONYPI_EVENT_FNKEY_ESC */ |
161 | { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, | 161 | 5, /* SONYPI_EVENT_FNKEY_F1 */ |
162 | { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, | 162 | 6, /* SONYPI_EVENT_FNKEY_F2 */ |
163 | { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, | 163 | 7, /* SONYPI_EVENT_FNKEY_F3 */ |
164 | { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, | 164 | 8, /* SONYPI_EVENT_FNKEY_F4 */ |
165 | { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, | 165 | 9, /* SONYPI_EVENT_FNKEY_F5 */ |
166 | { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, | 166 | 10, /* SONYPI_EVENT_FNKEY_F6 */ |
167 | { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, | 167 | 11, /* SONYPI_EVENT_FNKEY_F7 */ |
168 | { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, | 168 | 12, /* SONYPI_EVENT_FNKEY_F8 */ |
169 | { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, | 169 | 13, /* SONYPI_EVENT_FNKEY_F9 */ |
170 | { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, | 170 | 14, /* SONYPI_EVENT_FNKEY_F10 */ |
171 | { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, | 171 | 15, /* SONYPI_EVENT_FNKEY_F11 */ |
172 | { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, | 172 | 16, /* SONYPI_EVENT_FNKEY_F12 */ |
173 | { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, | 173 | 17, /* SONYPI_EVENT_FNKEY_1 */ |
174 | { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, | 174 | 18, /* SONYPI_EVENT_FNKEY_2 */ |
175 | { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, | 175 | 19, /* SONYPI_EVENT_FNKEY_D */ |
176 | { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, | 176 | 20, /* SONYPI_EVENT_FNKEY_E */ |
177 | { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, | 177 | 21, /* SONYPI_EVENT_FNKEY_F */ |
178 | { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, | 178 | 22, /* SONYPI_EVENT_FNKEY_S */ |
179 | { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, | 179 | 23, /* SONYPI_EVENT_FNKEY_B */ |
180 | { SONYPI_EVENT_WIRELESS_ON, KEY_WLAN }, | 180 | 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ |
181 | { SONYPI_EVENT_WIRELESS_OFF, KEY_WLAN }, | 181 | 25, /* SONYPI_EVENT_PKEY_P1 */ |
182 | { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, | 182 | 26, /* SONYPI_EVENT_PKEY_P2 */ |
183 | { 0, 0 }, | 183 | 27, /* SONYPI_EVENT_PKEY_P3 */ |
184 | 28, /* SONYPI_EVENT_BACK_PRESSED */ | ||
185 | -1, /* SONYPI_EVENT_LID_CLOSED */ | ||
186 | -1, /* SONYPI_EVENT_LID_OPENED */ | ||
187 | 29, /* SONYPI_EVENT_BLUETOOTH_ON */ | ||
188 | 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ | ||
189 | 31, /* SONYPI_EVENT_HELP_PRESSED */ | ||
190 | 32, /* SONYPI_EVENT_FNKEY_ONLY */ | ||
191 | 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ | ||
192 | 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ | ||
193 | 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ | ||
194 | 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ | ||
195 | 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ | ||
196 | 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ | ||
197 | 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ | ||
198 | 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ | ||
199 | 41, /* SONYPI_EVENT_ZOOM_PRESSED */ | ||
200 | 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ | ||
201 | 43, /* SONYPI_EVENT_MEYE_FACE */ | ||
202 | 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ | ||
203 | 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ | ||
204 | 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ | ||
205 | -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ | ||
206 | -1, /* SONYPI_EVENT_BATTERY_INSERT */ | ||
207 | -1, /* SONYPI_EVENT_BATTERY_REMOVE */ | ||
208 | -1, /* SONYPI_EVENT_FNKEY_RELEASED */ | ||
209 | 47, /* SONYPI_EVENT_WIRELESS_ON */ | ||
210 | 48, /* SONYPI_EVENT_WIRELESS_OFF */ | ||
211 | }; | ||
212 | |||
213 | static int sony_laptop_input_keycode_map[] = { | ||
214 | KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */ | ||
215 | KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */ | ||
216 | KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ | ||
217 | KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ | ||
218 | KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */ | ||
219 | KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */ | ||
220 | KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */ | ||
221 | KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */ | ||
222 | KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */ | ||
223 | KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */ | ||
224 | KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */ | ||
225 | KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */ | ||
226 | KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */ | ||
227 | KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */ | ||
228 | KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ | ||
229 | KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ | ||
230 | KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ | ||
231 | KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ | ||
232 | KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ | ||
233 | KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ | ||
234 | KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ | ||
235 | KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ | ||
236 | KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */ | ||
237 | KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */ | ||
238 | KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */ | ||
239 | KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */ | ||
240 | KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */ | ||
241 | KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */ | ||
242 | KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */ | ||
243 | KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */ | ||
244 | KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */ | ||
245 | KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */ | ||
246 | KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */ | ||
247 | KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ | ||
248 | KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */ | ||
249 | KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ | ||
250 | KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ | ||
251 | KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ | ||
252 | KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */ | ||
253 | KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ | ||
254 | KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ | ||
255 | KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */ | ||
256 | BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */ | ||
257 | KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */ | ||
258 | KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */ | ||
259 | KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */ | ||
260 | KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ | ||
261 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ | ||
262 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ | ||
184 | }; | 263 | }; |
185 | 264 | ||
186 | /* release buttons after a short delay if pressed */ | 265 | /* release buttons after a short delay if pressed */ |
@@ -204,7 +283,6 @@ static void sony_laptop_report_input_event(u8 event) | |||
204 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; | 283 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; |
205 | struct input_dev *key_dev = sony_laptop_input.key_dev; | 284 | struct input_dev *key_dev = sony_laptop_input.key_dev; |
206 | struct sony_laptop_keypress kp = { NULL }; | 285 | struct sony_laptop_keypress kp = { NULL }; |
207 | int i; | ||
208 | 286 | ||
209 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { | 287 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { |
210 | /* Nothing, not all VAIOs generate this event */ | 288 | /* Nothing, not all VAIOs generate this event */ |
@@ -233,17 +311,22 @@ static void sony_laptop_report_input_event(u8 event) | |||
233 | break; | 311 | break; |
234 | 312 | ||
235 | default: | 313 | default: |
236 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 314 | if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { |
237 | if (event == sony_laptop_inputkeys[i].sonypiev) { | 315 | dprintk("sony_laptop_report_input_event, event not known: %d\n", event); |
316 | break; | ||
317 | } | ||
318 | if (sony_laptop_input_index[event] != -1) { | ||
319 | kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]]; | ||
320 | if (kp.key != KEY_UNKNOWN) | ||
238 | kp.dev = key_dev; | 321 | kp.dev = key_dev; |
239 | kp.key = sony_laptop_inputkeys[i].inputev; | 322 | } |
240 | break; | ||
241 | } | ||
242 | break; | 323 | break; |
243 | } | 324 | } |
244 | 325 | ||
245 | if (kp.dev) { | 326 | if (kp.dev) { |
246 | input_report_key(kp.dev, kp.key, 1); | 327 | input_report_key(kp.dev, kp.key, 1); |
328 | /* we emit the scancode so we can always remap the key */ | ||
329 | input_event(kp.dev, EV_MSC, MSC_SCAN, event); | ||
247 | input_sync(kp.dev); | 330 | input_sync(kp.dev); |
248 | kfifo_put(sony_laptop_input.fifo, | 331 | kfifo_put(sony_laptop_input.fifo, |
249 | (unsigned char *)&kp, sizeof(kp)); | 332 | (unsigned char *)&kp, sizeof(kp)); |
@@ -298,11 +381,18 @@ static int sony_laptop_setup_input(void) | |||
298 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; | 381 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; |
299 | 382 | ||
300 | /* Initialize the Input Drivers: special keys */ | 383 | /* Initialize the Input Drivers: special keys */ |
301 | key_dev->evbit[0] = BIT(EV_KEY); | 384 | set_bit(EV_KEY, key_dev->evbit); |
302 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 385 | set_bit(EV_MSC, key_dev->evbit); |
303 | if (sony_laptop_inputkeys[i].inputev) | 386 | set_bit(MSC_SCAN, key_dev->mscbit); |
304 | set_bit(sony_laptop_inputkeys[i].inputev, | 387 | key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); |
305 | key_dev->keybit); | 388 | key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); |
389 | key_dev->keycode = &sony_laptop_input_keycode_map; | ||
390 | for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { | ||
391 | if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { | ||
392 | set_bit(sony_laptop_input_keycode_map[i], | ||
393 | key_dev->keybit); | ||
394 | } | ||
395 | } | ||
306 | 396 | ||
307 | error = input_register_device(key_dev); | 397 | error = input_register_device(key_dev); |
308 | if (error) | 398 | if (error) |