Skip to content

Commit

Permalink
Input: xpad - enable & autodetect Flydigi extra buttons
Browse files Browse the repository at this point in the history
This adds a framework for supporting additional features on devices
piggybacking an existing USB vendor/product ID but distinguishing
themselves via the idProduct field.  This is necessary because the
Flydigi Vader Pro series controllers reuse the same vendor/product ID as
orginal Microsoft Xbox 360 controllers.

The MAP_FLYDIGI_BUTTONS is a new mapping for the C, Z, and Circle face
buttons on Flydigi 360-compatible controllers.  It has been tested on
the Vader 3 Pro and Vader 4 Pro.

These controllers additionally have 4 back paddles, same as the Xbox
Elite controller, so it is included in the extra feature list.

Thanks-to: Matthew Carter <[email protected]>
See: paroj/xpad#268
Signed-off-by: Matoro Mahri <[email protected]>
  • Loading branch information
matoro authored and intel-lab-lkp committed Oct 21, 2024
1 parent d0c3a7a commit 87362d8
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion drivers/input/joystick/xpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#define MAP_SELECT_BUTTON (1 << 3)
#define MAP_PADDLES (1 << 4)
#define MAP_PROFILE_BUTTON (1 << 5)
#define MAP_FLYDIGI_BUTTONS (1 << 6)

#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
Expand Down Expand Up @@ -387,6 +388,19 @@ static const struct xpad_device {
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
};

// A "flavor" is an aftermarket variant of an existing model supporting
// additional features.
static const struct xpad_flavor {
u16 idVendor;
u16 idProduct;
char *product;
u8 mapping;
} xpad_flavor[] = {
{ 0x045e, 0x028e, "Flydigi VADER3", MAP_PADDLES | MAP_FLYDIGI_BUTTONS },
{ 0x045e, 0x028e, "Flydigi VADER4", MAP_PADDLES | MAP_FLYDIGI_BUTTONS },
{ 0x0000, 0x0000, NULL, 0 }
};

/* buttons shared with xbox and xbox360 */
static const signed short xpad_common_btn[] = {
BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */
Expand Down Expand Up @@ -444,6 +458,13 @@ static const signed short xpad_btn_paddles[] = {
-1 /* terminating entry */
};

/* used for extra buttons in addition to paddles on Flydigi Vader Pro series*/
static const signed short xpad_btn_extra[] = {
BTN_TRIGGER_HAPPY9, BTN_TRIGGER_HAPPY10, /* C, Z face buttons */
BTN_TRIGGER_HAPPY11, /* circle */
-1 /* terminating entry */
};

/*
* 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
Expand Down Expand Up @@ -898,6 +919,17 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
input_report_abs(dev, ABS_RZ, data[5]);
}

/* Additional buttons for Flydigi Vader Pro series presenting as 360 pad. */
if (xpad->mapping & MAP_FLYDIGI_BUTTONS) {
input_report_key(dev, BTN_TRIGGER_HAPPY9, data[19] & BIT(0)); // C
input_report_key(dev, BTN_TRIGGER_HAPPY10, data[19] & BIT(1)); // Z
input_report_key(dev, BTN_TRIGGER_HAPPY5, data[19] & BIT(3)); // Leftmost paddle (M2)
input_report_key(dev, BTN_TRIGGER_HAPPY6, data[19] & BIT(5)); // Second to leftmost (M4)
input_report_key(dev, BTN_TRIGGER_HAPPY7, data[19] & BIT(4)); // Second to rightmost (M3)
input_report_key(dev, BTN_TRIGGER_HAPPY8, data[19] & BIT(2)); // Rightmost paddle (M1)
input_report_key(dev, BTN_TRIGGER_HAPPY11, data[20] & BIT(0)); // Circle
}

input_sync(dev);

/* XBOX360W controllers can't be turned off without driver assistance */
Expand Down Expand Up @@ -1928,6 +1960,13 @@ static int xpad_init_input(struct usb_xpad *xpad)
input_set_capability(input_dev, EV_KEY, xpad_btn_paddles[i]);
}

/* set up extra face buttons if the controller has them */
if (xpad->mapping & MAP_FLYDIGI_BUTTONS) {
for (i = 0; xpad_btn_extra[i] >= 0; i++) {
input_set_capability(input_dev, EV_KEY, xpad_btn_extra[i]);
}
}

/*
* This should be a simple else block. However historically
* xbox360w has mapped DPAD to buttons while xbox360 did not. This
Expand Down Expand Up @@ -1982,7 +2021,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_xpad *xpad;
struct usb_endpoint_descriptor *ep_irq_in, *ep_irq_out;
int i, error;
int i, j, error;

if (intf->cur_altsetting->desc.bNumEndpoints != 2)
return -ENODEV;
Expand Down Expand Up @@ -2016,6 +2055,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->udev = udev;
xpad->intf = intf;
xpad->mapping = xpad_device[i].mapping;

if (udev->product) { // Only worry about extra flavors if a product string is present
for(j = 0; xpad_flavor[j].idVendor; j++) {
if (le16_to_cpu(udev->descriptor.idVendor) == xpad_flavor[j].idVendor &&
le16_to_cpu(udev->descriptor.idProduct) == xpad_flavor[j].idProduct &&
!strcmp(udev->product, xpad_flavor[j].product)) {
xpad->mapping |= xpad_flavor[j].mapping;
break;
}
}
}

xpad->xtype = xpad_device[i].xtype;
xpad->name = xpad_device[i].name;
xpad->packet_type = PKT_XB;
Expand Down

0 comments on commit 87362d8

Please sign in to comment.