diff options
| -rw-r--r-- | drivers/input/mouse/alps.c | 190 | ||||
| -rw-r--r-- | drivers/input/mouse/alps.h | 14 |
2 files changed, 151 insertions, 53 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index d164690bfdf7..a4d69ef0f846 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -165,8 +165,7 @@ static bool alps_is_valid_first_byte(struct alps_data *priv, | |||
| 165 | return (data & priv->mask0) == priv->byte0; | 165 | return (data & priv->mask0) == priv->byte0; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | static void alps_report_buttons(struct psmouse *psmouse, | 168 | static void alps_report_buttons(struct input_dev *dev1, struct input_dev *dev2, |
| 169 | struct input_dev *dev1, struct input_dev *dev2, | ||
| 170 | int left, int right, int middle) | 169 | int left, int right, int middle) |
| 171 | { | 170 | { |
| 172 | struct input_dev *dev; | 171 | struct input_dev *dev; |
| @@ -176,20 +175,21 @@ static void alps_report_buttons(struct psmouse *psmouse, | |||
| 176 | * other device (dev2) then this event should be also | 175 | * other device (dev2) then this event should be also |
| 177 | * sent through that device. | 176 | * sent through that device. |
| 178 | */ | 177 | */ |
| 179 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; | 178 | dev = (dev2 && test_bit(BTN_LEFT, dev2->key)) ? dev2 : dev1; |
| 180 | input_report_key(dev, BTN_LEFT, left); | 179 | input_report_key(dev, BTN_LEFT, left); |
| 181 | 180 | ||
| 182 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; | 181 | dev = (dev2 && test_bit(BTN_RIGHT, dev2->key)) ? dev2 : dev1; |
| 183 | input_report_key(dev, BTN_RIGHT, right); | 182 | input_report_key(dev, BTN_RIGHT, right); |
| 184 | 183 | ||
| 185 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; | 184 | dev = (dev2 && test_bit(BTN_MIDDLE, dev2->key)) ? dev2 : dev1; |
| 186 | input_report_key(dev, BTN_MIDDLE, middle); | 185 | input_report_key(dev, BTN_MIDDLE, middle); |
| 187 | 186 | ||
| 188 | /* | 187 | /* |
| 189 | * Sync the _other_ device now, we'll do the first | 188 | * Sync the _other_ device now, we'll do the first |
| 190 | * device later once we report the rest of the events. | 189 | * device later once we report the rest of the events. |
| 191 | */ | 190 | */ |
| 192 | input_sync(dev2); | 191 | if (dev2) |
| 192 | input_sync(dev2); | ||
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static void alps_process_packet_v1_v2(struct psmouse *psmouse) | 195 | static void alps_process_packet_v1_v2(struct psmouse *psmouse) |
| @@ -236,13 +236,13 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) | |||
| 236 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 236 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
| 237 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 237 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
| 238 | 238 | ||
| 239 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); | 239 | alps_report_buttons(dev2, dev, left, right, middle); |
| 240 | 240 | ||
| 241 | input_sync(dev2); | 241 | input_sync(dev2); |
| 242 | return; | 242 | return; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); | 245 | alps_report_buttons(dev, dev2, left, right, middle); |
| 246 | 246 | ||
| 247 | /* Convert hardware tap to a reasonable Z value */ | 247 | /* Convert hardware tap to a reasonable Z value */ |
| 248 | if (ges && !fin) | 248 | if (ges && !fin) |
| @@ -1123,23 +1123,89 @@ static void alps_process_packet_v7(struct psmouse *psmouse) | |||
| 1123 | alps_process_touchpad_packet_v7(psmouse); | 1123 | alps_process_touchpad_packet_v7(psmouse); |
| 1124 | } | 1124 | } |
| 1125 | 1125 | ||
| 1126 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | 1126 | static DEFINE_MUTEX(alps_mutex); |
| 1127 | |||
| 1128 | static void alps_register_bare_ps2_mouse(struct work_struct *work) | ||
| 1129 | { | ||
| 1130 | struct alps_data *priv = | ||
| 1131 | container_of(work, struct alps_data, dev3_register_work.work); | ||
| 1132 | struct psmouse *psmouse = priv->psmouse; | ||
| 1133 | struct input_dev *dev3; | ||
| 1134 | int error = 0; | ||
| 1135 | |||
| 1136 | mutex_lock(&alps_mutex); | ||
| 1137 | |||
| 1138 | if (priv->dev3) | ||
| 1139 | goto out; | ||
| 1140 | |||
| 1141 | dev3 = input_allocate_device(); | ||
| 1142 | if (!dev3) { | ||
| 1143 | psmouse_err(psmouse, "failed to allocate secondary device\n"); | ||
| 1144 | error = -ENOMEM; | ||
| 1145 | goto out; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s", | ||
| 1149 | psmouse->ps2dev.serio->phys, | ||
| 1150 | (priv->dev2 ? "input2" : "input1")); | ||
| 1151 | dev3->phys = priv->phys3; | ||
| 1152 | |||
| 1153 | /* | ||
| 1154 | * format of input device name is: "protocol vendor name" | ||
| 1155 | * see function psmouse_switch_protocol() in psmouse-base.c | ||
| 1156 | */ | ||
| 1157 | dev3->name = "PS/2 ALPS Mouse"; | ||
| 1158 | |||
| 1159 | dev3->id.bustype = BUS_I8042; | ||
| 1160 | dev3->id.vendor = 0x0002; | ||
| 1161 | dev3->id.product = PSMOUSE_PS2; | ||
| 1162 | dev3->id.version = 0x0000; | ||
| 1163 | dev3->dev.parent = &psmouse->ps2dev.serio->dev; | ||
| 1164 | |||
| 1165 | input_set_capability(dev3, EV_REL, REL_X); | ||
| 1166 | input_set_capability(dev3, EV_REL, REL_Y); | ||
| 1167 | input_set_capability(dev3, EV_KEY, BTN_LEFT); | ||
| 1168 | input_set_capability(dev3, EV_KEY, BTN_RIGHT); | ||
| 1169 | input_set_capability(dev3, EV_KEY, BTN_MIDDLE); | ||
| 1170 | |||
| 1171 | __set_bit(INPUT_PROP_POINTER, dev3->propbit); | ||
| 1172 | |||
| 1173 | error = input_register_device(dev3); | ||
| 1174 | if (error) { | ||
| 1175 | psmouse_err(psmouse, | ||
| 1176 | "failed to register secondary device: %d\n", | ||
| 1177 | error); | ||
| 1178 | input_free_device(dev3); | ||
| 1179 | goto out; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | priv->dev3 = dev3; | ||
| 1183 | |||
| 1184 | out: | ||
| 1185 | /* | ||
| 1186 | * Save the error code so that we can detect that we | ||
| 1187 | * already tried to create the device. | ||
| 1188 | */ | ||
| 1189 | if (error) | ||
| 1190 | priv->dev3 = ERR_PTR(error); | ||
| 1191 | |||
| 1192 | mutex_unlock(&alps_mutex); | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static void alps_report_bare_ps2_packet(struct input_dev *dev, | ||
| 1127 | unsigned char packet[], | 1196 | unsigned char packet[], |
| 1128 | bool report_buttons) | 1197 | bool report_buttons) |
| 1129 | { | 1198 | { |
| 1130 | struct alps_data *priv = psmouse->private; | ||
| 1131 | struct input_dev *dev2 = priv->dev2; | ||
| 1132 | |||
| 1133 | if (report_buttons) | 1199 | if (report_buttons) |
| 1134 | alps_report_buttons(psmouse, dev2, psmouse->dev, | 1200 | alps_report_buttons(dev, NULL, |
| 1135 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | 1201 | packet[0] & 1, packet[0] & 2, packet[0] & 4); |
| 1136 | 1202 | ||
| 1137 | input_report_rel(dev2, REL_X, | 1203 | input_report_rel(dev, REL_X, |
| 1138 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | 1204 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); |
| 1139 | input_report_rel(dev2, REL_Y, | 1205 | input_report_rel(dev, REL_Y, |
| 1140 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | 1206 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); |
| 1141 | 1207 | ||
| 1142 | input_sync(dev2); | 1208 | input_sync(dev); |
| 1143 | } | 1209 | } |
| 1144 | 1210 | ||
| 1145 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | 1211 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) |
| @@ -1204,8 +1270,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | |||
| 1204 | * de-synchronization. | 1270 | * de-synchronization. |
| 1205 | */ | 1271 | */ |
| 1206 | 1272 | ||
| 1207 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | 1273 | alps_report_bare_ps2_packet(priv->dev2, |
| 1208 | false); | 1274 | &psmouse->packet[3], false); |
| 1209 | 1275 | ||
| 1210 | /* | 1276 | /* |
| 1211 | * Continue with the standard ALPS protocol handling, | 1277 | * Continue with the standard ALPS protocol handling, |
| @@ -1261,9 +1327,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
| 1261 | * properly we only do this if the device is fully synchronized. | 1327 | * properly we only do this if the device is fully synchronized. |
| 1262 | */ | 1328 | */ |
| 1263 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | 1329 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { |
| 1330 | |||
| 1331 | /* Register dev3 mouse if we received PS/2 packet first time */ | ||
| 1332 | if (unlikely(!priv->dev3)) | ||
| 1333 | psmouse_queue_work(psmouse, | ||
| 1334 | &priv->dev3_register_work, 0); | ||
| 1335 | |||
| 1264 | if (psmouse->pktcnt == 3) { | 1336 | if (psmouse->pktcnt == 3) { |
| 1265 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, | 1337 | /* Once dev3 mouse device is registered report data */ |
| 1266 | true); | 1338 | if (likely(!IS_ERR_OR_NULL(priv->dev3))) |
| 1339 | alps_report_bare_ps2_packet(priv->dev3, | ||
| 1340 | psmouse->packet, | ||
| 1341 | true); | ||
| 1267 | return PSMOUSE_FULL_PACKET; | 1342 | return PSMOUSE_FULL_PACKET; |
| 1268 | } | 1343 | } |
| 1269 | return PSMOUSE_GOOD_DATA; | 1344 | return PSMOUSE_GOOD_DATA; |
| @@ -2378,7 +2453,10 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
| 2378 | 2453 | ||
| 2379 | psmouse_reset(psmouse); | 2454 | psmouse_reset(psmouse); |
| 2380 | del_timer_sync(&priv->timer); | 2455 | del_timer_sync(&priv->timer); |
| 2381 | input_unregister_device(priv->dev2); | 2456 | if (priv->dev2) |
| 2457 | input_unregister_device(priv->dev2); | ||
| 2458 | if (!IS_ERR_OR_NULL(priv->dev3)) | ||
| 2459 | input_unregister_device(priv->dev3); | ||
| 2382 | kfree(priv); | 2460 | kfree(priv); |
| 2383 | } | 2461 | } |
| 2384 | 2462 | ||
| @@ -2412,17 +2490,9 @@ static void alps_set_abs_params_mt(struct alps_data *priv, | |||
| 2412 | int alps_init(struct psmouse *psmouse) | 2490 | int alps_init(struct psmouse *psmouse) |
| 2413 | { | 2491 | { |
| 2414 | struct alps_data *priv = psmouse->private; | 2492 | struct alps_data *priv = psmouse->private; |
| 2415 | struct input_dev *dev1 = psmouse->dev, *dev2; | 2493 | struct input_dev *dev1 = psmouse->dev; |
| 2416 | int error; | 2494 | int error; |
| 2417 | 2495 | ||
| 2418 | dev2 = input_allocate_device(); | ||
| 2419 | if (!dev2) { | ||
| 2420 | error = -ENOMEM; | ||
| 2421 | goto init_fail; | ||
| 2422 | } | ||
| 2423 | |||
| 2424 | priv->dev2 = dev2; | ||
| 2425 | |||
| 2426 | error = priv->hw_init(psmouse); | 2496 | error = priv->hw_init(psmouse); |
| 2427 | if (error) | 2497 | if (error) |
| 2428 | goto init_fail; | 2498 | goto init_fail; |
| @@ -2474,36 +2544,57 @@ int alps_init(struct psmouse *psmouse) | |||
| 2474 | } | 2544 | } |
| 2475 | 2545 | ||
| 2476 | if (priv->flags & ALPS_DUALPOINT) { | 2546 | if (priv->flags & ALPS_DUALPOINT) { |
| 2547 | struct input_dev *dev2; | ||
| 2548 | |||
| 2549 | dev2 = input_allocate_device(); | ||
| 2550 | if (!dev2) { | ||
| 2551 | psmouse_err(psmouse, | ||
| 2552 | "failed to allocate trackstick device\n"); | ||
| 2553 | error = -ENOMEM; | ||
| 2554 | goto init_fail; | ||
| 2555 | } | ||
| 2556 | |||
| 2557 | snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1", | ||
| 2558 | psmouse->ps2dev.serio->phys); | ||
| 2559 | dev2->phys = priv->phys2; | ||
| 2560 | |||
| 2477 | /* | 2561 | /* |
| 2478 | * format of input device name is: "protocol vendor name" | 2562 | * format of input device name is: "protocol vendor name" |
| 2479 | * see function psmouse_switch_protocol() in psmouse-base.c | 2563 | * see function psmouse_switch_protocol() in psmouse-base.c |
| 2480 | */ | 2564 | */ |
| 2481 | dev2->name = "AlpsPS/2 ALPS DualPoint Stick"; | 2565 | dev2->name = "AlpsPS/2 ALPS DualPoint Stick"; |
| 2566 | |||
| 2567 | dev2->id.bustype = BUS_I8042; | ||
| 2568 | dev2->id.vendor = 0x0002; | ||
| 2482 | dev2->id.product = PSMOUSE_ALPS; | 2569 | dev2->id.product = PSMOUSE_ALPS; |
| 2483 | dev2->id.version = priv->proto_version; | 2570 | dev2->id.version = priv->proto_version; |
| 2484 | } else { | 2571 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; |
| 2485 | dev2->name = "PS/2 ALPS Mouse"; | ||
| 2486 | dev2->id.product = PSMOUSE_PS2; | ||
| 2487 | dev2->id.version = 0x0000; | ||
| 2488 | } | ||
| 2489 | |||
| 2490 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); | ||
| 2491 | dev2->phys = priv->phys; | ||
| 2492 | dev2->id.bustype = BUS_I8042; | ||
| 2493 | dev2->id.vendor = 0x0002; | ||
| 2494 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; | ||
| 2495 | 2572 | ||
| 2496 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 2573 | input_set_capability(dev2, EV_REL, REL_X); |
| 2497 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 2574 | input_set_capability(dev2, EV_REL, REL_Y); |
| 2498 | dev2->keybit[BIT_WORD(BTN_LEFT)] = | 2575 | input_set_capability(dev2, EV_KEY, BTN_LEFT); |
| 2499 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 2576 | input_set_capability(dev2, EV_KEY, BTN_RIGHT); |
| 2577 | input_set_capability(dev2, EV_KEY, BTN_MIDDLE); | ||
| 2500 | 2578 | ||
| 2501 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); | 2579 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); |
| 2502 | if (priv->flags & ALPS_DUALPOINT) | ||
| 2503 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); | 2580 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); |
| 2504 | 2581 | ||
| 2505 | if (input_register_device(priv->dev2)) | 2582 | error = input_register_device(dev2); |
| 2506 | goto init_fail; | 2583 | if (error) { |
| 2584 | psmouse_err(psmouse, | ||
| 2585 | "failed to register trackstick device: %d\n", | ||
| 2586 | error); | ||
| 2587 | input_free_device(dev2); | ||
| 2588 | goto init_fail; | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | priv->dev2 = dev2; | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | priv->psmouse = psmouse; | ||
| 2595 | |||
| 2596 | INIT_DELAYED_WORK(&priv->dev3_register_work, | ||
| 2597 | alps_register_bare_ps2_mouse); | ||
| 2507 | 2598 | ||
| 2508 | psmouse->protocol_handler = alps_process_byte; | 2599 | psmouse->protocol_handler = alps_process_byte; |
| 2509 | psmouse->poll = alps_poll; | 2600 | psmouse->poll = alps_poll; |
| @@ -2521,7 +2612,6 @@ int alps_init(struct psmouse *psmouse) | |||
| 2521 | 2612 | ||
| 2522 | init_fail: | 2613 | init_fail: |
| 2523 | psmouse_reset(psmouse); | 2614 | psmouse_reset(psmouse); |
| 2524 | input_free_device(dev2); | ||
| 2525 | /* | 2615 | /* |
| 2526 | * Even though we did not allocate psmouse->private we do free | 2616 | * Even though we did not allocate psmouse->private we do free |
| 2527 | * it here. | 2617 | * it here. |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index c79523562608..02513c0502fc 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
| @@ -141,8 +141,12 @@ struct alps_fields { | |||
| 141 | 141 | ||
| 142 | /** | 142 | /** |
| 143 | * struct alps_data - private data structure for the ALPS driver | 143 | * struct alps_data - private data structure for the ALPS driver |
| 144 | * @dev2: "Relative" device used to report trackstick or mouse activity. | 144 | * @psmouse: Pointer to parent psmouse device |
| 145 | * @phys: Physical path for the relative device. | 145 | * @dev2: Trackstick device (can be NULL). |
| 146 | * @dev3: Generic PS/2 mouse (can be NULL, delayed registering). | ||
| 147 | * @phys2: Physical path for the trackstick device. | ||
| 148 | * @phys3: Physical path for the generic PS/2 mouse. | ||
| 149 | * @dev3_register_work: Delayed work for registering PS/2 mouse. | ||
| 146 | * @nibble_commands: Command mapping used for touchpad register accesses. | 150 | * @nibble_commands: Command mapping used for touchpad register accesses. |
| 147 | * @addr_command: Command used to tell the touchpad that a register address | 151 | * @addr_command: Command used to tell the touchpad that a register address |
| 148 | * follows. | 152 | * follows. |
| @@ -169,8 +173,12 @@ struct alps_fields { | |||
| 169 | * @timer: Timer for flushing out the final report packet in the stream. | 173 | * @timer: Timer for flushing out the final report packet in the stream. |
| 170 | */ | 174 | */ |
| 171 | struct alps_data { | 175 | struct alps_data { |
| 176 | struct psmouse *psmouse; | ||
| 172 | struct input_dev *dev2; | 177 | struct input_dev *dev2; |
| 173 | char phys[32]; | 178 | struct input_dev *dev3; |
| 179 | char phys2[32]; | ||
| 180 | char phys3[32]; | ||
| 181 | struct delayed_work dev3_register_work; | ||
| 174 | 182 | ||
| 175 | /* these are autodetected when the device is identified */ | 183 | /* these are autodetected when the device is identified */ |
| 176 | const struct alps_nibble_commands *nibble_commands; | 184 | const struct alps_nibble_commands *nibble_commands; |
