STRUCT HID_DRIVER(9)
π struct hid_driver(9) π
okay so bestie, welcome to the struct hid_driver glow-up β this is the Kernel API Manual, and we're about to get so acquainted with every single field in this thing. no skipping, no scrolling past the "boring" parts. we're doing this together, and we're doing it thoroughly. π«Ά
β¨ NAME β¨
struct hid_driver β the driver struct itself. that's it, that's the name. she's iconic, she's a little mysterious, she contains multitudes. π
πΈ SYNOPSIS πΈ
struct hid_driver {
const char *name;
const struct hid_device_id *id_table;
struct list_head dyn_list;
spinlock_t dyn_lock;
bool (*match)(struct hid_device *dev, bool ignore_special_driver);
int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
void (*remove)(struct hid_device *dev);
const struct hid_report_id *report_table;
int (*raw_event)(struct hid_device *hdev, struct hid_report *report, u8 *data, int size);
const struct hid_usage_id *usage_table;
int (*event)(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value);
void (*report)(struct hid_device *hdev, struct hid_report *report);
const __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf,
unsigned int *size);
int (*input_mapping)(struct hid_device *hdev, struct hid_input *hidinput,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max);
int (*input_mapped)(struct hid_device *hdev, struct hid_input *hidinput,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max);
int (*input_configured)(struct hid_device *hdev, struct hid_input *hidinput);
void (*feature_mapping)(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage);
int (*suspend)(struct hid_device *hdev, pm_message_t message);
int (*resume)(struct hid_device *hdev);
int (*reset_resume)(struct hid_device *hdev);
void (*on_hid_hw_open)(struct hid_device *hdev);
void (*on_hid_hw_close)(struct hid_device *hdev);
};
π Members π
okay now the main character energy really kicks in β one by one, no cap:
nameβ the driver's name. literally her government name, like"Footech_bar-wheel". πid_tableβ which devices is this driver even for?? this is the list. and heads up: it must be non-NULL forprobeto be called. no id_table, no probe. periodt.dyn_listβ the list of dynamically added device ids. the guest list, if you will. πdyn_lockβ the lock protectingdyn_list. somebody has to guard the guest list. πmatchβ checks if the given device is handled by this driver.probeβ new device inserted. the big moment. the meet-cute. β¨removeβ device removed. it'sNULLif the driver isn't hot-plug capable. πreport_tableβ which reports to callraw_eventon.NULLmeans all of them.raw_eventβ if the report is inreport_table, this hook gets called.NULLmeans nop.usage_tableβ which events to calleventon.NULLmeans all.eventβ if the usage is inusage_table, this hook gets called.NULLmeans nop.reportβ called after parsing a report.NULLmeans nop.report_fixupβ called before report descriptor parsing.NULLmeans nop.input_mappingβ invoked on input registering, before mapping a usage.input_mappedβ invoked on input registering, after mapping a usage.input_configuredβ invoked just before the device is registered.feature_mappingβ invoked on feature registering.suspendβ invoked on suspend.NULLmeans nop. π΄resumeβ invoked on resume if the device was not reset.NULLmeans nop. βοΈreset_resumeβ invoked on resume if the device was reset.NULLmeans nop. πon_hid_hw_openβ invoked when hid core opens the first instance.NULLmeans nop.on_hid_hw_closeβ invoked when hid core closes the last instance.NULLmeans nop.
π¦ Description π¦
okay so here's where the rules live, and bestie, you gotta know these:
probe should return -errno on error, or 0 on success. and listen β during probe, input will not be passed to raw_event unless hid_device_io_start is called. so if you're wondering why nothing's coming through, that's why. π
raw_event and event should return negative on error. any other value will pass the event on to .event β which typically returns 0 for success. simple as that.
report_fixup must return a report descriptor pointer whose lifetime is at least that of the input rdesc. this is usually done by mutating the input rdesc and returning it, or returning a sub-portion of it. and in case a new buffer is allocated and returned, the implementation of report_fixup is responsible for freeing it later. no takebacks, no leaks β that's on you. π
input_mapping shall return:
- a negative value to completely ignore this usage (e.g. doubled or invalid usage),
- zero to continue with parsing of this usage by generic code (no special handling needed), or
- a positive value to skip generic parsing (needed special handling which was done in the hook already).
input_mapped shall return negative to inform the layer that this usage should not be considered for further processing, or zero to notify that no processing was performed and it should be done in a generic manner.
both these functions may be NULL, which means the same behavior as returning zero from them. so like, no function = chill vibes, zero. π§
π SEE ALSO π
go read the source, bestie β Kernel file ./include/linux/hid.h β plus all these baddies:
HID quirks(9), struct hid_battery(9), struct hid_ll_driver(9), module_hid_driver(9), hid_device_io_start(9), hid_device_io_stop(9), hid_map_usage(9), hid_map_usage_clear(9), hid_parse(9), hid_hw_power(9), hid_hw_idle(9), hid_hw_may_wakeup(9), hid_hw_wait(9), hid_report_len(9)
fr fr though β go actually read ./include/linux/hid.h before you go poking at any of these hooks. the manpage is the vibe check, the header is the whole personality. π
and that's the whole page, bestie! π this one came from ./include/linux, dated October 2026, and it's struct hid_driver(9) β Kernel API Manual energy from start to finish. slay, go write a driver, and remember: NULL means nop. ππβ
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms