Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lirc ioctl decoding #208

Merged
merged 1 commit into from Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -11,6 +11,7 @@ Noteworthy changes in release ?.?? (????-??-??)
attributes.
* Implemented decoding of PR_SET_VMA operation of prctl syscall.
* Implemented decoding of siginfo_t.si_pkey field.
* Implemented decoding of LIRC ioctl commands.
* Updated lists of FAN_*, IORING_*, IOSQE_*, KVM_*, MODULE_INIT_*, TCA_ACT_*,
and *_MAGIC constants.

Expand Down
1 change: 1 addition & 0 deletions bundled/Makefile.am
Expand Up @@ -60,6 +60,7 @@ EXTRA_DIST = \
linux/include/uapi/linux/keyctl.h \
linux/include/uapi/linux/landlock.h \
linux/include/uapi/linux/libc-compat.h \
linux/include/uapi/linux/lirc.h \
linux/include/uapi/linux/loop.h \
linux/include/uapi/linux/mctp.h \
linux/include/uapi/linux/memfd.h \
Expand Down
232 changes: 232 additions & 0 deletions bundled/linux/include/uapi/linux/lirc.h
@@ -0,0 +1,232 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* lirc.h - linux infrared remote control header file
*/

#ifndef _LINUX_LIRC_H
#define _LINUX_LIRC_H

#include <linux/types.h>
#include <linux/ioctl.h>

#define PULSE_BIT 0x01000000
#define PULSE_MASK 0x00FFFFFF

#define LIRC_MODE2_SPACE 0x00000000
#define LIRC_MODE2_PULSE 0x01000000
#define LIRC_MODE2_FREQUENCY 0x02000000
#define LIRC_MODE2_TIMEOUT 0x03000000

#define LIRC_VALUE_MASK 0x00FFFFFF
#define LIRC_MODE2_MASK 0xFF000000

#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)
#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY)
#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT)

#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK)
#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK)

#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE)
#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE)
#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY)
#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT)

/* used heavily by lirc userspace */
#define lirc_t int

/*** lirc compatible hardware features ***/

#define LIRC_MODE2SEND(x) (x)
#define LIRC_SEND2MODE(x) (x)
#define LIRC_MODE2REC(x) ((x) << 16)
#define LIRC_REC2MODE(x) ((x) >> 16)

#define LIRC_MODE_RAW 0x00000001
#define LIRC_MODE_PULSE 0x00000002
#define LIRC_MODE_MODE2 0x00000004
#define LIRC_MODE_SCANCODE 0x00000008
#define LIRC_MODE_LIRCCODE 0x00000010


#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW)
#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE)
#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2)
#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)

#define LIRC_CAN_SEND_MASK 0x0000003f

#define LIRC_CAN_SET_SEND_CARRIER 0x00000100
#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200
#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400

#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW)
#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE)
#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2)
#define LIRC_CAN_REC_SCANCODE LIRC_MODE2REC(LIRC_MODE_SCANCODE)
#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE)

#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK)

#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16)
#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)

#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000
#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000
#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000
#define LIRC_CAN_SET_REC_FILTER 0x08000000

#define LIRC_CAN_MEASURE_CARRIER 0x02000000
#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000

#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)

#define LIRC_CAN_NOTIFY_DECODE 0x01000000

/*** IOCTL commands for lirc driver ***/

#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32)

#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32)
#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32)
#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32)

#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32)
#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32)

/* code length in bits, currently only for LIRC_MODE_LIRCCODE */
#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32)

#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32)
#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32)
/* Note: these can reset the according pulse_width */
#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32)
#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32)
#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32)
#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32)

/*
* when a timeout != 0 is set the driver will send a
* LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is
* never sent, timeout is disabled by default
*/
#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32)

/* 1 enables, 0 disables timeout reports in MODE2 */
#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32)

/*
* if enabled from the next key press on the driver will send
* LIRC_MODE2_FREQUENCY packets
*/
#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32)

/*
* to set a range use LIRC_SET_REC_CARRIER_RANGE with the
* lower bound first and later LIRC_SET_REC_CARRIER with the upper bound
*/
#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32)

#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32)

/*
* Return the recording timeout, which is either set by
* the ioctl LIRC_SET_REC_TIMEOUT or by the kernel after setting the protocols.
*/
#define LIRC_GET_REC_TIMEOUT _IOR('i', 0x00000024, __u32)

/**
* struct lirc_scancode - decoded scancode with protocol for use with
* LIRC_MODE_SCANCODE
*
* @timestamp: Timestamp in nanoseconds using CLOCK_MONOTONIC when IR
* was decoded.
* @flags: should be 0 for transmit. When receiving scancodes,
* LIRC_SCANCODE_FLAG_TOGGLE or LIRC_SCANCODE_FLAG_REPEAT can be set
* depending on the protocol
* @rc_proto: see enum rc_proto
* @keycode: the translated keycode. Set to 0 for transmit.
* @scancode: the scancode received or to be sent
*/
struct lirc_scancode {
__u64 timestamp;
__u16 flags;
__u16 rc_proto;
__u32 keycode;
__u64 scancode;
};

/* Set if the toggle bit of rc-5 or rc-6 is enabled */
#define LIRC_SCANCODE_FLAG_TOGGLE 1
/* Set if this is a nec or sanyo repeat */
#define LIRC_SCANCODE_FLAG_REPEAT 2

/**
* enum rc_proto - the Remote Controller protocol
*
* @RC_PROTO_UNKNOWN: Protocol not known
* @RC_PROTO_OTHER: Protocol known but proprietary
* @RC_PROTO_RC5: Philips RC5 protocol
* @RC_PROTO_RC5X_20: Philips RC5x 20 bit protocol
* @RC_PROTO_RC5_SZ: StreamZap variant of RC5
* @RC_PROTO_JVC: JVC protocol
* @RC_PROTO_SONY12: Sony 12 bit protocol
* @RC_PROTO_SONY15: Sony 15 bit protocol
* @RC_PROTO_SONY20: Sony 20 bit protocol
* @RC_PROTO_NEC: NEC protocol
* @RC_PROTO_NECX: Extended NEC protocol
* @RC_PROTO_NEC32: NEC 32 bit protocol
* @RC_PROTO_SANYO: Sanyo protocol
* @RC_PROTO_MCIR2_KBD: RC6-ish MCE keyboard
* @RC_PROTO_MCIR2_MSE: RC6-ish MCE mouse
* @RC_PROTO_RC6_0: Philips RC6-0-16 protocol
* @RC_PROTO_RC6_6A_20: Philips RC6-6A-20 protocol
* @RC_PROTO_RC6_6A_24: Philips RC6-6A-24 protocol
* @RC_PROTO_RC6_6A_32: Philips RC6-6A-32 protocol
* @RC_PROTO_RC6_MCE: MCE (Philips RC6-6A-32 subtype) protocol
* @RC_PROTO_SHARP: Sharp protocol
* @RC_PROTO_XMP: XMP protocol
* @RC_PROTO_CEC: CEC protocol
* @RC_PROTO_IMON: iMon Pad protocol
* @RC_PROTO_RCMM12: RC-MM protocol 12 bits
* @RC_PROTO_RCMM24: RC-MM protocol 24 bits
* @RC_PROTO_RCMM32: RC-MM protocol 32 bits
* @RC_PROTO_XBOX_DVD: Xbox DVD Movie Playback Kit protocol
* @RC_PROTO_MAX: Maximum value of enum rc_proto
*/
enum rc_proto {
RC_PROTO_UNKNOWN = 0,
RC_PROTO_OTHER = 1,
RC_PROTO_RC5 = 2,
RC_PROTO_RC5X_20 = 3,
RC_PROTO_RC5_SZ = 4,
RC_PROTO_JVC = 5,
RC_PROTO_SONY12 = 6,
RC_PROTO_SONY15 = 7,
RC_PROTO_SONY20 = 8,
RC_PROTO_NEC = 9,
RC_PROTO_NECX = 10,
RC_PROTO_NEC32 = 11,
RC_PROTO_SANYO = 12,
RC_PROTO_MCIR2_KBD = 13,
RC_PROTO_MCIR2_MSE = 14,
RC_PROTO_RC6_0 = 15,
RC_PROTO_RC6_6A_20 = 16,
RC_PROTO_RC6_6A_24 = 17,
RC_PROTO_RC6_6A_32 = 18,
RC_PROTO_RC6_MCE = 19,
RC_PROTO_SHARP = 20,
RC_PROTO_XMP = 21,
RC_PROTO_CEC = 22,
RC_PROTO_IMON = 23,
RC_PROTO_RCMM12 = 24,
RC_PROTO_RCMM24 = 25,
RC_PROTO_RCMM32 = 26,
RC_PROTO_XBOX_DVD = 27,
RC_PROTO_MAX = RC_PROTO_XBOX_DVD,
};

#endif
1 change: 1 addition & 0 deletions src/Makefile.am
Expand Up @@ -184,6 +184,7 @@ libstrace_a_SOURCES = \
link.c \
linux/x32/asm_stat.h \
linux/x86_64/asm_stat.h \
lirc_ioctl.c \
list.h \
listen.c \
lookup_dcookie.c \
Expand Down
1 change: 1 addition & 0 deletions src/defs.h
Expand Up @@ -1362,6 +1362,7 @@ DECL_IOCTL(gpio);
DECL_IOCTL(inotify);
DECL_IOCTL(kd);
DECL_IOCTL(kvm);
DECL_IOCTL(lirc);
DECL_IOCTL(nbd);
DECL_IOCTL(nsfs);
DECL_IOCTL(ptp);
Expand Down
2 changes: 2 additions & 0 deletions src/ioctl.c
Expand Up @@ -386,6 +386,8 @@ ioctl_decode(struct tcb *tcp)
return fs_x_ioctl(tcp, code, arg);
case 'f':
return f_ioctl(tcp, code, arg);
case 'i':
return lirc_ioctl(tcp, code, arg);
case 'o':
return ubi_ioctl(tcp, code, arg);
case 'p':
Expand Down
75 changes: 75 additions & 0 deletions src/lirc_ioctl.c
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2022 Sean Young <sean@mess.org>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include "defs.h"
#include <linux/lirc.h>
#include "xlat/lirc_features.h"
#include "xlat/lirc_modes.h"

int
lirc_ioctl(struct tcb *const tcp, const unsigned int code,
const kernel_ulong_t arg)
{
unsigned int value;

switch (code) {
case LIRC_GET_FEATURES:
case LIRC_GET_SEND_MODE:
case LIRC_GET_REC_MODE:
case LIRC_GET_REC_RESOLUTION:
case LIRC_GET_MIN_TIMEOUT:
case LIRC_GET_MAX_TIMEOUT:
case LIRC_GET_LENGTH:
case LIRC_SET_SEND_MODE:
case LIRC_SET_REC_MODE:
case LIRC_SET_SEND_CARRIER:
case LIRC_SET_REC_CARRIER:
case LIRC_SET_SEND_DUTY_CYCLE:
case LIRC_SET_TRANSMITTER_MASK:
case LIRC_SET_REC_TIMEOUT:
case LIRC_SET_REC_TIMEOUT_REPORTS:
case LIRC_SET_MEASURE_CARRIER_MODE:
case LIRC_SET_REC_CARRIER_RANGE:
case LIRC_SET_WIDEBAND_RECEIVER:
case LIRC_GET_REC_TIMEOUT:
break;
default:
return RVAL_DECODED;
}

if (entering(tcp)) {
tprint_arg_next();
if (_IOC_DIR(code) == _IOC_READ)
return 0;
}

if (umove_or_printaddr(tcp, arg, &value))
return RVAL_IOCTL_DECODED;

tprint_indirect_begin();

switch (code) {
case LIRC_GET_FEATURES:
printflags(lirc_features, value, "LIRC_CAN_???");
break;
case LIRC_GET_SEND_MODE:
case LIRC_GET_REC_MODE:
case LIRC_SET_SEND_MODE:
case LIRC_SET_REC_MODE:
printxval(lirc_modes, value, "LIRC_MODE_???");
break;
case LIRC_SET_TRANSMITTER_MASK:
PRINT_VAL_X(value);
break;
default:
PRINT_VAL_U(value);
break;
}

tprint_indirect_end();

return RVAL_IOCTL_DECODED;
}
15 changes: 15 additions & 0 deletions src/xlat/lirc_features.in
@@ -0,0 +1,15 @@
#unconditional
LIRC_CAN_SEND_PULSE
LIRC_CAN_SEND_LIRCCODE
LIRC_CAN_SET_SEND_CARRIER
LIRC_CAN_SET_SEND_DUTY_CYCLE
LIRC_CAN_SET_TRANSMITTER_MASK
LIRC_CAN_REC_MODE2
LIRC_CAN_REC_SCANCODE
LIRC_CAN_REC_LIRCCODE
LIRC_CAN_SET_REC_CARRIER
LIRC_CAN_MEASURE_CARRIER
LIRC_CAN_USE_WIDEBAND_RECEIVER
LIRC_CAN_SET_REC_TIMEOUT
LIRC_CAN_GET_REC_RESOLUTION
LIRC_CAN_SET_REC_CARRIER_RANGE
6 changes: 6 additions & 0 deletions src/xlat/lirc_modes.in
@@ -0,0 +1,6 @@
#unconditional
LIRC_MODE_RAW
LIRC_MODE_PULSE
LIRC_MODE_MODE2
LIRC_MODE_SCANCODE
LIRC_MODE_LIRCCODE
2 changes: 2 additions & 0 deletions tests/.gitignore
Expand Up @@ -325,6 +325,8 @@ ioctl_kd-success-s1024-Xverbose
ioctl_kvm_run
ioctl_kvm_run-v
ioctl_kvm_run_auxstr_vcpu
ioctl_lirc
ioctl_lirc-success
ioctl_loop
ioctl_loop-nv
ioctl_loop-v
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Expand Up @@ -200,6 +200,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
ioctl_kd-success-s1024-Xabbrev \
ioctl_kd-success-s1024-Xraw \
ioctl_kd-success-s1024-Xverbose \
ioctl_lirc-success \
ioctl_loop-nv \
ioctl_loop-v \
ioctl_mtd-success \
Expand Down
2 changes: 2 additions & 0 deletions tests/gen_tests.in
Expand Up @@ -339,6 +339,8 @@ ioctl_kd-success-s1024-Xverbose +ioctl-success.sh -a20 -s1024 -Xverbose
ioctl_kvm_run +ioctl.test -a36 -y
ioctl_kvm_run-v +ioctl.test -v -a36 -y
ioctl_kvm_run_auxstr_vcpu +ioctl.test -a36 -y -e kvm=vcpu
ioctl_lirc +ioctl-success.sh -a30
ioctl_lirc-success +ioctl-success.sh -a30
ldv-alt marked this conversation as resolved.
Show resolved Hide resolved
ioctl_loop +ioctl.test
ioctl_loop-nv +ioctl.test -a22 -e verbose=none
ioctl_loop-v +ioctl.test -v
Expand Down