drivers/hid/hid-universal-pidff.c

Source file repositories/reference/linux-study-clean/drivers/hid/hid-universal-pidff.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-universal-pidff.c
Extension
.c
Size
6945 bytes
Lines
205
Domain
Driver Families
Bucket
drivers/hid
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((hdev->collection[i].usage & HID_USAGE_PAGE) == HID_UP_PID) {
			error = 0;
			hid_dbg(hdev, "PID usage page found\n");
			break;
		}

	/*
	 * Do not fail as this might be the second "device"
	 * just for additional buttons/axes. Exit cleanly if force
	 * feedback usage page wasn't found (included devices were
	 * tested and confirmed to be USB PID after all).
	 */
	if (error) {
		hid_dbg(hdev, "PID usage page not found in the descriptor\n");
		return 0;
	}

	/* Check if HID_PID support is enabled */
	int (*init_function)(struct hid_device *, u32);

	init_function = hid_pidff_init_with_quirks;
	if (!init_function) {
		hid_warn(hdev, "HID_PID support not enabled!\n");
		return 0;
	}

	error = init_function(hdev, id->driver_data);
	if (error) {
		hid_warn(hdev, "Error initialising force feedback\n");
		goto err;
	}

	hid_info(hdev, "Universal pidff driver loaded successfully!");

	return 0;
err:
	return error;
}

static int universal_pidff_input_configured(struct hid_device *hdev,
					    struct hid_input *hidinput)
{
	int axis;
	struct input_dev *input = hidinput->input;

	if (!input->absinfo)
		return 0;

	/* Decrease fuzz and deadzone on available axes */
	for (axis = ABS_X; axis <= ABS_BRAKE; axis++) {
		if (!test_bit(axis, input->absbit))
			continue;

		input_set_abs_params(input, axis, input->absinfo[axis].minimum,
				     input->absinfo[axis].maximum,
				     axis == ABS_X ? 0 : 8, 0);
	}

	/* Remove fuzz and deadzone from the second joystick axis */
	if (hdev->vendor == USB_VENDOR_ID_FFBEAST &&
	    hdev->product == USB_DEVICE_ID_FFBEAST_JOYSTICK)
		input_set_abs_params(input, ABS_Y,
				     input->absinfo[ABS_Y].minimum,
				     input->absinfo[ABS_Y].maximum, 0, 0);

	return 0;
}

static const struct hid_device_id universal_pidff_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_2),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_2),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_2),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_2),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_2),
	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5) },

Annotation

Implementation Notes