Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add paddles support for the Elite Series 2 firmware versions < 5.x #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions driver/gamepad.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

#define GIP_GP_NAME "Microsoft Xbox Controller"

#define GIP_VENDOR_MICROSOFT 0x045e
#define GIP_PRODUCT_ELITE_SERIES_2 0x0b00
// Various versions of the Elite Series 2 firmware have changed the way paddle
// states are sent. Paddle support is only reported up to this firmware
// version.
#define GIP_ELITE_SERIES_2_MAX_FIRMWARE 0x04FF

#define GIP_GP_RUMBLE_DELAY msecs_to_jiffies(10)
#define GIP_GP_RUMBLE_MAX 100

Expand Down Expand Up @@ -43,6 +50,13 @@ enum gip_gamepad_button {
GIP_GP_BTN_STICK_R = BIT(15),
};

enum gip_gamepad_paddle {
GIP_GP_BTN_P1 = BIT(0),
GIP_GP_BTN_P2 = BIT(1),
GIP_GP_BTN_P3 = BIT(2),
GIP_GP_BTN_P4 = BIT(3),
};

enum gip_gamepad_motor {
GIP_GP_MOTOR_R = BIT(0),
GIP_GP_MOTOR_L = BIT(1),
Expand Down Expand Up @@ -86,6 +100,7 @@ struct gip_gamepad {

bool supports_share;
bool supports_dli;
bool supports_paddles;

struct gip_gamepad_rumble {
/* serializes access to rumble packet */
Expand Down Expand Up @@ -160,16 +175,28 @@ static int gip_gamepad_init_rumble(struct gip_gamepad *gamepad)
static int gip_gamepad_init_input(struct gip_gamepad *gamepad)
{
struct input_dev *dev = gamepad->input.dev;
struct gip_hardware hardware = gamepad->client->hardware;
int err;

gamepad->supports_share = gip_has_interface(gamepad->client,
&gip_gamepad_guid_share);
gamepad->supports_dli = gip_has_interface(gamepad->client,
&gip_gamepad_guid_dli);

gamepad->supports_paddles = hardware.vendor == GIP_VENDOR_MICROSOFT
&& hardware.product == GIP_PRODUCT_ELITE_SERIES_2
&& hardware.version <= GIP_ELITE_SERIES_2_MAX_FIRMWARE;

if (gamepad->supports_share)
input_set_capability(dev, EV_KEY, KEY_RECORD);

if (gamepad->supports_paddles) {
input_set_capability(dev, EV_KEY, BTN_TRIGGER_HAPPY5);
input_set_capability(dev, EV_KEY, BTN_TRIGGER_HAPPY6);
input_set_capability(dev, EV_KEY, BTN_TRIGGER_HAPPY7);
input_set_capability(dev, EV_KEY, BTN_TRIGGER_HAPPY8);
}

input_set_capability(dev, EV_KEY, BTN_MODE);
input_set_capability(dev, EV_KEY, BTN_START);
input_set_capability(dev, EV_KEY, BTN_SELECT);
Expand Down Expand Up @@ -276,6 +303,17 @@ static int gip_gamepad_op_input(struct gip_client *client, void *data, u32 len)
input_report_key(dev, BTN_TR, buttons & GIP_GP_BTN_BUMPER_R);
input_report_key(dev, BTN_THUMBL, buttons & GIP_GP_BTN_STICK_L);
input_report_key(dev, BTN_THUMBR, buttons & GIP_GP_BTN_STICK_R);


if (gamepad->supports_paddles && len > sizeof(struct gip_gamepad_pkt_input)) {
// On the original Elite Series 2 firmware paddles are stored right after other data in the packet
u8 paddles = ((u8 *) data)[sizeof(struct gip_gamepad_pkt_input)];
input_report_key(dev, BTN_TRIGGER_HAPPY5, paddles & GIP_GP_BTN_P1);
input_report_key(dev, BTN_TRIGGER_HAPPY6, paddles & GIP_GP_BTN_P2);
input_report_key(dev, BTN_TRIGGER_HAPPY7, paddles & GIP_GP_BTN_P3);
input_report_key(dev, BTN_TRIGGER_HAPPY8, paddles & GIP_GP_BTN_P4);
}

input_report_abs(dev, ABS_X, (s16)le16_to_cpu(pkt->stick_left_x));
input_report_abs(dev, ABS_RX, (s16)le16_to_cpu(pkt->stick_right_x));
input_report_abs(dev, ABS_Y, ~(s16)le16_to_cpu(pkt->stick_left_y));
Expand Down