in hid-nintendo.c [1591:1755]
static int joycon_input_create(struct joycon_ctlr *ctlr)
{
struct hid_device *hdev;
const char *name;
const char *imu_name;
int ret;
int i;
hdev = ctlr->hdev;
switch (hdev->product) {
case USB_DEVICE_ID_NINTENDO_PROCON:
name = "Nintendo Switch Pro Controller";
imu_name = "Nintendo Switch Pro Controller IMU";
break;
case USB_DEVICE_ID_NINTENDO_CHRGGRIP:
if (jc_type_has_left(ctlr)) {
name = "Nintendo Switch Left Joy-Con (Grip)";
imu_name = "Nintendo Switch Left Joy-Con IMU (Grip)";
} else {
name = "Nintendo Switch Right Joy-Con (Grip)";
imu_name = "Nintendo Switch Right Joy-Con IMU (Grip)";
}
break;
case USB_DEVICE_ID_NINTENDO_JOYCONL:
name = "Nintendo Switch Left Joy-Con";
imu_name = "Nintendo Switch Left Joy-Con IMU";
break;
case USB_DEVICE_ID_NINTENDO_JOYCONR:
name = "Nintendo Switch Right Joy-Con";
imu_name = "Nintendo Switch Right Joy-Con IMU";
break;
default: /* Should be impossible */
hid_err(hdev, "Invalid hid product\n");
return -EINVAL;
}
ctlr->input = devm_input_allocate_device(&hdev->dev);
if (!ctlr->input)
return -ENOMEM;
ctlr->input->id.bustype = hdev->bus;
ctlr->input->id.vendor = hdev->vendor;
ctlr->input->id.product = hdev->product;
ctlr->input->id.version = hdev->version;
ctlr->input->uniq = ctlr->mac_addr_str;
ctlr->input->name = name;
input_set_drvdata(ctlr->input, ctlr);
/* set up sticks and buttons */
if (jc_type_has_left(ctlr)) {
input_set_abs_params(ctlr->input, ABS_X,
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
JC_STICK_FUZZ, JC_STICK_FLAT);
input_set_abs_params(ctlr->input, ABS_Y,
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
JC_STICK_FUZZ, JC_STICK_FLAT);
for (i = 0; joycon_button_inputs_l[i] > 0; i++)
input_set_capability(ctlr->input, EV_KEY,
joycon_button_inputs_l[i]);
/* configure d-pad differently for joy-con vs pro controller */
if (hdev->product != USB_DEVICE_ID_NINTENDO_PROCON) {
for (i = 0; joycon_dpad_inputs_jc[i] > 0; i++)
input_set_capability(ctlr->input, EV_KEY,
joycon_dpad_inputs_jc[i]);
} else {
input_set_abs_params(ctlr->input, ABS_HAT0X,
-JC_MAX_DPAD_MAG, JC_MAX_DPAD_MAG,
JC_DPAD_FUZZ, JC_DPAD_FLAT);
input_set_abs_params(ctlr->input, ABS_HAT0Y,
-JC_MAX_DPAD_MAG, JC_MAX_DPAD_MAG,
JC_DPAD_FUZZ, JC_DPAD_FLAT);
}
}
if (jc_type_has_right(ctlr)) {
input_set_abs_params(ctlr->input, ABS_RX,
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
JC_STICK_FUZZ, JC_STICK_FLAT);
input_set_abs_params(ctlr->input, ABS_RY,
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
JC_STICK_FUZZ, JC_STICK_FLAT);
for (i = 0; joycon_button_inputs_r[i] > 0; i++)
input_set_capability(ctlr->input, EV_KEY,
joycon_button_inputs_r[i]);
}
/* Let's report joy-con S triggers separately */
if (hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONL) {
input_set_capability(ctlr->input, EV_KEY, BTN_TR);
input_set_capability(ctlr->input, EV_KEY, BTN_TR2);
} else if (hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONR) {
input_set_capability(ctlr->input, EV_KEY, BTN_TL);
input_set_capability(ctlr->input, EV_KEY, BTN_TL2);
}
#if IS_ENABLED(CONFIG_NINTENDO_FF)
/* set up rumble */
input_set_capability(ctlr->input, EV_FF, FF_RUMBLE);
input_ff_create_memless(ctlr->input, NULL, joycon_play_effect);
ctlr->rumble_ll_freq = JC_RUMBLE_DFLT_LOW_FREQ;
ctlr->rumble_lh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
ctlr->rumble_rl_freq = JC_RUMBLE_DFLT_LOW_FREQ;
ctlr->rumble_rh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
joycon_clamp_rumble_freqs(ctlr);
joycon_set_rumble(ctlr, 0, 0, false);
ctlr->rumble_msecs = jiffies_to_msecs(jiffies);
#endif
ret = input_register_device(ctlr->input);
if (ret)
return ret;
/* configure the imu input device */
ctlr->imu_input = devm_input_allocate_device(&hdev->dev);
if (!ctlr->imu_input)
return -ENOMEM;
ctlr->imu_input->id.bustype = hdev->bus;
ctlr->imu_input->id.vendor = hdev->vendor;
ctlr->imu_input->id.product = hdev->product;
ctlr->imu_input->id.version = hdev->version;
ctlr->imu_input->uniq = ctlr->mac_addr_str;
ctlr->imu_input->name = imu_name;
input_set_drvdata(ctlr->imu_input, ctlr);
/* configure imu axes */
input_set_abs_params(ctlr->imu_input, ABS_X,
-JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG,
JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT);
input_set_abs_params(ctlr->imu_input, ABS_Y,
-JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG,
JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT);
input_set_abs_params(ctlr->imu_input, ABS_Z,
-JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG,
JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT);
input_abs_set_res(ctlr->imu_input, ABS_X, JC_IMU_ACCEL_RES_PER_G);
input_abs_set_res(ctlr->imu_input, ABS_Y, JC_IMU_ACCEL_RES_PER_G);
input_abs_set_res(ctlr->imu_input, ABS_Z, JC_IMU_ACCEL_RES_PER_G);
input_set_abs_params(ctlr->imu_input, ABS_RX,
-JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG,
JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT);
input_set_abs_params(ctlr->imu_input, ABS_RY,
-JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG,
JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT);
input_set_abs_params(ctlr->imu_input, ABS_RZ,
-JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG,
JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT);
input_abs_set_res(ctlr->imu_input, ABS_RX, JC_IMU_GYRO_RES_PER_DPS);
input_abs_set_res(ctlr->imu_input, ABS_RY, JC_IMU_GYRO_RES_PER_DPS);
input_abs_set_res(ctlr->imu_input, ABS_RZ, JC_IMU_GYRO_RES_PER_DPS);
__set_bit(EV_MSC, ctlr->imu_input->evbit);
__set_bit(MSC_TIMESTAMP, ctlr->imu_input->mscbit);
__set_bit(INPUT_PROP_ACCELEROMETER, ctlr->imu_input->propbit);
ret = input_register_device(ctlr->imu_input);
if (ret)
return ret;
return 0;
}