brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · f8b4f7f Raw
238 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2022-2024 Red Hat */3 4#include "hid_common.h"5 6/* for older kernels */7#ifndef HIDIOCREVOKE8#define HIDIOCREVOKE	      _IOW('H', 0x0D, int) /* Revoke device access */9#endif /* HIDIOCREVOKE */10 11FIXTURE(hidraw) {12	int dev_id;13	int uhid_fd;14	int hidraw_fd;15	int hid_id;16	pthread_t tid;17};18static 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 25FIXTURE_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 38FIXTURE_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 */66TEST_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 hidraw73 */74TEST_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 hidraw94 * node and check that we can not read any more data.95 */96TEST_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 */133TEST_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 */151TEST_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 hidraw190 * node and check that we can not read any more data.191 */192TEST_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 234int main(int argc, char **argv)235{236	return test_harness_run(argc, argv);237}238