static int joycon_input_create()

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;
}