drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c

Source file repositories/reference/linux-study-clean/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
Extension
.c
Size
4630 bytes
Lines
178
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

struct wacom_params {
	__u16 pid;
	__u16 rdesc_len;
	__u8 report_id;
	__u8 report_len;
	struct {
		__u8 tip_switch;
		__u8 pressure;
		__u8 tool_type;
	} offsets;
};

/*
 * Multiple device can support the same stylus, so
 * we need to know which device has which offsets
 */
static const struct wacom_params devices[] = {
	{
		.pid = PID_INTUOS_PRO_2_M,
		.rdesc_len = 949,
		.report_id = 16,
		.report_len = 27,
		.offsets = {
			.tip_switch = 1,
			.pressure = 8,
			.tool_type = 25,
		},
	},
};

static struct wacom_params params = { 0 };

/* HID-BPF reports a 64 bytes chunk anyway, so this ensures
 * the verifier to know we are addressing the memory correctly
 */
#define PEN_REPORT_LEN		64

/* only odd frames are modified */
static bool odd;

static __u16 prev_pressure;

static inline void *get_bits(__u8 *data, unsigned int byte_offset)
{
	return data + byte_offset;
}

static inline __u16 *get_u16(__u8 *data, unsigned int offset)
{
	return (__u16 *)get_bits(data, offset);
}

static inline __u8 *get_u8(__u8 *data, unsigned int offset)
{
	return (__u8 *)get_bits(data, offset);
}

SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
{
	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PEN_REPORT_LEN /* size */);
	__u16 *pressure, *tool_type;
	__u8 *tip_switch;

	if (!data)
		return 0; /* EPERM check */

	if (data[0] != params.report_id ||
	    params.offsets.tip_switch >= PEN_REPORT_LEN ||
	    params.offsets.pressure >= PEN_REPORT_LEN - 1 ||
	    params.offsets.tool_type >= PEN_REPORT_LEN - 1)
		return 0; /* invalid report or parameters */

	tool_type = get_u16(data, params.offsets.tool_type);
	if (*tool_type != ART_PEN_ID)
		return 0;

	tip_switch = get_u8(data, params.offsets.tip_switch);
	if ((*tip_switch & 0x01) == 0) {
		prev_pressure = 0;
		odd = true;
		return 0;
	}

	pressure = get_u16(data, params.offsets.pressure);

	if (odd)
		*pressure = (*pressure + prev_pressure) / 2;

	prev_pressure = *pressure;

Annotation

Implementation Notes