Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.13 221 lines 5.3 kB view raw
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 11FIXTURE(hidraw) { 12 struct uhid_device hid; 13 int hidraw_fd; 14}; 15static void close_hidraw(FIXTURE_DATA(hidraw) * self) 16{ 17 if (self->hidraw_fd) 18 close(self->hidraw_fd); 19 self->hidraw_fd = 0; 20} 21 22FIXTURE_TEARDOWN(hidraw) { 23 void *uhid_err; 24 25 uhid_destroy(_metadata, &self->hid); 26 27 close_hidraw(self); 28 pthread_join(self->hid.tid, &uhid_err); 29} 30#define TEARDOWN_LOG(fmt, ...) do { \ 31 TH_LOG(fmt, ##__VA_ARGS__); \ 32 hidraw_teardown(_metadata, self, variant); \ 33} while (0) 34 35FIXTURE_SETUP(hidraw) 36{ 37 int err; 38 39 err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a37, rdesc, sizeof(rdesc)); 40 ASSERT_OK(err); 41 42 self->hidraw_fd = open_hidraw(&self->hid); 43 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 44} 45 46/* 47 * A simple test to see if the fixture is working fine. 48 * If this fails, none of the other tests will pass. 49 */ 50TEST_F(hidraw, test_create_uhid) 51{ 52} 53 54/* 55 * Inject one event in the uhid device, 56 * check that we get the same data through hidraw 57 */ 58TEST_F(hidraw, raw_event) 59{ 60 __u8 buf[10] = {0}; 61 int err; 62 63 /* inject one event */ 64 buf[0] = 1; 65 buf[1] = 42; 66 uhid_send_event(_metadata, &self->hid, buf, 6); 67 68 /* read the data from hidraw */ 69 memset(buf, 0, sizeof(buf)); 70 err = read(self->hidraw_fd, buf, sizeof(buf)); 71 ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 72 ASSERT_EQ(buf[0], 1); 73 ASSERT_EQ(buf[1], 42); 74} 75 76/* 77 * After initial opening/checks of hidraw, revoke the hidraw 78 * node and check that we can not read any more data. 79 */ 80TEST_F(hidraw, raw_event_revoked) 81{ 82 __u8 buf[10] = {0}; 83 int err; 84 85 /* inject one event */ 86 buf[0] = 1; 87 buf[1] = 42; 88 uhid_send_event(_metadata, &self->hid, buf, 6); 89 90 /* read the data from hidraw */ 91 memset(buf, 0, sizeof(buf)); 92 err = read(self->hidraw_fd, buf, sizeof(buf)); 93 ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 94 ASSERT_EQ(buf[0], 1); 95 ASSERT_EQ(buf[1], 42); 96 97 /* call the revoke ioctl */ 98 err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); 99 ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); 100 101 /* inject one other event */ 102 buf[0] = 1; 103 buf[1] = 43; 104 uhid_send_event(_metadata, &self->hid, 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, -1) TH_LOG("read_hidraw"); 110 ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while reading the hidraw node: %d", 111 errno); 112} 113 114/* 115 * Revoke the hidraw node and check that we can not do any ioctl. 116 */ 117TEST_F(hidraw, ioctl_revoked) 118{ 119 int err, desc_size = 0; 120 121 /* call the revoke ioctl */ 122 err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); 123 ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); 124 125 /* do an ioctl */ 126 err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size); 127 ASSERT_EQ(err, -1) TH_LOG("ioctl_hidraw"); 128 ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while doing an ioctl: %d", 129 errno); 130} 131 132/* 133 * Setup polling of the fd, and check that revoke works properly. 134 */ 135TEST_F(hidraw, poll_revoked) 136{ 137 struct pollfd pfds[1]; 138 __u8 buf[10] = {0}; 139 int err, ready; 140 141 /* setup polling */ 142 pfds[0].fd = self->hidraw_fd; 143 pfds[0].events = POLLIN; 144 145 /* inject one event */ 146 buf[0] = 1; 147 buf[1] = 42; 148 uhid_send_event(_metadata, &self->hid, buf, 6); 149 150 while (true) { 151 ready = poll(pfds, 1, 5000); 152 ASSERT_EQ(ready, 1) TH_LOG("poll return value"); 153 154 if (pfds[0].revents & POLLIN) { 155 memset(buf, 0, sizeof(buf)); 156 err = read(self->hidraw_fd, buf, sizeof(buf)); 157 ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 158 ASSERT_EQ(buf[0], 1); 159 ASSERT_EQ(buf[1], 42); 160 161 /* call the revoke ioctl */ 162 err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); 163 ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); 164 } else { 165 break; 166 } 167 } 168 169 ASSERT_TRUE(pfds[0].revents & POLLHUP); 170} 171 172/* 173 * After initial opening/checks of hidraw, revoke the hidraw 174 * node and check that we can not read any more data. 175 */ 176TEST_F(hidraw, write_event_revoked) 177{ 178 struct timespec time_to_wait; 179 __u8 buf[10] = {0}; 180 int err; 181 182 /* inject one event from hidraw */ 183 buf[0] = 1; /* report ID */ 184 buf[1] = 2; 185 buf[2] = 42; 186 187 pthread_mutex_lock(&uhid_output_mtx); 188 189 memset(output_report, 0, sizeof(output_report)); 190 clock_gettime(CLOCK_REALTIME, &time_to_wait); 191 time_to_wait.tv_sec += 2; 192 193 err = write(self->hidraw_fd, buf, 3); 194 ASSERT_EQ(err, 3) TH_LOG("unexpected error while writing to hidraw node: %d", err); 195 196 err = pthread_cond_timedwait(&uhid_output_cond, &uhid_output_mtx, &time_to_wait); 197 ASSERT_OK(err) TH_LOG("error while calling waiting for the condition"); 198 199 ASSERT_EQ(output_report[0], 1); 200 ASSERT_EQ(output_report[1], 2); 201 ASSERT_EQ(output_report[2], 42); 202 203 /* call the revoke ioctl */ 204 err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); 205 ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); 206 207 /* inject one other event */ 208 buf[0] = 1; 209 buf[1] = 43; 210 err = write(self->hidraw_fd, buf, 3); 211 ASSERT_LT(err, 0) TH_LOG("unexpected success while writing to hidraw node: %d", err); 212 ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while writing to hidraw node: %d", 213 errno); 214 215 pthread_mutex_unlock(&uhid_output_mtx); 216} 217 218int main(int argc, char **argv) 219{ 220 return test_harness_run(argc, argv); 221}