aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick
diff options
context:
space:
mode:
authorPavel Rojtberg <rojtberg@gmail.com>2015-12-09 16:30:34 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-01-04 17:35:06 -0500
commit4220f7db1e424f2a086ad41217b5770cc9f003a9 (patch)
tree73366f1fda60c39819b5e8047ad6c51017999c47 /drivers/input/joystick
parent2a6d7527b35cf987260800807e328d167aef22ac (diff)
Input: xpad - workaround dead irq_out after suspend/ resume
The irq_out urb is dead after suspend/ resume on my x360 wr pad. (also reproduced by Zachary Lund [0]) Work around this by implementing suspend, resume, and reset_resume callbacks and properly shutting down URBs on suspend and restarting them on resume. [0]: https://github.com/paroj/xpad/issues/6 Signed-off-by: Pavel Rojtberg <rojtberg@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/joystick')
-rw-r--r--drivers/input/joystick/xpad.c175
1 files changed, 137 insertions, 38 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index aa6586043a6c..fa2612c9799c 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -82,6 +82,7 @@
82#include <linux/stat.h> 82#include <linux/stat.h>
83#include <linux/module.h> 83#include <linux/module.h>
84#include <linux/usb/input.h> 84#include <linux/usb/input.h>
85#include <linux/usb/quirks.h>
85 86
86#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" 87#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
87#define DRIVER_DESC "X-Box pad driver" 88#define DRIVER_DESC "X-Box pad driver"
@@ -346,9 +347,10 @@ struct usb_xpad {
346 dma_addr_t idata_dma; 347 dma_addr_t idata_dma;
347 348
348 struct urb *irq_out; /* urb for interrupt out report */ 349 struct urb *irq_out; /* urb for interrupt out report */
350 struct usb_anchor irq_out_anchor;
349 bool irq_out_active; /* we must not use an active URB */ 351 bool irq_out_active; /* we must not use an active URB */
350 unsigned char *odata; /* output data */
351 u8 odata_serial; /* serial number for xbox one protocol */ 352 u8 odata_serial; /* serial number for xbox one protocol */
353 unsigned char *odata; /* output data */
352 dma_addr_t odata_dma; 354 dma_addr_t odata_dma;
353 spinlock_t odata_lock; 355 spinlock_t odata_lock;
354 356
@@ -764,11 +766,13 @@ static int xpad_try_sending_next_out_packet(struct usb_xpad *xpad)
764 int error; 766 int error;
765 767
766 if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) { 768 if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) {
769 usb_anchor_urb(xpad->irq_out, &xpad->irq_out_anchor);
767 error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC); 770 error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
768 if (error) { 771 if (error) {
769 dev_err(&xpad->intf->dev, 772 dev_err(&xpad->intf->dev,
770 "%s - usb_submit_urb failed with result %d\n", 773 "%s - usb_submit_urb failed with result %d\n",
771 __func__, error); 774 __func__, error);
775 usb_unanchor_urb(xpad->irq_out);
772 return -EIO; 776 return -EIO;
773 } 777 }
774 778
@@ -811,11 +815,13 @@ static void xpad_irq_out(struct urb *urb)
811 } 815 }
812 816
813 if (xpad->irq_out_active) { 817 if (xpad->irq_out_active) {
818 usb_anchor_urb(urb, &xpad->irq_out_anchor);
814 error = usb_submit_urb(urb, GFP_ATOMIC); 819 error = usb_submit_urb(urb, GFP_ATOMIC);
815 if (error) { 820 if (error) {
816 dev_err(dev, 821 dev_err(dev,
817 "%s - usb_submit_urb failed with result %d\n", 822 "%s - usb_submit_urb failed with result %d\n",
818 __func__, error); 823 __func__, error);
824 usb_unanchor_urb(urb);
819 xpad->irq_out_active = false; 825 xpad->irq_out_active = false;
820 } 826 }
821 } 827 }
@@ -832,6 +838,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
832 if (xpad->xtype == XTYPE_UNKNOWN) 838 if (xpad->xtype == XTYPE_UNKNOWN)
833 return 0; 839 return 0;
834 840
841 init_usb_anchor(&xpad->irq_out_anchor);
842
835 xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, 843 xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
836 GFP_KERNEL, &xpad->odata_dma); 844 GFP_KERNEL, &xpad->odata_dma);
837 if (!xpad->odata) { 845 if (!xpad->odata) {
@@ -866,8 +874,14 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
866 874
867static void xpad_stop_output(struct usb_xpad *xpad) 875static void xpad_stop_output(struct usb_xpad *xpad)
868{ 876{
869 if (xpad->xtype != XTYPE_UNKNOWN) 877 if (xpad->xtype != XTYPE_UNKNOWN) {
870 usb_kill_urb(xpad->irq_out); 878 if (!usb_wait_anchor_empty_timeout(&xpad->irq_out_anchor,
879 5000)) {
880 dev_warn(&xpad->intf->dev,
881 "timed out waiting for output URB to complete, killing\n");
882 usb_kill_anchored_urbs(&xpad->irq_out_anchor);
883 }
884 }
871} 885}
872 886
873static void xpad_deinit_output(struct usb_xpad *xpad) 887static void xpad_deinit_output(struct usb_xpad *xpad)
@@ -1196,32 +1210,73 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { }
1196static void xpad_identify_controller(struct usb_xpad *xpad) { } 1210static void xpad_identify_controller(struct usb_xpad *xpad) { }
1197#endif 1211#endif
1198 1212
1199static int xpad_open(struct input_dev *dev) 1213static int xpad_start_input(struct usb_xpad *xpad)
1200{ 1214{
1201 struct usb_xpad *xpad = input_get_drvdata(dev); 1215 int error;
1202
1203 /* URB was submitted in probe */
1204 if (xpad->xtype == XTYPE_XBOX360W)
1205 return 0;
1206 1216
1207 xpad->irq_in->dev = xpad->udev;
1208 if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) 1217 if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
1209 return -EIO; 1218 return -EIO;
1210 1219
1211 if (xpad->xtype == XTYPE_XBOXONE) 1220 if (xpad->xtype == XTYPE_XBOXONE) {
1212 return xpad_start_xbox_one(xpad); 1221 error = xpad_start_xbox_one(xpad);
1222 if (error) {
1223 usb_kill_urb(xpad->irq_in);
1224 return error;
1225 }
1226 }
1213 1227
1214 return 0; 1228 return 0;
1215} 1229}
1216 1230
1217static void xpad_close(struct input_dev *dev) 1231static void xpad_stop_input(struct usb_xpad *xpad)
1218{ 1232{
1219 struct usb_xpad *xpad = input_get_drvdata(dev); 1233 usb_kill_urb(xpad->irq_in);
1234}
1235
1236static int xpad360w_start_input(struct usb_xpad *xpad)
1237{
1238 int error;
1239
1240 error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
1241 if (error)
1242 return -EIO;
1220 1243
1221 if (xpad->xtype != XTYPE_XBOX360W) 1244 /*
1245 * Send presence packet.
1246 * This will force the controller to resend connection packets.
1247 * This is useful in the case we activate the module after the
1248 * adapter has been plugged in, as it won't automatically
1249 * send us info about the controllers.
1250 */
1251 error = xpad_inquiry_pad_presence(xpad);
1252 if (error) {
1222 usb_kill_urb(xpad->irq_in); 1253 usb_kill_urb(xpad->irq_in);
1254 return error;
1255 }
1223 1256
1224 xpad_stop_output(xpad); 1257 return 0;
1258}
1259
1260static void xpad360w_stop_input(struct usb_xpad *xpad)
1261{
1262 usb_kill_urb(xpad->irq_in);
1263
1264 /* Make sure we are done with presence work if it was scheduled */
1265 flush_work(&xpad->work);
1266}
1267
1268static int xpad_open(struct input_dev *dev)
1269{
1270 struct usb_xpad *xpad = input_get_drvdata(dev);
1271
1272 return xpad_start_input(xpad);
1273}
1274
1275static void xpad_close(struct input_dev *dev)
1276{
1277 struct usb_xpad *xpad = input_get_drvdata(dev);
1278
1279 xpad_stop_input(xpad);
1225} 1280}
1226 1281
1227static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) 1282static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -1276,8 +1331,10 @@ static int xpad_init_input(struct usb_xpad *xpad)
1276 1331
1277 input_set_drvdata(input_dev, xpad); 1332 input_set_drvdata(input_dev, xpad);
1278 1333
1279 input_dev->open = xpad_open; 1334 if (xpad->xtype != XTYPE_XBOX360W) {
1280 input_dev->close = xpad_close; 1335 input_dev->open = xpad_open;
1336 input_dev->close = xpad_close;
1337 }
1281 1338
1282 __set_bit(EV_KEY, input_dev->evbit); 1339 __set_bit(EV_KEY, input_dev->evbit);
1283 1340
@@ -1445,21 +1502,17 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
1445 * exactly the message that a controller has arrived that 1502 * exactly the message that a controller has arrived that
1446 * we're waiting for. 1503 * we're waiting for.
1447 */ 1504 */
1448 xpad->irq_in->dev = xpad->udev; 1505 error = xpad360w_start_input(xpad);
1449 error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
1450 if (error) 1506 if (error)
1451 goto err_deinit_output; 1507 goto err_deinit_output;
1452
1453 /* 1508 /*
1454 * Send presence packet. 1509 * Wireless controllers require RESET_RESUME to work properly
1455 * This will force the controller to resend connection packets. 1510 * after suspend. Ideally this quirk should be in usb core
1456 * This is useful in the case we activate the module after the 1511 * quirk list, but we have too many vendors producing these
1457 * adapter has been plugged in, as it won't automatically 1512 * controllers and we'd need to maintain 2 identical lists
1458 * send us info about the controllers. 1513 * here in this driver and in usb core.
1459 */ 1514 */
1460 error = xpad_inquiry_pad_presence(xpad); 1515 udev->quirks |= USB_QUIRK_RESET_RESUME;
1461 if (error)
1462 goto err_kill_in_urb;
1463 } else { 1516 } else {
1464 error = xpad_init_input(xpad); 1517 error = xpad_init_input(xpad);
1465 if (error) 1518 if (error)
@@ -1467,8 +1520,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
1467 } 1520 }
1468 return 0; 1521 return 0;
1469 1522
1470err_kill_in_urb:
1471 usb_kill_urb(xpad->irq_in);
1472err_deinit_output: 1523err_deinit_output:
1473 xpad_deinit_output(xpad); 1524 xpad_deinit_output(xpad);
1474err_free_in_urb: 1525err_free_in_urb:
@@ -1478,35 +1529,83 @@ err_free_idata:
1478err_free_mem: 1529err_free_mem:
1479 kfree(xpad); 1530 kfree(xpad);
1480 return error; 1531 return error;
1481
1482} 1532}
1483 1533
1484static void xpad_disconnect(struct usb_interface *intf) 1534static void xpad_disconnect(struct usb_interface *intf)
1485{ 1535{
1486 struct usb_xpad *xpad = usb_get_intfdata (intf); 1536 struct usb_xpad *xpad = usb_get_intfdata(intf);
1487 1537
1488 if (xpad->xtype == XTYPE_XBOX360W) 1538 if (xpad->xtype == XTYPE_XBOX360W)
1489 usb_kill_urb(xpad->irq_in); 1539 xpad360w_stop_input(xpad);
1490
1491 cancel_work_sync(&xpad->work);
1492 1540
1493 xpad_deinit_input(xpad); 1541 xpad_deinit_input(xpad);
1494 1542
1543 /*
1544 * Now that both input device and LED device are gone we can
1545 * stop output URB.
1546 */
1547 xpad_stop_output(xpad);
1548
1549 xpad_deinit_output(xpad);
1550
1495 usb_free_urb(xpad->irq_in); 1551 usb_free_urb(xpad->irq_in);
1496 usb_free_coherent(xpad->udev, XPAD_PKT_LEN, 1552 usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
1497 xpad->idata, xpad->idata_dma); 1553 xpad->idata, xpad->idata_dma);
1498 1554
1499 xpad_deinit_output(xpad);
1500
1501 kfree(xpad); 1555 kfree(xpad);
1502 1556
1503 usb_set_intfdata(intf, NULL); 1557 usb_set_intfdata(intf, NULL);
1504} 1558}
1505 1559
1560static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
1561{
1562 struct usb_xpad *xpad = usb_get_intfdata(intf);
1563 struct input_dev *input = xpad->dev;
1564
1565 if (xpad->xtype == XTYPE_XBOX360W) {
1566 /*
1567 * Wireless controllers always listen to input so
1568 * they are notified when controller shows up
1569 * or goes away.
1570 */
1571 xpad360w_stop_input(xpad);
1572 } else {
1573 mutex_lock(&input->mutex);
1574 if (input->users)
1575 xpad_stop_input(xpad);
1576 mutex_unlock(&input->mutex);
1577 }
1578
1579 xpad_stop_output(xpad);
1580
1581 return 0;
1582}
1583
1584static int xpad_resume(struct usb_interface *intf)
1585{
1586 struct usb_xpad *xpad = usb_get_intfdata(intf);
1587 struct input_dev *input = xpad->dev;
1588 int retval = 0;
1589
1590 if (xpad->xtype == XTYPE_XBOX360W) {
1591 retval = xpad360w_start_input(xpad);
1592 } else {
1593 mutex_lock(&input->mutex);
1594 if (input->users)
1595 retval = xpad_start_input(xpad);
1596 mutex_unlock(&input->mutex);
1597 }
1598
1599 return retval;
1600}
1601
1506static struct usb_driver xpad_driver = { 1602static struct usb_driver xpad_driver = {
1507 .name = "xpad", 1603 .name = "xpad",
1508 .probe = xpad_probe, 1604 .probe = xpad_probe,
1509 .disconnect = xpad_disconnect, 1605 .disconnect = xpad_disconnect,
1606 .suspend = xpad_suspend,
1607 .resume = xpad_resume,
1608 .reset_resume = xpad_resume,
1510 .id_table = xpad_table, 1609 .id_table = xpad_table,
1511}; 1610};
1512 1611