diff options
-rw-r--r-- | tools/bpf/bpftool/prog.c | 1 | ||||
-rw-r--r-- | tools/include/uapi/linux/bpf.h | 79 | ||||
-rw-r--r-- | tools/include/uapi/linux/lirc.h | 217 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 1 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/.gitignore | 1 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/Makefile | 7 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/bpf_helpers.h | 5 | ||||
-rwxr-xr-x | tools/testing/selftests/bpf/test_lirc_mode2.sh | 28 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_lirc_mode2_kern.c | 23 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_lirc_mode2_user.c | 149 |
10 files changed, 494 insertions, 17 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 39b88e760367..a4f435203fef 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c | |||
@@ -71,6 +71,7 @@ static const char * const prog_type_name[] = { | |||
71 | [BPF_PROG_TYPE_SK_MSG] = "sk_msg", | 71 | [BPF_PROG_TYPE_SK_MSG] = "sk_msg", |
72 | [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint", | 72 | [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint", |
73 | [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr", | 73 | [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr", |
74 | [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2", | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) | 77 | static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) |
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 3f556b35ac8d..64ac0f7a689e 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h | |||
@@ -143,6 +143,7 @@ enum bpf_prog_type { | |||
143 | BPF_PROG_TYPE_RAW_TRACEPOINT, | 143 | BPF_PROG_TYPE_RAW_TRACEPOINT, |
144 | BPF_PROG_TYPE_CGROUP_SOCK_ADDR, | 144 | BPF_PROG_TYPE_CGROUP_SOCK_ADDR, |
145 | BPF_PROG_TYPE_LWT_SEG6LOCAL, | 145 | BPF_PROG_TYPE_LWT_SEG6LOCAL, |
146 | BPF_PROG_TYPE_LIRC_MODE2, | ||
146 | }; | 147 | }; |
147 | 148 | ||
148 | enum bpf_attach_type { | 149 | enum bpf_attach_type { |
@@ -162,6 +163,7 @@ enum bpf_attach_type { | |||
162 | BPF_CGROUP_INET6_POST_BIND, | 163 | BPF_CGROUP_INET6_POST_BIND, |
163 | BPF_CGROUP_UDP4_SENDMSG, | 164 | BPF_CGROUP_UDP4_SENDMSG, |
164 | BPF_CGROUP_UDP6_SENDMSG, | 165 | BPF_CGROUP_UDP6_SENDMSG, |
166 | BPF_LIRC_MODE2, | ||
165 | __MAX_BPF_ATTACH_TYPE | 167 | __MAX_BPF_ATTACH_TYPE |
166 | }; | 168 | }; |
167 | 169 | ||
@@ -1852,10 +1854,10 @@ union bpf_attr { | |||
1852 | * If lookup is successful and result shows packet is to be | 1854 | * If lookup is successful and result shows packet is to be |
1853 | * forwarded, the neighbor tables are searched for the nexthop. | 1855 | * forwarded, the neighbor tables are searched for the nexthop. |
1854 | * If successful (ie., FIB lookup shows forwarding and nexthop | 1856 | * If successful (ie., FIB lookup shows forwarding and nexthop |
1855 | * is resolved), the nexthop address is returned in ipv4_dst, | 1857 | * is resolved), the nexthop address is returned in ipv4_dst |
1856 | * ipv6_dst or mpls_out based on family, smac is set to mac | 1858 | * or ipv6_dst based on family, smac is set to mac address of |
1857 | * address of egress device, dmac is set to nexthop mac address, | 1859 | * egress device, dmac is set to nexthop mac address, rt_metric |
1858 | * rt_metric is set to metric from route. | 1860 | * is set to metric from route (IPv4/IPv6 only). |
1859 | * | 1861 | * |
1860 | * *plen* argument is the size of the passed in struct. | 1862 | * *plen* argument is the size of the passed in struct. |
1861 | * *flags* argument can be a combination of one or more of the | 1863 | * *flags* argument can be a combination of one or more of the |
@@ -2005,6 +2007,53 @@ union bpf_attr { | |||
2005 | * direct packet access. | 2007 | * direct packet access. |
2006 | * Return | 2008 | * Return |
2007 | * 0 on success, or a negative error in case of failure. | 2009 | * 0 on success, or a negative error in case of failure. |
2010 | * | ||
2011 | * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) | ||
2012 | * Description | ||
2013 | * This helper is used in programs implementing IR decoding, to | ||
2014 | * report a successfully decoded key press with *scancode*, | ||
2015 | * *toggle* value in the given *protocol*. The scancode will be | ||
2016 | * translated to a keycode using the rc keymap, and reported as | ||
2017 | * an input key down event. After a period a key up event is | ||
2018 | * generated. This period can be extended by calling either | ||
2019 | * **bpf_rc_keydown** () again with the same values, or calling | ||
2020 | * **bpf_rc_repeat** (). | ||
2021 | * | ||
2022 | * Some protocols include a toggle bit, in case the button was | ||
2023 | * released and pressed again between consecutive scancodes. | ||
2024 | * | ||
2025 | * The *ctx* should point to the lirc sample as passed into | ||
2026 | * the program. | ||
2027 | * | ||
2028 | * The *protocol* is the decoded protocol number (see | ||
2029 | * **enum rc_proto** for some predefined values). | ||
2030 | * | ||
2031 | * This helper is only available is the kernel was compiled with | ||
2032 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | ||
2033 | * "**y**". | ||
2034 | * | ||
2035 | * Return | ||
2036 | * 0 | ||
2037 | * | ||
2038 | * int bpf_rc_repeat(void *ctx) | ||
2039 | * Description | ||
2040 | * This helper is used in programs implementing IR decoding, to | ||
2041 | * report a successfully decoded repeat key message. This delays | ||
2042 | * the generation of a key up event for previously generated | ||
2043 | * key down event. | ||
2044 | * | ||
2045 | * Some IR protocols like NEC have a special IR message for | ||
2046 | * repeating last button, for when a button is held down. | ||
2047 | * | ||
2048 | * The *ctx* should point to the lirc sample as passed into | ||
2049 | * the program. | ||
2050 | * | ||
2051 | * This helper is only available is the kernel was compiled with | ||
2052 | * the **CONFIG_BPF_LIRC_MODE2** configuration option set to | ||
2053 | * "**y**". | ||
2054 | * | ||
2055 | * Return | ||
2056 | * 0 | ||
2008 | */ | 2057 | */ |
2009 | #define __BPF_FUNC_MAPPER(FN) \ | 2058 | #define __BPF_FUNC_MAPPER(FN) \ |
2010 | FN(unspec), \ | 2059 | FN(unspec), \ |
@@ -2083,7 +2132,9 @@ union bpf_attr { | |||
2083 | FN(lwt_push_encap), \ | 2132 | FN(lwt_push_encap), \ |
2084 | FN(lwt_seg6_store_bytes), \ | 2133 | FN(lwt_seg6_store_bytes), \ |
2085 | FN(lwt_seg6_adjust_srh), \ | 2134 | FN(lwt_seg6_adjust_srh), \ |
2086 | FN(lwt_seg6_action), | 2135 | FN(lwt_seg6_action), \ |
2136 | FN(rc_repeat), \ | ||
2137 | FN(rc_keydown), | ||
2087 | 2138 | ||
2088 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper | 2139 | /* integer value in 'imm' field of BPF_CALL instruction selects which helper |
2089 | * function eBPF program intends to call | 2140 | * function eBPF program intends to call |
@@ -2537,8 +2588,10 @@ struct bpf_raw_tracepoint_args { | |||
2537 | #define BPF_FIB_LOOKUP_OUTPUT BIT(1) | 2588 | #define BPF_FIB_LOOKUP_OUTPUT BIT(1) |
2538 | 2589 | ||
2539 | struct bpf_fib_lookup { | 2590 | struct bpf_fib_lookup { |
2540 | /* input */ | 2591 | /* input: network family for lookup (AF_INET, AF_INET6) |
2541 | __u8 family; /* network family, AF_INET, AF_INET6, AF_MPLS */ | 2592 | * output: network family of egress nexthop |
2593 | */ | ||
2594 | __u8 family; | ||
2542 | 2595 | ||
2543 | /* set if lookup is to consider L4 data - e.g., FIB rules */ | 2596 | /* set if lookup is to consider L4 data - e.g., FIB rules */ |
2544 | __u8 l4_protocol; | 2597 | __u8 l4_protocol; |
@@ -2554,22 +2607,20 @@ struct bpf_fib_lookup { | |||
2554 | __u8 tos; /* AF_INET */ | 2607 | __u8 tos; /* AF_INET */ |
2555 | __be32 flowlabel; /* AF_INET6 */ | 2608 | __be32 flowlabel; /* AF_INET6 */ |
2556 | 2609 | ||
2557 | /* output: metric of fib result */ | 2610 | /* output: metric of fib result (IPv4/IPv6 only) */ |
2558 | __u32 rt_metric; | 2611 | __u32 rt_metric; |
2559 | }; | 2612 | }; |
2560 | 2613 | ||
2561 | union { | 2614 | union { |
2562 | __be32 mpls_in; | ||
2563 | __be32 ipv4_src; | 2615 | __be32 ipv4_src; |
2564 | __u32 ipv6_src[4]; /* in6_addr; network order */ | 2616 | __u32 ipv6_src[4]; /* in6_addr; network order */ |
2565 | }; | 2617 | }; |
2566 | 2618 | ||
2567 | /* input to bpf_fib_lookup, *dst is destination address. | 2619 | /* input to bpf_fib_lookup, ipv{4,6}_dst is destination address in |
2568 | * output: bpf_fib_lookup sets to gateway address | 2620 | * network header. output: bpf_fib_lookup sets to gateway address |
2621 | * if FIB lookup returns gateway route | ||
2569 | */ | 2622 | */ |
2570 | union { | 2623 | union { |
2571 | /* return for MPLS lookups */ | ||
2572 | __be32 mpls_out[4]; /* support up to 4 labels */ | ||
2573 | __be32 ipv4_dst; | 2624 | __be32 ipv4_dst; |
2574 | __u32 ipv6_dst[4]; /* in6_addr; network order */ | 2625 | __u32 ipv6_dst[4]; /* in6_addr; network order */ |
2575 | }; | 2626 | }; |
diff --git a/tools/include/uapi/linux/lirc.h b/tools/include/uapi/linux/lirc.h new file mode 100644 index 000000000000..f189931042a7 --- /dev/null +++ b/tools/include/uapi/linux/lirc.h | |||
@@ -0,0 +1,217 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | ||
2 | /* | ||
3 | * lirc.h - linux infrared remote control header file | ||
4 | * last modified 2010/07/13 by Jarod Wilson | ||
5 | */ | ||
6 | |||
7 | #ifndef _LINUX_LIRC_H | ||
8 | #define _LINUX_LIRC_H | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | #include <linux/ioctl.h> | ||
12 | |||
13 | #define PULSE_BIT 0x01000000 | ||
14 | #define PULSE_MASK 0x00FFFFFF | ||
15 | |||
16 | #define LIRC_MODE2_SPACE 0x00000000 | ||
17 | #define LIRC_MODE2_PULSE 0x01000000 | ||
18 | #define LIRC_MODE2_FREQUENCY 0x02000000 | ||
19 | #define LIRC_MODE2_TIMEOUT 0x03000000 | ||
20 | |||
21 | #define LIRC_VALUE_MASK 0x00FFFFFF | ||
22 | #define LIRC_MODE2_MASK 0xFF000000 | ||
23 | |||
24 | #define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) | ||
25 | #define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) | ||
26 | #define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) | ||
27 | #define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) | ||
28 | |||
29 | #define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) | ||
30 | #define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) | ||
31 | |||
32 | #define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) | ||
33 | #define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) | ||
34 | #define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) | ||
35 | #define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) | ||
36 | |||
37 | /* used heavily by lirc userspace */ | ||
38 | #define lirc_t int | ||
39 | |||
40 | /*** lirc compatible hardware features ***/ | ||
41 | |||
42 | #define LIRC_MODE2SEND(x) (x) | ||
43 | #define LIRC_SEND2MODE(x) (x) | ||
44 | #define LIRC_MODE2REC(x) ((x) << 16) | ||
45 | #define LIRC_REC2MODE(x) ((x) >> 16) | ||
46 | |||
47 | #define LIRC_MODE_RAW 0x00000001 | ||
48 | #define LIRC_MODE_PULSE 0x00000002 | ||
49 | #define LIRC_MODE_MODE2 0x00000004 | ||
50 | #define LIRC_MODE_SCANCODE 0x00000008 | ||
51 | #define LIRC_MODE_LIRCCODE 0x00000010 | ||
52 | |||
53 | |||
54 | #define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) | ||
55 | #define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) | ||
56 | #define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) | ||
57 | #define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) | ||
58 | |||
59 | #define LIRC_CAN_SEND_MASK 0x0000003f | ||
60 | |||
61 | #define LIRC_CAN_SET_SEND_CARRIER 0x00000100 | ||
62 | #define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 | ||
63 | #define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 | ||
64 | |||
65 | #define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) | ||
66 | #define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) | ||
67 | #define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) | ||
68 | #define LIRC_CAN_REC_SCANCODE LIRC_MODE2REC(LIRC_MODE_SCANCODE) | ||
69 | #define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) | ||
70 | |||
71 | #define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) | ||
72 | |||
73 | #define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) | ||
74 | #define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) | ||
75 | |||
76 | #define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 | ||
77 | #define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 | ||
78 | #define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 | ||
79 | #define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 | ||
80 | #define LIRC_CAN_SET_REC_FILTER 0x08000000 | ||
81 | |||
82 | #define LIRC_CAN_MEASURE_CARRIER 0x02000000 | ||
83 | #define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000 | ||
84 | |||
85 | #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) | ||
86 | #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) | ||
87 | |||
88 | #define LIRC_CAN_NOTIFY_DECODE 0x01000000 | ||
89 | |||
90 | /*** IOCTL commands for lirc driver ***/ | ||
91 | |||
92 | #define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) | ||
93 | |||
94 | #define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) | ||
95 | #define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) | ||
96 | #define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) | ||
97 | |||
98 | #define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) | ||
99 | #define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) | ||
100 | |||
101 | /* code length in bits, currently only for LIRC_MODE_LIRCCODE */ | ||
102 | #define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) | ||
103 | |||
104 | #define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) | ||
105 | #define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) | ||
106 | /* Note: these can reset the according pulse_width */ | ||
107 | #define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) | ||
108 | #define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) | ||
109 | #define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) | ||
110 | #define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) | ||
111 | |||
112 | /* | ||
113 | * when a timeout != 0 is set the driver will send a | ||
114 | * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is | ||
115 | * never sent, timeout is disabled by default | ||
116 | */ | ||
117 | #define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) | ||
118 | |||
119 | /* 1 enables, 0 disables timeout reports in MODE2 */ | ||
120 | #define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) | ||
121 | |||
122 | /* | ||
123 | * if enabled from the next key press on the driver will send | ||
124 | * LIRC_MODE2_FREQUENCY packets | ||
125 | */ | ||
126 | #define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) | ||
127 | |||
128 | /* | ||
129 | * to set a range use LIRC_SET_REC_CARRIER_RANGE with the | ||
130 | * lower bound first and later LIRC_SET_REC_CARRIER with the upper bound | ||
131 | */ | ||
132 | #define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) | ||
133 | |||
134 | #define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) | ||
135 | |||
136 | /* | ||
137 | * struct lirc_scancode - decoded scancode with protocol for use with | ||
138 | * LIRC_MODE_SCANCODE | ||
139 | * | ||
140 | * @timestamp: Timestamp in nanoseconds using CLOCK_MONOTONIC when IR | ||
141 | * was decoded. | ||
142 | * @flags: should be 0 for transmit. When receiving scancodes, | ||
143 | * LIRC_SCANCODE_FLAG_TOGGLE or LIRC_SCANCODE_FLAG_REPEAT can be set | ||
144 | * depending on the protocol | ||
145 | * @rc_proto: see enum rc_proto | ||
146 | * @keycode: the translated keycode. Set to 0 for transmit. | ||
147 | * @scancode: the scancode received or to be sent | ||
148 | */ | ||
149 | struct lirc_scancode { | ||
150 | __u64 timestamp; | ||
151 | __u16 flags; | ||
152 | __u16 rc_proto; | ||
153 | __u32 keycode; | ||
154 | __u64 scancode; | ||
155 | }; | ||
156 | |||
157 | /* Set if the toggle bit of rc-5 or rc-6 is enabled */ | ||
158 | #define LIRC_SCANCODE_FLAG_TOGGLE 1 | ||
159 | /* Set if this is a nec or sanyo repeat */ | ||
160 | #define LIRC_SCANCODE_FLAG_REPEAT 2 | ||
161 | |||
162 | /** | ||
163 | * enum rc_proto - the Remote Controller protocol | ||
164 | * | ||
165 | * @RC_PROTO_UNKNOWN: Protocol not known | ||
166 | * @RC_PROTO_OTHER: Protocol known but proprietary | ||
167 | * @RC_PROTO_RC5: Philips RC5 protocol | ||
168 | * @RC_PROTO_RC5X_20: Philips RC5x 20 bit protocol | ||
169 | * @RC_PROTO_RC5_SZ: StreamZap variant of RC5 | ||
170 | * @RC_PROTO_JVC: JVC protocol | ||
171 | * @RC_PROTO_SONY12: Sony 12 bit protocol | ||
172 | * @RC_PROTO_SONY15: Sony 15 bit protocol | ||
173 | * @RC_PROTO_SONY20: Sony 20 bit protocol | ||
174 | * @RC_PROTO_NEC: NEC protocol | ||
175 | * @RC_PROTO_NECX: Extended NEC protocol | ||
176 | * @RC_PROTO_NEC32: NEC 32 bit protocol | ||
177 | * @RC_PROTO_SANYO: Sanyo protocol | ||
178 | * @RC_PROTO_MCIR2_KBD: RC6-ish MCE keyboard | ||
179 | * @RC_PROTO_MCIR2_MSE: RC6-ish MCE mouse | ||
180 | * @RC_PROTO_RC6_0: Philips RC6-0-16 protocol | ||
181 | * @RC_PROTO_RC6_6A_20: Philips RC6-6A-20 protocol | ||
182 | * @RC_PROTO_RC6_6A_24: Philips RC6-6A-24 protocol | ||
183 | * @RC_PROTO_RC6_6A_32: Philips RC6-6A-32 protocol | ||
184 | * @RC_PROTO_RC6_MCE: MCE (Philips RC6-6A-32 subtype) protocol | ||
185 | * @RC_PROTO_SHARP: Sharp protocol | ||
186 | * @RC_PROTO_XMP: XMP protocol | ||
187 | * @RC_PROTO_CEC: CEC protocol | ||
188 | * @RC_PROTO_IMON: iMon Pad protocol | ||
189 | */ | ||
190 | enum rc_proto { | ||
191 | RC_PROTO_UNKNOWN = 0, | ||
192 | RC_PROTO_OTHER = 1, | ||
193 | RC_PROTO_RC5 = 2, | ||
194 | RC_PROTO_RC5X_20 = 3, | ||
195 | RC_PROTO_RC5_SZ = 4, | ||
196 | RC_PROTO_JVC = 5, | ||
197 | RC_PROTO_SONY12 = 6, | ||
198 | RC_PROTO_SONY15 = 7, | ||
199 | RC_PROTO_SONY20 = 8, | ||
200 | RC_PROTO_NEC = 9, | ||
201 | RC_PROTO_NECX = 10, | ||
202 | RC_PROTO_NEC32 = 11, | ||
203 | RC_PROTO_SANYO = 12, | ||
204 | RC_PROTO_MCIR2_KBD = 13, | ||
205 | RC_PROTO_MCIR2_MSE = 14, | ||
206 | RC_PROTO_RC6_0 = 15, | ||
207 | RC_PROTO_RC6_6A_20 = 16, | ||
208 | RC_PROTO_RC6_6A_24 = 17, | ||
209 | RC_PROTO_RC6_6A_32 = 18, | ||
210 | RC_PROTO_RC6_MCE = 19, | ||
211 | RC_PROTO_SHARP = 20, | ||
212 | RC_PROTO_XMP = 21, | ||
213 | RC_PROTO_CEC = 22, | ||
214 | RC_PROTO_IMON = 23, | ||
215 | }; | ||
216 | |||
217 | #endif | ||
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index b1a60ac8424e..a1e96b5de5ff 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -1462,6 +1462,7 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type) | |||
1462 | case BPF_PROG_TYPE_CGROUP_DEVICE: | 1462 | case BPF_PROG_TYPE_CGROUP_DEVICE: |
1463 | case BPF_PROG_TYPE_SK_MSG: | 1463 | case BPF_PROG_TYPE_SK_MSG: |
1464 | case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: | 1464 | case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: |
1465 | case BPF_PROG_TYPE_LIRC_MODE2: | ||
1465 | return false; | 1466 | return false; |
1466 | case BPF_PROG_TYPE_UNSPEC: | 1467 | case BPF_PROG_TYPE_UNSPEC: |
1467 | case BPF_PROG_TYPE_KPROBE: | 1468 | case BPF_PROG_TYPE_KPROBE: |
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index adc8e5474b66..6ea835982464 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore | |||
@@ -17,3 +17,4 @@ test_sock_addr | |||
17 | urandom_read | 17 | urandom_read |
18 | test_btf | 18 | test_btf |
19 | test_sockmap | 19 | test_sockmap |
20 | test_lirc_mode2_user | ||
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index a1b66da965d0..553d1816b77a 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile | |||
@@ -24,7 +24,7 @@ urandom_read: urandom_read.c | |||
24 | # Order correspond to 'make run_tests' order | 24 | # Order correspond to 'make run_tests' order |
25 | TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ | 25 | TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ |
26 | test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ | 26 | test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ |
27 | test_sock test_btf test_sockmap | 27 | test_sock test_btf test_sockmap test_lirc_mode2_user |
28 | 28 | ||
29 | TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ | 29 | TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ |
30 | test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ | 30 | test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ |
@@ -34,7 +34,7 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test | |||
34 | sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ | 34 | sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ |
35 | test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o test_tunnel_kern.o \ | 35 | test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o test_tunnel_kern.o \ |
36 | test_get_stack_rawtp.o test_sockmap_kern.o test_sockhash_kern.o \ | 36 | test_get_stack_rawtp.o test_sockmap_kern.o test_sockhash_kern.o \ |
37 | test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o | 37 | test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o |
38 | 38 | ||
39 | # Order correspond to 'make run_tests' order | 39 | # Order correspond to 'make run_tests' order |
40 | TEST_PROGS := test_kmod.sh \ | 40 | TEST_PROGS := test_kmod.sh \ |
@@ -44,7 +44,8 @@ TEST_PROGS := test_kmod.sh \ | |||
44 | test_offload.py \ | 44 | test_offload.py \ |
45 | test_sock_addr.sh \ | 45 | test_sock_addr.sh \ |
46 | test_tunnel.sh \ | 46 | test_tunnel.sh \ |
47 | test_lwt_seg6local.sh | 47 | test_lwt_seg6local.sh \ |
48 | test_lirc_mode2.sh | ||
48 | 49 | ||
49 | # Compile but not part of 'make run_tests' | 50 | # Compile but not part of 'make run_tests' |
50 | TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr | 51 | TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr |
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 334d3e8c5e89..a66a9d91acf4 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h | |||
@@ -126,6 +126,11 @@ static int (*bpf_lwt_seg6_action)(void *ctx, unsigned int action, void *param, | |||
126 | static int (*bpf_lwt_seg6_adjust_srh)(void *ctx, unsigned int offset, | 126 | static int (*bpf_lwt_seg6_adjust_srh)(void *ctx, unsigned int offset, |
127 | unsigned int len) = | 127 | unsigned int len) = |
128 | (void *) BPF_FUNC_lwt_seg6_adjust_srh; | 128 | (void *) BPF_FUNC_lwt_seg6_adjust_srh; |
129 | static int (*bpf_rc_repeat)(void *ctx) = | ||
130 | (void *) BPF_FUNC_rc_repeat; | ||
131 | static int (*bpf_rc_keydown)(void *ctx, unsigned int protocol, | ||
132 | unsigned long long scancode, unsigned int toggle) = | ||
133 | (void *) BPF_FUNC_rc_keydown; | ||
129 | 134 | ||
130 | /* llvm builtin functions that eBPF C program may use to | 135 | /* llvm builtin functions that eBPF C program may use to |
131 | * emit BPF_LD_ABS and BPF_LD_IND instructions | 136 | * emit BPF_LD_ABS and BPF_LD_IND instructions |
diff --git a/tools/testing/selftests/bpf/test_lirc_mode2.sh b/tools/testing/selftests/bpf/test_lirc_mode2.sh new file mode 100755 index 000000000000..ce2e15e4f976 --- /dev/null +++ b/tools/testing/selftests/bpf/test_lirc_mode2.sh | |||
@@ -0,0 +1,28 @@ | |||
1 | #!/bin/bash | ||
2 | # SPDX-License-Identifier: GPL-2.0 | ||
3 | |||
4 | GREEN='\033[0;92m' | ||
5 | RED='\033[0;31m' | ||
6 | NC='\033[0m' # No Color | ||
7 | |||
8 | modprobe rc-loopback | ||
9 | |||
10 | for i in /sys/class/rc/rc* | ||
11 | do | ||
12 | if grep -q DRV_NAME=rc-loopback $i/uevent | ||
13 | then | ||
14 | LIRCDEV=$(grep DEVNAME= $i/lirc*/uevent | sed sQDEVNAME=Q/dev/Q) | ||
15 | fi | ||
16 | done | ||
17 | |||
18 | if [ -n $LIRCDEV ]; | ||
19 | then | ||
20 | TYPE=lirc_mode2 | ||
21 | ./test_lirc_mode2_user $LIRCDEV | ||
22 | ret=$? | ||
23 | if [ $ret -ne 0 ]; then | ||
24 | echo -e ${RED}"FAIL: $TYPE"${NC} | ||
25 | else | ||
26 | echo -e ${GREEN}"PASS: $TYPE"${NC} | ||
27 | fi | ||
28 | fi | ||
diff --git a/tools/testing/selftests/bpf/test_lirc_mode2_kern.c b/tools/testing/selftests/bpf/test_lirc_mode2_kern.c new file mode 100644 index 000000000000..ba26855563a5 --- /dev/null +++ b/tools/testing/selftests/bpf/test_lirc_mode2_kern.c | |||
@@ -0,0 +1,23 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // test ir decoder | ||
3 | // | ||
4 | // Copyright (C) 2018 Sean Young <sean@mess.org> | ||
5 | |||
6 | #include <linux/bpf.h> | ||
7 | #include <linux/lirc.h> | ||
8 | #include "bpf_helpers.h" | ||
9 | |||
10 | SEC("lirc_mode2") | ||
11 | int bpf_decoder(unsigned int *sample) | ||
12 | { | ||
13 | if (LIRC_IS_PULSE(*sample)) { | ||
14 | unsigned int duration = LIRC_VALUE(*sample); | ||
15 | |||
16 | if (duration & 0x10000) | ||
17 | bpf_rc_keydown(sample, 0x40, duration & 0xffff, 0); | ||
18 | } | ||
19 | |||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | char _license[] SEC("license") = "GPL"; | ||
diff --git a/tools/testing/selftests/bpf/test_lirc_mode2_user.c b/tools/testing/selftests/bpf/test_lirc_mode2_user.c new file mode 100644 index 000000000000..d470d63c33db --- /dev/null +++ b/tools/testing/selftests/bpf/test_lirc_mode2_user.c | |||
@@ -0,0 +1,149 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // test ir decoder | ||
3 | // | ||
4 | // Copyright (C) 2018 Sean Young <sean@mess.org> | ||
5 | |||
6 | // A lirc chardev is a device representing a consumer IR (cir) device which | ||
7 | // can receive infrared signals from remote control and/or transmit IR. | ||
8 | // | ||
9 | // IR is sent as a series of pulses and space somewhat like morse code. The | ||
10 | // BPF program can decode this into scancodes so that rc-core can translate | ||
11 | // this into input key codes using the rc keymap. | ||
12 | // | ||
13 | // This test works by sending IR over rc-loopback, so the IR is processed by | ||
14 | // BPF and then decoded into scancodes. The lirc chardev must be the one | ||
15 | // associated with rc-loopback, see the output of ir-keytable(1). | ||
16 | // | ||
17 | // The following CONFIG options must be enabled for the test to succeed: | ||
18 | // CONFIG_RC_CORE=y | ||
19 | // CONFIG_BPF_RAWIR_EVENT=y | ||
20 | // CONFIG_RC_LOOPBACK=y | ||
21 | |||
22 | // Steps: | ||
23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) | ||
24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. | ||
25 | // 3. Send some IR to the same IR device; since it is loopback, this will | ||
26 | // end up in the bpf program | ||
27 | // 4. bpf program should decode IR and report keycode | ||
28 | // 5. We can read keycode from same /dev/lirc device | ||
29 | |||
30 | #include <linux/bpf.h> | ||
31 | #include <linux/lirc.h> | ||
32 | #include <errno.h> | ||
33 | #include <stdio.h> | ||
34 | #include <stdlib.h> | ||
35 | #include <string.h> | ||
36 | #include <unistd.h> | ||
37 | #include <poll.h> | ||
38 | #include <sys/types.h> | ||
39 | #include <sys/ioctl.h> | ||
40 | #include <sys/stat.h> | ||
41 | #include <fcntl.h> | ||
42 | |||
43 | #include "bpf_util.h" | ||
44 | #include <bpf/bpf.h> | ||
45 | #include <bpf/libbpf.h> | ||
46 | |||
47 | int main(int argc, char **argv) | ||
48 | { | ||
49 | struct bpf_object *obj; | ||
50 | int ret, lircfd, progfd, mode; | ||
51 | int testir = 0x1dead; | ||
52 | u32 prog_ids[10], prog_flags[10], prog_cnt; | ||
53 | |||
54 | if (argc != 2) { | ||
55 | printf("Usage: %s /dev/lircN\n", argv[0]); | ||
56 | return 2; | ||
57 | } | ||
58 | |||
59 | ret = bpf_prog_load("test_lirc_mode2_kern.o", | ||
60 | BPF_PROG_TYPE_LIRC_MODE2, &obj, &progfd); | ||
61 | if (ret) { | ||
62 | printf("Failed to load bpf program\n"); | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | lircfd = open(argv[1], O_RDWR | O_NONBLOCK); | ||
67 | if (lircfd == -1) { | ||
68 | printf("failed to open lirc device %s: %m\n", argv[1]); | ||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | /* Let's try detach it before it was ever attached */ | ||
73 | ret = bpf_prog_detach2(progfd, lircfd, BPF_LIRC_MODE2); | ||
74 | if (ret != -1 || errno != ENOENT) { | ||
75 | printf("bpf_prog_detach2 not attached should fail: %m\n"); | ||
76 | return 1; | ||
77 | } | ||
78 | |||
79 | mode = LIRC_MODE_SCANCODE; | ||
80 | if (ioctl(lircfd, LIRC_SET_REC_MODE, &mode)) { | ||
81 | printf("failed to set rec mode: %m\n"); | ||
82 | return 1; | ||
83 | } | ||
84 | |||
85 | prog_cnt = 10; | ||
86 | ret = bpf_prog_query(lircfd, BPF_LIRC_MODE2, 0, prog_flags, prog_ids, | ||
87 | &prog_cnt); | ||
88 | if (ret) { | ||
89 | printf("Failed to query bpf programs on lirc device: %m\n"); | ||
90 | return 1; | ||
91 | } | ||
92 | |||
93 | if (prog_cnt != 0) { | ||
94 | printf("Expected nothing to be attached\n"); | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | ret = bpf_prog_attach(progfd, lircfd, BPF_LIRC_MODE2, 0); | ||
99 | if (ret) { | ||
100 | printf("Failed to attach bpf to lirc device: %m\n"); | ||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | /* Write raw IR */ | ||
105 | ret = write(lircfd, &testir, sizeof(testir)); | ||
106 | if (ret != sizeof(testir)) { | ||
107 | printf("Failed to send test IR message: %m\n"); | ||
108 | return 1; | ||
109 | } | ||
110 | |||
111 | struct pollfd pfd = { .fd = lircfd, .events = POLLIN }; | ||
112 | struct lirc_scancode lsc; | ||
113 | |||
114 | poll(&pfd, 1, 100); | ||
115 | |||
116 | /* Read decoded IR */ | ||
117 | ret = read(lircfd, &lsc, sizeof(lsc)); | ||
118 | if (ret != sizeof(lsc)) { | ||
119 | printf("Failed to read decoded IR: %m\n"); | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | if (lsc.scancode != 0xdead || lsc.rc_proto != 64) { | ||
124 | printf("Incorrect scancode decoded\n"); | ||
125 | return 1; | ||
126 | } | ||
127 | |||
128 | prog_cnt = 10; | ||
129 | ret = bpf_prog_query(lircfd, BPF_LIRC_MODE2, 0, prog_flags, prog_ids, | ||
130 | &prog_cnt); | ||
131 | if (ret) { | ||
132 | printf("Failed to query bpf programs on lirc device: %m\n"); | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | if (prog_cnt != 1) { | ||
137 | printf("Expected one program to be attached\n"); | ||
138 | return 1; | ||
139 | } | ||
140 | |||
141 | /* Let's try detaching it now it is actually attached */ | ||
142 | ret = bpf_prog_detach2(progfd, lircfd, BPF_LIRC_MODE2); | ||
143 | if (ret) { | ||
144 | printf("bpf_prog_detach2: returned %m\n"); | ||
145 | return 1; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | } | ||