aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Loup A. Griffais <pgriffais@valvesoftware.com>2015-06-22 17:10:36 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-06-22 17:24:57 -0400
commit75b7f05d2798ee3a1cc5bbdd54acd0e318a80396 (patch)
treea5882c75aca99569f57b93a449000eb0ccef09ca
parente998200c1912f22cf257ae88771e56de588ee8fb (diff)
Input: xpad - set the LEDs properly on XBox Wireless controllers
Based on Patch by Pierre-Loup A. Griffais <pgriffais@valvesoftware.com>: Add the logic to set the LEDs on XBox Wireless controllers. Command sequence found by sniffing the Windows data stream when plugging the device in. Updated based on comments on linux-input: unify codepaths in xpad_send_led_command for wired/ wireless controller. Also document command values for clarification. All values tested on Xbox 360 Wireless Controller. Signed-off-by: Pavel Rojtberg <rojtberg@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/joystick/xpad.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 61c761156371..6f8755e2c491 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -881,17 +881,57 @@ struct xpad_led {
881 struct usb_xpad *xpad; 881 struct usb_xpad *xpad;
882}; 882};
883 883
884/**
885 * @param command
886 * 0: off
887 * 1: all blink, then previous setting
888 * 2: 1/top-left blink, then on
889 * 3: 2/top-right blink, then on
890 * 4: 3/bottom-left blink, then on
891 * 5: 4/bottom-right blink, then on
892 * 6: 1/top-left on
893 * 7: 2/top-right on
894 * 8: 3/bottom-left on
895 * 9: 4/bottom-right on
896 * 10: rotate
897 * 11: blink, based on previous setting
898 * 12: slow blink, based on previous setting
899 * 13: rotate with two lights
900 * 14: persistent slow all blink
901 * 15: blink once, then previous setting
902 */
884static void xpad_send_led_command(struct usb_xpad *xpad, int command) 903static void xpad_send_led_command(struct usb_xpad *xpad, int command)
885{ 904{
886 if (command >= 0 && command < 14) { 905 command %= 16;
887 mutex_lock(&xpad->odata_mutex); 906
907 mutex_lock(&xpad->odata_mutex);
908
909 switch (xpad->xtype) {
910 case XTYPE_XBOX360:
888 xpad->odata[0] = 0x01; 911 xpad->odata[0] = 0x01;
889 xpad->odata[1] = 0x03; 912 xpad->odata[1] = 0x03;
890 xpad->odata[2] = command; 913 xpad->odata[2] = command;
891 xpad->irq_out->transfer_buffer_length = 3; 914 xpad->irq_out->transfer_buffer_length = 3;
892 usb_submit_urb(xpad->irq_out, GFP_KERNEL); 915 break;
893 mutex_unlock(&xpad->odata_mutex); 916 case XTYPE_XBOX360W:
917 xpad->odata[0] = 0x00;
918 xpad->odata[1] = 0x00;
919 xpad->odata[2] = 0x08;
920 xpad->odata[3] = 0x40 + command;
921 xpad->odata[4] = 0x00;
922 xpad->odata[5] = 0x00;
923 xpad->odata[6] = 0x00;
924 xpad->odata[7] = 0x00;
925 xpad->odata[8] = 0x00;
926 xpad->odata[9] = 0x00;
927 xpad->odata[10] = 0x00;
928 xpad->odata[11] = 0x00;
929 xpad->irq_out->transfer_buffer_length = 12;
930 break;
894 } 931 }
932
933 usb_submit_urb(xpad->irq_out, GFP_KERNEL);
934 mutex_unlock(&xpad->odata_mutex);
895} 935}
896 936
897static void xpad_led_set(struct led_classdev *led_cdev, 937static void xpad_led_set(struct led_classdev *led_cdev,
@@ -911,7 +951,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
911 struct led_classdev *led_cdev; 951 struct led_classdev *led_cdev;
912 int error; 952 int error;
913 953
914 if (xpad->xtype != XTYPE_XBOX360) 954 if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W)
915 return 0; 955 return 0;
916 956
917 xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); 957 xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL);