STRUCT RC_DEV(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

✨ struct rc_dev(9) ✨

okay bestie, so this is literally the blueprint for a remote control device in the kernel β€” the struct rc_dev is what represents an RC device and it's giving main character energy in ./include/media/rc-core.h. we're talking Kernel API Manual vibes, and i'm gonna walk you through every single member because there are a LOT and they all matter, no cap πŸ’…


🌸 SYNOPSIS 🌸

like, here's the whole struct in all its glory β€” every field, every callback, exactly as it lives in the header. don't skip any of it, bestie, it's all important:

struct rc_dev {
    struct device                   dev;
    bool registered;
    bool idle;
    bool encode_wakeup;
    unsigned int                    minor;
    const struct attribute_group    *sysfs_groups[5];
    const char                      *device_name;
    const char                      *input_phys;
    struct input_id                 input_id;
    const char                      *driver_name;
    const char                      *map_name;
    struct rc_map                   rc_map;
    struct mutex                    lock;
    struct ir_raw_event_ctrl        *raw;
    struct input_dev                *input_dev;
    enum rc_driver_type             driver_type;
    u32 users;
    u64 allowed_protocols;
    u64 enabled_protocols;
    u64 allowed_wakeup_protocols;
    enum rc_proto                   wakeup_protocol;
    struct rc_scancode_filter       scancode_filter;
    struct rc_scancode_filter       scancode_wakeup_filter;
    u32 scancode_mask;
    void *priv;
    spinlock_t keylock;
    bool keypressed;
    u8 last_toggle;
    u32 last_keycode;
    enum rc_proto                   last_protocol;
    u64 last_scancode;
    unsigned long                   keyup_jiffies;
    struct timer_list               timer_keyup;
    struct timer_list               timer_repeat;
    u32 timeout;
    u32 min_timeout;
    u32 max_timeout;
    u32 rx_resolution;
  #ifdef CONFIG_LIRC;
    struct device                   lirc_dev;
    struct cdev                     lirc_cdev;
    ktime_t gap_start;
    spinlock_t lirc_fh_lock;
    struct list_head                lirc_fh;
  #endif;
    int (*change_protocol)(struct rc_dev *dev, u64 *rc_proto);
    int (*open)(struct rc_dev *dev);
    void (*close)(struct rc_dev *dev);
    int (*s_tx_mask)(struct rc_dev *dev, u32 mask);
    int (*s_tx_carrier)(struct rc_dev *dev, u32 carrier);
    int (*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
    int (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
    int (*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
    void (*s_idle)(struct rc_dev *dev, bool enable);
    int (*s_wideband_receiver)(struct rc_dev *dev, int enable);
    int (*s_carrier_report) (struct rc_dev *dev, int enable);
    int (*s_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
    int (*s_wakeup_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
    int (*s_timeout)(struct rc_dev *dev, unsigned int timeout);
 };

πŸŽ€ Members πŸŽ€

okay so now we're getting into the actual members one by one. this is the part where you really get to know your rc_dev, bestie. every single one, let's go ✨

  • dev β€” the driver model's view of this device. like, this is how the rest of the kernel sees it, periodt.
  • registered β€” set to true by rc_register_device, and false by rc_unregister_device. it's the "are we live yet" flag basically πŸ’–
  • idle β€” used to keep track of RX state. lowkey just a little bookkeeping buddy.
  • encode_wakeup β€” wakeup filtering uses the IR encode API, so the allowed wakeup protocols is literally the set of all raw encoders. iykyk 🌈
  • minor β€” unique minor remote control device number. everyone gets their own number, no sharing πŸŽ€
  • sysfs_groups β€” sysfs attribute groups. the whole array of them.
  • device_name β€” name of the rc child device.
  • input_phys β€” physical path to the input child device.
  • input_id β€” id of the input child device, and it's a struct input_id.
  • driver_name β€” name of the hardware driver which registered this device. like, who's your parent, bestie?
  • map_name β€” name of the default keymap.
  • rc_map β€” current scan/key table.
  • lock β€” used to ensure we've filled in all protocol details before anyone can call show_protocols or store_protocols. so like, nobody jumps the gun, okay? πŸ”’
  • raw β€” additional data for raw pulse/space devices.
  • input_dev β€” the input child device used to communicate events to userspace. this is the messenger to the outside world πŸ¦‹
  • driver_type β€” specifies if protocol decoding is done in hardware or software. hardware girlies vs software girlies, both valid πŸ’…
  • users β€” number of current users of the device.
  • allowed_protocols β€” bitmask with the supported RC_PROTO_BIT_* protocols.
  • enabled_protocols β€” bitmask with the enabled RC_PROTO_BIT_* protocols.
  • allowed_wakeup_protocols β€” bitmask with the supported RC_PROTO_BIT_* wakeup protocols.
  • wakeup_protocol β€” the enabled RC_PROTO_* wakeup protocol, or RC_PROTO_UNKNOWN if it's disabled. like, it's either on with a real protocol or it's giving unknown energy πŸ™ˆ
  • scancode_filter β€” scancode filter.
  • scancode_wakeup_filter β€” scancode wakeup filters.
  • scancode_mask β€” okay so this one is a whole thing: some hardware decoders are not capable of providing the full scancode to the application. as this is a hardware limit, we can't do anything with it. yet, as the same keycode table can be used with other devices, a mask is provided to allow its usage. drivers should generally leave this field in blank. so like, drivers, don't touch unless you know what you're doing, fr fr ⚠️
  • priv β€” driver-specific data. it's giving "my own little corner" energy.
  • keylock β€” protects the remaining members of the struct. it's the bodyguard for everything after this point πŸ”
  • keypressed β€” whether a key is currently pressed.
  • last_toggle β€” toggle value of last command.
  • last_keycode β€” keycode of last keypress.
  • last_protocol β€” protocol of last keypress.
  • last_scancode β€” scancode of last keypress.
  • keyup_jiffies β€” time (in jiffies) when the current keypress should be released. like a little countdown timer, but in kernel time ⏳
  • timer_keyup β€” timer for releasing a keypress.
  • timer_repeat β€” timer for autorepeat events. this is needed for CEC, which has non-standard repeats. so don't @ me about it, it's a CEC thing πŸ’€
  • timeout β€” optional time after which device stops sending data.
  • min_timeout β€” minimum timeout supported by device.
  • max_timeout β€” maximum timeout supported by device.
  • rx_resolution β€” resolution (in us) of input sampler.
  • lirc_dev β€” lirc device. (this one lives inside the #ifdef CONFIG_LIRC block, so it's conditional bestie)
  • lirc_cdev β€” lirc char cdev.
  • gap_start β€” start time for gap after timeout if non-zero.
  • lirc_fh_lock β€” protects lirc_fh list.
  • lirc_fh β€” list of open files.

okay now we're into the callback members, which are like the action functions of the struct. these are the ones that actually DO stuff when the kernel calls them. slay πŸ’–

  • change_protocol β€” allow changing the protocol used on hardware decoders. it takes struct rc_dev *dev, u64 *rc_proto.
  • open β€” callback to allow drivers to enable polling/irq when IR input device is opened. (yes the original says "when IR input device is opened" β€” i'm just giving you the facts, bestie)
  • close β€” callback to allow drivers to disable polling/irq when IR input device is opened. again, that's what it says β€” i'm not fixing it, i'm just the messenger 🫢
  • s_tx_mask β€” set transmitter mask (for devices with multiple tx outputs).
  • s_tx_carrier β€” set transmit carrier frequency.
  • s_tx_duty_cycle β€” set transmit duty cycle (0% - 100%). literally zero to a hundred, periodt.
  • s_rx_carrier_range β€” inform driver about carrier it is expected to handle.
  • tx_ir β€” transmit IR.
  • s_idle β€” enable/disable hardware idle mode, upon which, device doesn't interrupt host until it sees IR pulses. so it's like "shh, don't bother the host until something actually happens" energy 😴
  • s_wideband_receiver β€” enable wide band receiver used for learning.
  • s_carrier_report β€” enable carrier reports.
  • s_filter β€” set the scancode filter.
  • s_wakeup_filter β€” set the wakeup scancode filter. if the mask is zero then wakeup should be disabled. wakeup_protocol will be set to a valid protocol if mask is nonzero. important detail bestie β€” zero mask means no wakeup, no cap πŸ’…
  • s_timeout β€” set hardware timeout in us.

πŸ‘€ SEE ALSO πŸ‘€

okay so if you want to go deeper (and you KNOW you do), the kernel file to look at is ./include/media/rc-core.h, and these are the related pages you should absolutely check out, bestie:


that's the whole page, bestie! now go forth and register some remote control devices with confidence πŸ¦‹βœ¨

source: ./include/media β€” version date: October 2026 β€” struct rc_dev(9) πŸ’œ

πŸ“¦ where this page comes from