Skip to content

Commit

Permalink
Merge branch 'next' into for-linus
Browse files Browse the repository at this point in the history
Prepare second round of input updates for 3.17.
  • Loading branch information
dtor committed Aug 15, 2014
2 parents a6b4869 + 3361a97 commit 91167e1
Show file tree
Hide file tree
Showing 7 changed files with 459 additions and 201 deletions.
38 changes: 27 additions & 11 deletions drivers/input/input-mt.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,31 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
}
EXPORT_SYMBOL(input_mt_report_pointer_emulation);

/**
* input_mt_drop_unused() - Inactivate slots not seen in this frame
* @dev: input device with allocated MT slots
*
* Lift all slots not seen since the last call to this function.
*/
void input_mt_drop_unused(struct input_dev *dev)
{
struct input_mt *mt = dev->mt;
int i;

if (!mt)
return;

for (i = 0; i < mt->num_slots; i++) {
if (!input_mt_is_used(mt, &mt->slots[i])) {
input_mt_slot(dev, i);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
}
}

mt->frame++;
}
EXPORT_SYMBOL(input_mt_drop_unused);

/**
* input_mt_sync_frame() - synchronize mt frame
* @dev: input device with allocated MT slots
Expand All @@ -247,27 +272,18 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation);
void input_mt_sync_frame(struct input_dev *dev)
{
struct input_mt *mt = dev->mt;
struct input_mt_slot *s;
bool use_count = false;

if (!mt)
return;

if (mt->flags & INPUT_MT_DROP_UNUSED) {
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (input_mt_is_used(mt, s))
continue;
input_mt_slot(dev, s - mt->slots);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
}
}
if (mt->flags & INPUT_MT_DROP_UNUSED)
input_mt_drop_unused(dev);

if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
use_count = true;

input_mt_report_pointer_emulation(dev, use_count);

mt->frame++;
}
EXPORT_SYMBOL(input_mt_sync_frame);

Expand Down
174 changes: 157 additions & 17 deletions drivers/input/joystick/xpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
#define XTYPE_XBOX360W 2
#define XTYPE_UNKNOWN 3
#define XTYPE_XBOXONE 3
#define XTYPE_UNKNOWN 4

static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
Expand All @@ -121,6 +122,7 @@ static const struct xpad_device {
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
Expand Down Expand Up @@ -231,10 +233,12 @@ static const signed short xpad_abs_triggers[] = {
-1
};

/* Xbox 360 has a vendor-specific class, so we cannot match it with only
/*
* Xbox 360 has a vendor-specific class, so we cannot match it with only
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
* wireless controllers have protocol 129. */
* wireless controllers have protocol 129.
*/
#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
Expand All @@ -245,9 +249,20 @@ static const signed short xpad_abs_triggers[] = {
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }

/* The Xbox One controller uses subclass 71 and protocol 208. */
#define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
.bInterfaceSubClass = 71, \
.bInterfaceProtocol = (pr)
#define XPAD_XBOXONE_VENDOR(vend) \
{ XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }

static struct usb_device_id xpad_table[] = {
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
Expand Down Expand Up @@ -278,12 +293,10 @@ struct usb_xpad {
struct urb *bulk_out;
unsigned char *bdata;

#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct urb *irq_out; /* urb for interrupt out report */
unsigned char *odata; /* output data */
dma_addr_t odata_dma;
struct mutex odata_mutex;
#endif

#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct xpad_led *led;
Expand Down Expand Up @@ -470,6 +483,105 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha
xpad360_process_packet(xpad, cmd, &data[4]);
}

/*
* xpadone_process_buttons
*
* Process a button update packet from an Xbox one controller.
*/
static void xpadone_process_buttons(struct usb_xpad *xpad,
struct input_dev *dev,
unsigned char *data)
{
/* menu/view buttons */
input_report_key(dev, BTN_START, data[4] & 0x04);
input_report_key(dev, BTN_SELECT, data[4] & 0x08);

/* buttons A,B,X,Y */
input_report_key(dev, BTN_A, data[4] & 0x10);
input_report_key(dev, BTN_B, data[4] & 0x20);
input_report_key(dev, BTN_X, data[4] & 0x40);
input_report_key(dev, BTN_Y, data[4] & 0x80);

/* digital pad */
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (left, right, up, down) */
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04);
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08);
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01);
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02);
} else {
input_report_abs(dev, ABS_HAT0X,
!!(data[5] & 0x08) - !!(data[5] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
!!(data[5] & 0x02) - !!(data[5] & 0x01));
}

/* TL/TR */
input_report_key(dev, BTN_TL, data[5] & 0x10);
input_report_key(dev, BTN_TR, data[5] & 0x20);

/* stick press left/right */
input_report_key(dev, BTN_THUMBL, data[5] & 0x40);
input_report_key(dev, BTN_THUMBR, data[5] & 0x80);

if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
/* left stick */
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 10)));
input_report_abs(dev, ABS_Y,
~(__s16) le16_to_cpup((__le16 *)(data + 12)));

/* right stick */
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 14)));
input_report_abs(dev, ABS_RY,
~(__s16) le16_to_cpup((__le16 *)(data + 16)));
}

/* triggers left/right */
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
input_report_key(dev, BTN_TL2,
(__u16) le16_to_cpup((__le16 *)(data + 6)));
input_report_key(dev, BTN_TR2,
(__u16) le16_to_cpup((__le16 *)(data + 8)));
} else {
input_report_abs(dev, ABS_Z,
(__u16) le16_to_cpup((__le16 *)(data + 6)));
input_report_abs(dev, ABS_RZ,
(__u16) le16_to_cpup((__le16 *)(data + 8)));
}

input_sync(dev);
}

/*
* xpadone_process_packet
*
* Completes a request by converting the data into events for the
* input subsystem. This version is for the Xbox One controller.
*
* The report format was gleaned from
* https://github.com/kylelemons/xbox/blob/master/xbox.go
*/

static void xpadone_process_packet(struct usb_xpad *xpad,
u16 cmd, unsigned char *data)
{
struct input_dev *dev = xpad->dev;

switch (data[0]) {
case 0x20:
xpadone_process_buttons(xpad, dev, data);
break;

case 0x07:
/* the xbox button has its own special report */
input_report_key(dev, BTN_MODE, data[4] & 0x01);
input_sync(dev);
break;
}
}

static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
Expand Down Expand Up @@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb)
case XTYPE_XBOX360W:
xpad360w_process_packet(xpad, 0, xpad->idata);
break;
case XTYPE_XBOXONE:
xpadone_process_packet(xpad, 0, xpad->idata);
break;
default:
xpad_process_packet(xpad, 0, xpad->idata);
}
Expand Down Expand Up @@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *urb)
}
}

#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
static void xpad_irq_out(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
Expand Down Expand Up @@ -573,6 +687,7 @@ static void xpad_irq_out(struct urb *urb)
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
{
struct usb_endpoint_descriptor *ep_irq_out;
int ep_irq_out_idx;
int error;

if (xpad->xtype == XTYPE_UNKNOWN)
Expand All @@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
goto fail2;
}

ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
/* Xbox One controller has in/out endpoints swapped. */
ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1;
ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc;

usb_fill_int_urb(xpad->irq_out, xpad->udev,
usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
xpad->odata, XPAD_PKT_LEN,
Expand Down Expand Up @@ -621,11 +739,6 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
xpad->odata, xpad->odata_dma);
}
}
#else
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
static void xpad_deinit_output(struct usb_xpad *xpad) {}
static void xpad_stop_output(struct usb_xpad *xpad) {}
#endif

#ifdef CONFIG_JOYSTICK_XPAD_FF
static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
Expand Down Expand Up @@ -692,7 +805,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect

static int xpad_init_ff(struct usb_xpad *xpad)
{
if (xpad->xtype == XTYPE_UNKNOWN)
if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE)
return 0;

input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
Expand Down Expand Up @@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;

if (xpad->xtype == XTYPE_XBOXONE) {
/* Xbox one controller needs to be initialized. */
xpad->odata[0] = 0x05;
xpad->odata[1] = 0x20;
xpad->irq_out->transfer_buffer_length = 2;
return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
}

return 0;
}

Expand All @@ -816,6 +937,7 @@ static void xpad_close(struct input_dev *dev)

static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
{
struct usb_xpad *xpad = input_get_drvdata(input_dev);
set_bit(abs, input_dev->absbit);

switch (abs) {
Expand All @@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
break;
case ABS_Z:
case ABS_RZ: /* the triggers (if mapped to axes) */
input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
if (xpad->xtype == XTYPE_XBOXONE)
input_set_abs_params(input_dev, abs, 0, 1023, 0, 0);
else
input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
Expand All @@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct usb_xpad *xpad;
struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
int ep_irq_in_idx;
int i, error;

for (i = 0; xpad_device[i].idVendor; i++) {
Expand All @@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
break;
}

if (xpad_device[i].xtype == XTYPE_XBOXONE &&
intf->cur_altsetting->desc.bInterfaceNumber != 0) {
/*
* The Xbox One controller lists three interfaces all with the
* same interface class, subclass and protocol. Differentiate by
* interface number.
*/
return -ENODEV;
}

xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
input_dev = input_allocate_device();
if (!xpad || !input_dev) {
Expand Down Expand Up @@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit(xpad_common_btn[i], input_dev->keybit);

/* set up model-specific ones */
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
xpad->xtype == XTYPE_XBOXONE) {
for (i = 0; xpad360_btn[i] >= 0; i++)
__set_bit(xpad360_btn[i], input_dev->keybit);
} else {
Expand All @@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit(xpad_btn_pad[i], input_dev->keybit);
} else {
for (i = 0; xpad_abs_pad[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
}

if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
Expand All @@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if (error)
goto fail5;

ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
/* Xbox One controller has in/out endpoints swapped. */
ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;

usb_fill_int_urb(xpad->irq_in, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
Expand Down
Loading

0 comments on commit 91167e1

Please sign in to comment.