Skip to content

Commit 321f779

Browse files
author
Benjamin Tissoires
committed
selftests/hid: Add HIDIOCREVOKE tests
Add 4 tests for the new revoke ioctl, for read/write/ioctl and poll. Reviewed-by: Peter Hutterer <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 8163892 commit 321f779

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

tools/testing/selftests/hid/hidraw.c

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
#include "hid_common.h"
55

6+
/* for older kernels */
7+
#ifndef HIDIOCREVOKE
8+
#define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */
9+
#endif /* HIDIOCREVOKE */
10+
611
FIXTURE(hidraw) {
712
int dev_id;
813
int uhid_fd;
@@ -84,6 +89,148 @@ TEST_F(hidraw, raw_event)
8489
ASSERT_EQ(buf[1], 42);
8590
}
8691

92+
/*
93+
* After initial opening/checks of hidraw, revoke the hidraw
94+
* node and check that we can not read any more data.
95+
*/
96+
TEST_F(hidraw, raw_event_revoked)
97+
{
98+
__u8 buf[10] = {0};
99+
int err;
100+
101+
/* inject one event */
102+
buf[0] = 1;
103+
buf[1] = 42;
104+
uhid_send_event(_metadata, self->uhid_fd, buf, 6);
105+
106+
/* read the data from hidraw */
107+
memset(buf, 0, sizeof(buf));
108+
err = read(self->hidraw_fd, buf, sizeof(buf));
109+
ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
110+
ASSERT_EQ(buf[0], 1);
111+
ASSERT_EQ(buf[1], 42);
112+
113+
/* call the revoke ioctl */
114+
err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL);
115+
ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd");
116+
117+
/* inject one other event */
118+
buf[0] = 1;
119+
buf[1] = 43;
120+
uhid_send_event(_metadata, self->uhid_fd, buf, 6);
121+
122+
/* read the data from hidraw */
123+
memset(buf, 0, sizeof(buf));
124+
err = read(self->hidraw_fd, buf, sizeof(buf));
125+
ASSERT_EQ(err, -1) TH_LOG("read_hidraw");
126+
ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while reading the hidraw node: %d",
127+
errno);
128+
}
129+
130+
/*
131+
* Revoke the hidraw node and check that we can not do any ioctl.
132+
*/
133+
TEST_F(hidraw, ioctl_revoked)
134+
{
135+
int err, desc_size = 0;
136+
137+
/* call the revoke ioctl */
138+
err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL);
139+
ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd");
140+
141+
/* do an ioctl */
142+
err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size);
143+
ASSERT_EQ(err, -1) TH_LOG("ioctl_hidraw");
144+
ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while doing an ioctl: %d",
145+
errno);
146+
}
147+
148+
/*
149+
* Setup polling of the fd, and check that revoke works properly.
150+
*/
151+
TEST_F(hidraw, poll_revoked)
152+
{
153+
struct pollfd pfds[1];
154+
__u8 buf[10] = {0};
155+
int err, ready;
156+
157+
/* setup polling */
158+
pfds[0].fd = self->hidraw_fd;
159+
pfds[0].events = POLLIN;
160+
161+
/* inject one event */
162+
buf[0] = 1;
163+
buf[1] = 42;
164+
uhid_send_event(_metadata, self->uhid_fd, buf, 6);
165+
166+
while (true) {
167+
ready = poll(pfds, 1, 5000);
168+
ASSERT_EQ(ready, 1) TH_LOG("poll return value");
169+
170+
if (pfds[0].revents & POLLIN) {
171+
memset(buf, 0, sizeof(buf));
172+
err = read(self->hidraw_fd, buf, sizeof(buf));
173+
ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
174+
ASSERT_EQ(buf[0], 1);
175+
ASSERT_EQ(buf[1], 42);
176+
177+
/* call the revoke ioctl */
178+
err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL);
179+
ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd");
180+
} else {
181+
break;
182+
}
183+
}
184+
185+
ASSERT_TRUE(pfds[0].revents & POLLHUP);
186+
}
187+
188+
/*
189+
* After initial opening/checks of hidraw, revoke the hidraw
190+
* node and check that we can not read any more data.
191+
*/
192+
TEST_F(hidraw, write_event_revoked)
193+
{
194+
struct timespec time_to_wait;
195+
__u8 buf[10] = {0};
196+
int err;
197+
198+
/* inject one event from hidraw */
199+
buf[0] = 1; /* report ID */
200+
buf[1] = 2;
201+
buf[2] = 42;
202+
203+
pthread_mutex_lock(&uhid_output_mtx);
204+
205+
memset(output_report, 0, sizeof(output_report));
206+
clock_gettime(CLOCK_REALTIME, &time_to_wait);
207+
time_to_wait.tv_sec += 2;
208+
209+
err = write(self->hidraw_fd, buf, 3);
210+
ASSERT_EQ(err, 3) TH_LOG("unexpected error while writing to hidraw node: %d", err);
211+
212+
err = pthread_cond_timedwait(&uhid_output_cond, &uhid_output_mtx, &time_to_wait);
213+
ASSERT_OK(err) TH_LOG("error while calling waiting for the condition");
214+
215+
ASSERT_EQ(output_report[0], 1);
216+
ASSERT_EQ(output_report[1], 2);
217+
ASSERT_EQ(output_report[2], 42);
218+
219+
/* call the revoke ioctl */
220+
err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL);
221+
ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd");
222+
223+
/* inject one other event */
224+
buf[0] = 1;
225+
buf[1] = 43;
226+
err = write(self->hidraw_fd, buf, 3);
227+
ASSERT_LT(err, 0) TH_LOG("unexpected success while writing to hidraw node: %d", err);
228+
ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while writing to hidraw node: %d",
229+
errno);
230+
231+
pthread_mutex_unlock(&uhid_output_mtx);
232+
}
233+
87234
int main(int argc, char **argv)
88235
{
89236
return test_harness_run(argc, argv);

0 commit comments

Comments
 (0)