aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/sony-laptop.c190
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
146static struct { 146 * and input layer indexes in the keymap
147 int sonypiev; 147 */
148 int inputev; 148static 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
213static 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)