Loading drivers/hid/hid-steam.c +147 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,14 @@ static LIST_HEAD(steam_devices); #define STEAM_DECK_TRIGGER_RESOLUTION 5461 /* Joystick runs are about 5 mm and 32768 units */ #define STEAM_DECK_JOYSTICK_RESOLUTION 6553 /* Accelerometer has 16 bit resolution and a range of +/- 2g */ #define STEAM_DECK_ACCEL_RES_PER_G 16384 #define STEAM_DECK_ACCEL_RANGE 32768 #define STEAM_DECK_ACCEL_FUZZ 32 /* Gyroscope has 16 bit resolution and a range of +/- 2000 dps */ #define STEAM_DECK_GYRO_RES_PER_DPS 16 #define STEAM_DECK_GYRO_RANGE 32768 #define STEAM_DECK_GYRO_FUZZ 1 #define STEAM_PAD_FUZZ 256 Loading Loading @@ -288,6 +296,7 @@ struct steam_device { struct mutex report_mutex; unsigned long client_opened; struct input_dev __rcu *input; struct input_dev __rcu *sensors; unsigned long quirks; struct work_struct work_connect; bool connected; Loading @@ -302,6 +311,7 @@ struct steam_device { struct work_struct rumble_work; u16 rumble_left; u16 rumble_right; unsigned int sensor_timestamp_us; }; static int steam_recv_report(struct steam_device *steam, Loading Loading @@ -825,6 +835,74 @@ static int steam_input_register(struct steam_device *steam) return ret; } static int steam_sensors_register(struct steam_device *steam) { struct hid_device *hdev = steam->hdev; struct input_dev *sensors; int ret; if (!(steam->quirks & STEAM_QUIRK_DECK)) return 0; rcu_read_lock(); sensors = rcu_dereference(steam->sensors); rcu_read_unlock(); if (sensors) { dbg_hid("%s: already connected\n", __func__); return 0; } sensors = input_allocate_device(); if (!sensors) return -ENOMEM; input_set_drvdata(sensors, steam); sensors->dev.parent = &hdev->dev; sensors->name = "Steam Deck Motion Sensors"; sensors->phys = hdev->phys; sensors->uniq = steam->serial_no; sensors->id.bustype = hdev->bus; sensors->id.vendor = hdev->vendor; sensors->id.product = hdev->product; sensors->id.version = hdev->version; __set_bit(INPUT_PROP_ACCELEROMETER, sensors->propbit); __set_bit(EV_MSC, sensors->evbit); __set_bit(MSC_TIMESTAMP, sensors->mscbit); input_set_abs_params(sensors, ABS_X, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_set_abs_params(sensors, ABS_Y, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_set_abs_params(sensors, ABS_Z, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_abs_set_res(sensors, ABS_X, STEAM_DECK_ACCEL_RES_PER_G); input_abs_set_res(sensors, ABS_Y, STEAM_DECK_ACCEL_RES_PER_G); input_abs_set_res(sensors, ABS_Z, STEAM_DECK_ACCEL_RES_PER_G); input_set_abs_params(sensors, ABS_RX, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_set_abs_params(sensors, ABS_RY, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_set_abs_params(sensors, ABS_RZ, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_abs_set_res(sensors, ABS_RX, STEAM_DECK_GYRO_RES_PER_DPS); input_abs_set_res(sensors, ABS_RY, STEAM_DECK_GYRO_RES_PER_DPS); input_abs_set_res(sensors, ABS_RZ, STEAM_DECK_GYRO_RES_PER_DPS); ret = input_register_device(sensors); if (ret) goto sensors_register_fail; rcu_assign_pointer(steam->sensors, sensors); return 0; sensors_register_fail: input_free_device(sensors); return ret; } static void steam_input_unregister(struct steam_device *steam) { struct input_dev *input; Loading @@ -838,6 +916,24 @@ static void steam_input_unregister(struct steam_device *steam) input_unregister_device(input); } static void steam_sensors_unregister(struct steam_device *steam) { struct input_dev *sensors; if (!(steam->quirks & STEAM_QUIRK_DECK)) return; rcu_read_lock(); sensors = rcu_dereference(steam->sensors); rcu_read_unlock(); if (!sensors) return; RCU_INIT_POINTER(steam->sensors, NULL); synchronize_rcu(); input_unregister_device(sensors); } static void steam_battery_unregister(struct steam_device *steam) { struct power_supply *battery; Loading Loading @@ -890,18 +986,28 @@ static int steam_register(struct steam_device *steam) spin_lock_irqsave(&steam->lock, flags); client_opened = steam->client_opened; spin_unlock_irqrestore(&steam->lock, flags); if (!client_opened) { steam_set_lizard_mode(steam, lizard_mode); ret = steam_input_register(steam); } else ret = 0; if (ret != 0) goto steam_register_input_fail; ret = steam_sensors_register(steam); if (ret != 0) goto steam_register_sensors_fail; } return 0; steam_register_sensors_fail: steam_input_unregister(steam); steam_register_input_fail: return ret; } static void steam_unregister(struct steam_device *steam) { steam_battery_unregister(steam); steam_sensors_unregister(steam); steam_input_unregister(steam); if (steam->serial_no[0]) { hid_info(steam->hdev, "Steam Controller '%s' disconnected", Loading Loading @@ -1010,6 +1116,7 @@ static int steam_client_ll_open(struct hid_device *hdev) steam->client_opened++; spin_unlock_irqrestore(&steam->lock, flags); steam_sensors_unregister(steam); steam_input_unregister(steam); return 0; Loading @@ -1030,6 +1137,7 @@ static void steam_client_ll_close(struct hid_device *hdev) if (connected) { steam_set_lizard_mode(steam, lizard_mode); steam_input_register(steam); steam_sensors_register(steam); } } Loading Loading @@ -1121,6 +1229,7 @@ static int steam_probe(struct hid_device *hdev, INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb); INIT_LIST_HEAD(&steam->list); INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); steam->sensor_timestamp_us = 0; /* * With the real steam controller interface, do not connect hidraw. Loading Loading @@ -1380,12 +1489,12 @@ static void steam_do_input_event(struct steam_device *steam, * 18-19 | s16 | ABS_HAT0Y | left-pad Y value * 20-21 | s16 | ABS_HAT1X | right-pad X value * 22-23 | s16 | ABS_HAT1Y | right-pad Y value * 24-25 | s16 | -- | accelerometer X value * 26-27 | s16 | -- | accelerometer Y value * 28-29 | s16 | -- | accelerometer Z value * 30-31 | s16 | -- | gyro X value * 32-33 | s16 | -- | gyro Y value * 34-35 | s16 | -- | gyro Z value * 24-25 | s16 | IMU ABS_X | accelerometer X value * 26-27 | s16 | IMU ABS_Z | accelerometer Y value * 28-29 | s16 | IMU ABS_Y | accelerometer Z value * 30-31 | s16 | IMU ABS_RX | gyro X value * 32-33 | s16 | IMU ABS_RZ | gyro Y value * 34-35 | s16 | IMU ABS_RY | gyro Z value * 36-37 | s16 | -- | quaternion W value * 38-39 | s16 | -- | quaternion X value * 40-41 | s16 | -- | quaternion Y value Loading Loading @@ -1546,6 +1655,32 @@ static void steam_do_deck_input_event(struct steam_device *steam, input_sync(input); } static void steam_do_deck_sensors_event(struct steam_device *steam, struct input_dev *sensors, u8 *data) { /* * The deck input report is received every 4 ms on average, * with a jitter of +/- 4 ms even though the USB descriptor claims * that it uses 1 kHz. * Since the HID report does not include a sensor timestamp, * use a fixed increment here. */ steam->sensor_timestamp_us += 4000; if (!steam->gamepad_mode) return; input_event(sensors, EV_MSC, MSC_TIMESTAMP, steam->sensor_timestamp_us); input_report_abs(sensors, ABS_X, steam_le16(data + 24)); input_report_abs(sensors, ABS_Z, -steam_le16(data + 26)); input_report_abs(sensors, ABS_Y, steam_le16(data + 28)); input_report_abs(sensors, ABS_RX, steam_le16(data + 30)); input_report_abs(sensors, ABS_RZ, -steam_le16(data + 32)); input_report_abs(sensors, ABS_RY, steam_le16(data + 34)); input_sync(sensors); } /* * The size for this message payload is 11. * The known values are: Loading Loading @@ -1583,6 +1718,7 @@ static int steam_raw_event(struct hid_device *hdev, { struct steam_device *steam = hid_get_drvdata(hdev); struct input_dev *input; struct input_dev *sensors; struct power_supply *battery; if (!steam) Loading Loading @@ -1628,6 +1764,9 @@ static int steam_raw_event(struct hid_device *hdev, input = rcu_dereference(steam->input); if (likely(input)) steam_do_deck_input_event(steam, input, data); sensors = rcu_dereference(steam->sensors); if (likely(sensors)) steam_do_deck_sensors_event(steam, sensors, data); rcu_read_unlock(); break; case ID_CONTROLLER_WIRELESS: Loading Loading
drivers/hid/hid-steam.c +147 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,14 @@ static LIST_HEAD(steam_devices); #define STEAM_DECK_TRIGGER_RESOLUTION 5461 /* Joystick runs are about 5 mm and 32768 units */ #define STEAM_DECK_JOYSTICK_RESOLUTION 6553 /* Accelerometer has 16 bit resolution and a range of +/- 2g */ #define STEAM_DECK_ACCEL_RES_PER_G 16384 #define STEAM_DECK_ACCEL_RANGE 32768 #define STEAM_DECK_ACCEL_FUZZ 32 /* Gyroscope has 16 bit resolution and a range of +/- 2000 dps */ #define STEAM_DECK_GYRO_RES_PER_DPS 16 #define STEAM_DECK_GYRO_RANGE 32768 #define STEAM_DECK_GYRO_FUZZ 1 #define STEAM_PAD_FUZZ 256 Loading Loading @@ -288,6 +296,7 @@ struct steam_device { struct mutex report_mutex; unsigned long client_opened; struct input_dev __rcu *input; struct input_dev __rcu *sensors; unsigned long quirks; struct work_struct work_connect; bool connected; Loading @@ -302,6 +311,7 @@ struct steam_device { struct work_struct rumble_work; u16 rumble_left; u16 rumble_right; unsigned int sensor_timestamp_us; }; static int steam_recv_report(struct steam_device *steam, Loading Loading @@ -825,6 +835,74 @@ static int steam_input_register(struct steam_device *steam) return ret; } static int steam_sensors_register(struct steam_device *steam) { struct hid_device *hdev = steam->hdev; struct input_dev *sensors; int ret; if (!(steam->quirks & STEAM_QUIRK_DECK)) return 0; rcu_read_lock(); sensors = rcu_dereference(steam->sensors); rcu_read_unlock(); if (sensors) { dbg_hid("%s: already connected\n", __func__); return 0; } sensors = input_allocate_device(); if (!sensors) return -ENOMEM; input_set_drvdata(sensors, steam); sensors->dev.parent = &hdev->dev; sensors->name = "Steam Deck Motion Sensors"; sensors->phys = hdev->phys; sensors->uniq = steam->serial_no; sensors->id.bustype = hdev->bus; sensors->id.vendor = hdev->vendor; sensors->id.product = hdev->product; sensors->id.version = hdev->version; __set_bit(INPUT_PROP_ACCELEROMETER, sensors->propbit); __set_bit(EV_MSC, sensors->evbit); __set_bit(MSC_TIMESTAMP, sensors->mscbit); input_set_abs_params(sensors, ABS_X, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_set_abs_params(sensors, ABS_Y, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_set_abs_params(sensors, ABS_Z, -STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0); input_abs_set_res(sensors, ABS_X, STEAM_DECK_ACCEL_RES_PER_G); input_abs_set_res(sensors, ABS_Y, STEAM_DECK_ACCEL_RES_PER_G); input_abs_set_res(sensors, ABS_Z, STEAM_DECK_ACCEL_RES_PER_G); input_set_abs_params(sensors, ABS_RX, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_set_abs_params(sensors, ABS_RY, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_set_abs_params(sensors, ABS_RZ, -STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0); input_abs_set_res(sensors, ABS_RX, STEAM_DECK_GYRO_RES_PER_DPS); input_abs_set_res(sensors, ABS_RY, STEAM_DECK_GYRO_RES_PER_DPS); input_abs_set_res(sensors, ABS_RZ, STEAM_DECK_GYRO_RES_PER_DPS); ret = input_register_device(sensors); if (ret) goto sensors_register_fail; rcu_assign_pointer(steam->sensors, sensors); return 0; sensors_register_fail: input_free_device(sensors); return ret; } static void steam_input_unregister(struct steam_device *steam) { struct input_dev *input; Loading @@ -838,6 +916,24 @@ static void steam_input_unregister(struct steam_device *steam) input_unregister_device(input); } static void steam_sensors_unregister(struct steam_device *steam) { struct input_dev *sensors; if (!(steam->quirks & STEAM_QUIRK_DECK)) return; rcu_read_lock(); sensors = rcu_dereference(steam->sensors); rcu_read_unlock(); if (!sensors) return; RCU_INIT_POINTER(steam->sensors, NULL); synchronize_rcu(); input_unregister_device(sensors); } static void steam_battery_unregister(struct steam_device *steam) { struct power_supply *battery; Loading Loading @@ -890,18 +986,28 @@ static int steam_register(struct steam_device *steam) spin_lock_irqsave(&steam->lock, flags); client_opened = steam->client_opened; spin_unlock_irqrestore(&steam->lock, flags); if (!client_opened) { steam_set_lizard_mode(steam, lizard_mode); ret = steam_input_register(steam); } else ret = 0; if (ret != 0) goto steam_register_input_fail; ret = steam_sensors_register(steam); if (ret != 0) goto steam_register_sensors_fail; } return 0; steam_register_sensors_fail: steam_input_unregister(steam); steam_register_input_fail: return ret; } static void steam_unregister(struct steam_device *steam) { steam_battery_unregister(steam); steam_sensors_unregister(steam); steam_input_unregister(steam); if (steam->serial_no[0]) { hid_info(steam->hdev, "Steam Controller '%s' disconnected", Loading Loading @@ -1010,6 +1116,7 @@ static int steam_client_ll_open(struct hid_device *hdev) steam->client_opened++; spin_unlock_irqrestore(&steam->lock, flags); steam_sensors_unregister(steam); steam_input_unregister(steam); return 0; Loading @@ -1030,6 +1137,7 @@ static void steam_client_ll_close(struct hid_device *hdev) if (connected) { steam_set_lizard_mode(steam, lizard_mode); steam_input_register(steam); steam_sensors_register(steam); } } Loading Loading @@ -1121,6 +1229,7 @@ static int steam_probe(struct hid_device *hdev, INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb); INIT_LIST_HEAD(&steam->list); INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); steam->sensor_timestamp_us = 0; /* * With the real steam controller interface, do not connect hidraw. Loading Loading @@ -1380,12 +1489,12 @@ static void steam_do_input_event(struct steam_device *steam, * 18-19 | s16 | ABS_HAT0Y | left-pad Y value * 20-21 | s16 | ABS_HAT1X | right-pad X value * 22-23 | s16 | ABS_HAT1Y | right-pad Y value * 24-25 | s16 | -- | accelerometer X value * 26-27 | s16 | -- | accelerometer Y value * 28-29 | s16 | -- | accelerometer Z value * 30-31 | s16 | -- | gyro X value * 32-33 | s16 | -- | gyro Y value * 34-35 | s16 | -- | gyro Z value * 24-25 | s16 | IMU ABS_X | accelerometer X value * 26-27 | s16 | IMU ABS_Z | accelerometer Y value * 28-29 | s16 | IMU ABS_Y | accelerometer Z value * 30-31 | s16 | IMU ABS_RX | gyro X value * 32-33 | s16 | IMU ABS_RZ | gyro Y value * 34-35 | s16 | IMU ABS_RY | gyro Z value * 36-37 | s16 | -- | quaternion W value * 38-39 | s16 | -- | quaternion X value * 40-41 | s16 | -- | quaternion Y value Loading Loading @@ -1546,6 +1655,32 @@ static void steam_do_deck_input_event(struct steam_device *steam, input_sync(input); } static void steam_do_deck_sensors_event(struct steam_device *steam, struct input_dev *sensors, u8 *data) { /* * The deck input report is received every 4 ms on average, * with a jitter of +/- 4 ms even though the USB descriptor claims * that it uses 1 kHz. * Since the HID report does not include a sensor timestamp, * use a fixed increment here. */ steam->sensor_timestamp_us += 4000; if (!steam->gamepad_mode) return; input_event(sensors, EV_MSC, MSC_TIMESTAMP, steam->sensor_timestamp_us); input_report_abs(sensors, ABS_X, steam_le16(data + 24)); input_report_abs(sensors, ABS_Z, -steam_le16(data + 26)); input_report_abs(sensors, ABS_Y, steam_le16(data + 28)); input_report_abs(sensors, ABS_RX, steam_le16(data + 30)); input_report_abs(sensors, ABS_RZ, -steam_le16(data + 32)); input_report_abs(sensors, ABS_RY, steam_le16(data + 34)); input_sync(sensors); } /* * The size for this message payload is 11. * The known values are: Loading Loading @@ -1583,6 +1718,7 @@ static int steam_raw_event(struct hid_device *hdev, { struct steam_device *steam = hid_get_drvdata(hdev); struct input_dev *input; struct input_dev *sensors; struct power_supply *battery; if (!steam) Loading Loading @@ -1628,6 +1764,9 @@ static int steam_raw_event(struct hid_device *hdev, input = rcu_dereference(steam->input); if (likely(input)) steam_do_deck_input_event(steam, input, data); sensors = rcu_dereference(steam->sensors); if (likely(sensors)) steam_do_deck_sensors_event(steam, sensors, data); rcu_read_unlock(); break; case ID_CONTROLLER_WIRELESS: Loading