~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/hid/hidraw.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright (c) 2022-2024 Red Hat */
  3 
  4 #include "hid_common.h"
  5 
  6 /* for older kernels */
  7 #ifndef HIDIOCREVOKE
  8 #define HIDIOCREVOKE          _IOW('H', 0x0D, int) /* Revoke device access */
  9 #endif /* HIDIOCREVOKE */
 10 
 11 FIXTURE(hidraw) {
 12         int dev_id;
 13         int uhid_fd;
 14         int hidraw_fd;
 15         int hid_id;
 16         pthread_t tid;
 17 };
 18 static void close_hidraw(FIXTURE_DATA(hidraw) * self)
 19 {
 20         if (self->hidraw_fd)
 21                 close(self->hidraw_fd);
 22         self->hidraw_fd = 0;
 23 }
 24 
 25 FIXTURE_TEARDOWN(hidraw) {
 26         void *uhid_err;
 27 
 28         uhid_destroy(_metadata, self->uhid_fd);
 29 
 30         close_hidraw(self);
 31         pthread_join(self->tid, &uhid_err);
 32 }
 33 #define TEARDOWN_LOG(fmt, ...) do { \
 34         TH_LOG(fmt, ##__VA_ARGS__); \
 35         hidraw_teardown(_metadata, self, variant); \
 36 } while (0)
 37 
 38 FIXTURE_SETUP(hidraw)
 39 {
 40         time_t t;
 41         int err;
 42 
 43         /* initialize random number generator */
 44         srand((unsigned int)time(&t));
 45 
 46         self->dev_id = rand() % 1024;
 47 
 48         self->uhid_fd = setup_uhid(_metadata, self->dev_id);
 49 
 50         /* locate the uev, self, variant);ent file of the created device */
 51         self->hid_id = get_hid_id(self->dev_id);
 52         ASSERT_GT(self->hid_id, 0)
 53                 TEARDOWN_LOG("Could not locate uhid device id: %d", self->hid_id);
 54 
 55         err = uhid_start_listener(_metadata, &self->tid, self->uhid_fd);
 56         ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err);
 57 
 58         self->hidraw_fd = open_hidraw(self->dev_id);
 59         ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
 60 }
 61 
 62 /*
 63  * A simple test to see if the fixture is working fine.
 64  * If this fails, none of the other tests will pass.
 65  */
 66 TEST_F(hidraw, test_create_uhid)
 67 {
 68 }
 69 
 70 /*
 71  * Inject one event in the uhid device,
 72  * check that we get the same data through hidraw
 73  */
 74 TEST_F(hidraw, raw_event)
 75 {
 76         __u8 buf[10] = {0};
 77         int err;
 78 
 79         /* inject one event */
 80         buf[0] = 1;
 81         buf[1] = 42;
 82         uhid_send_event(_metadata, self->uhid_fd, buf, 6);
 83 
 84         /* read the data from hidraw */
 85         memset(buf, 0, sizeof(buf));
 86         err = read(self->hidraw_fd, buf, sizeof(buf));
 87         ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
 88         ASSERT_EQ(buf[0], 1);
 89         ASSERT_EQ(buf[1], 42);
 90 }
 91 
 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 
234 int main(int argc, char **argv)
235 {
236         return test_harness_run(argc, argv);
237 }
238 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php