aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/alps.c190
-rw-r--r--drivers/input/mouse/alps.h14
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
168static void alps_report_buttons(struct psmouse *psmouse, 168static 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
195static void alps_process_packet_v1_v2(struct psmouse *psmouse) 195static 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
1126static void alps_report_bare_ps2_packet(struct psmouse *psmouse, 1126static DEFINE_MUTEX(alps_mutex);
1127
1128static 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
1184out:
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
1195static 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
1145static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) 1211static 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,
2412int alps_init(struct psmouse *psmouse) 2490int 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
2522init_fail: 2613init_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 */
171struct alps_data { 175struct 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;