xref: /openbmc/linux/samples/hidraw/hid-example.c (revision ee89bd6b)
1 /*
2  * Hidraw Userspace Example
3  *
4  * Copyright (c) 2010 Alan Ott <alan@signal11.us>
5  * Copyright (c) 2010 Signal 11 Software
6  *
7  * The code may be used by anyone for any purpose,
8  * and can serve as a starting point for developing
9  * applications using hidraw.
10  */
11 
12 /* Linux */
13 #include <linux/types.h>
14 #include <linux/input.h>
15 #include <linux/hidraw.h>
16 
17 /*
18  * Ugly hack to work around failing compilation on systems that don't
19  * yet populate new version of hidraw.h to userspace.
20  */
21 #ifndef HIDIOCSFEATURE
22 #warning Please have your distro update the userspace kernel headers
23 #define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
24 #define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
25 #endif
26 
27 /* Unix */
28 #include <sys/ioctl.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 
34 /* C */
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 
40 const char *bus_str(int bus);
41 
42 int main(int argc, char **argv)
43 {
44 	int fd;
45 	int i, res, desc_size = 0;
46 	char buf[256];
47 	struct hidraw_report_descriptor rpt_desc;
48 	struct hidraw_devinfo info;
49 
50 	/* Open the Device with non-blocking reads. In real life,
51 	   don't use a hard coded path; use libudev instead. */
52 	fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);
53 
54 	if (fd < 0) {
55 		perror("Unable to open device");
56 		return 1;
57 	}
58 
59 	memset(&rpt_desc, 0x0, sizeof(rpt_desc));
60 	memset(&info, 0x0, sizeof(info));
61 	memset(buf, 0x0, sizeof(buf));
62 
63 	/* Get Report Descriptor Size */
64 	res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
65 	if (res < 0)
66 		perror("HIDIOCGRDESCSIZE");
67 	else
68 		printf("Report Descriptor Size: %d\n", desc_size);
69 
70 	/* Get Report Descriptor */
71 	rpt_desc.size = desc_size;
72 	res = ioctl(fd, HIDIOCGRDESC, &rpt_desc);
73 	if (res < 0) {
74 		perror("HIDIOCGRDESC");
75 	} else {
76 		printf("Report Descriptor:\n");
77 		for (i = 0; i < rpt_desc.size; i++)
78 			printf("%hhx ", rpt_desc.value[i]);
79 		puts("\n");
80 	}
81 
82 	/* Get Raw Name */
83 	res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
84 	if (res < 0)
85 		perror("HIDIOCGRAWNAME");
86 	else
87 		printf("Raw Name: %s\n", buf);
88 
89 	/* Get Physical Location */
90 	res = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
91 	if (res < 0)
92 		perror("HIDIOCGRAWPHYS");
93 	else
94 		printf("Raw Phys: %s\n", buf);
95 
96 	/* Get Raw Info */
97 	res = ioctl(fd, HIDIOCGRAWINFO, &info);
98 	if (res < 0) {
99 		perror("HIDIOCGRAWINFO");
100 	} else {
101 		printf("Raw Info:\n");
102 		printf("\tbustype: %d (%s)\n",
103 			info.bustype, bus_str(info.bustype));
104 		printf("\tvendor: 0x%04hx\n", info.vendor);
105 		printf("\tproduct: 0x%04hx\n", info.product);
106 	}
107 
108 	/* Set Feature */
109 	buf[0] = 0x9; /* Report Number */
110 	buf[1] = 0xff;
111 	buf[2] = 0xff;
112 	buf[3] = 0xff;
113 	res = ioctl(fd, HIDIOCSFEATURE(4), buf);
114 	if (res < 0)
115 		perror("HIDIOCSFEATURE");
116 	else
117 		printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
118 
119 	/* Get Feature */
120 	buf[0] = 0x9; /* Report Number */
121 	res = ioctl(fd, HIDIOCGFEATURE(256), buf);
122 	if (res < 0) {
123 		perror("HIDIOCGFEATURE");
124 	} else {
125 		printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
126 		printf("Report data (not containing the report number):\n\t");
127 		for (i = 0; i < res; i++)
128 			printf("%hhx ", buf[i]);
129 		puts("\n");
130 	}
131 
132 	/* Send a Report to the Device */
133 	buf[0] = 0x1; /* Report Number */
134 	buf[1] = 0x77;
135 	res = write(fd, buf, 2);
136 	if (res < 0) {
137 		printf("Error: %d\n", errno);
138 		perror("write");
139 	} else {
140 		printf("write() wrote %d bytes\n", res);
141 	}
142 
143 	/* Get a report from the device */
144 	res = read(fd, buf, 16);
145 	if (res < 0) {
146 		perror("read");
147 	} else {
148 		printf("read() read %d bytes:\n\t", res);
149 		for (i = 0; i < res; i++)
150 			printf("%hhx ", buf[i]);
151 		puts("\n");
152 	}
153 	close(fd);
154 	return 0;
155 }
156 
157 const char *
158 bus_str(int bus)
159 {
160 	switch (bus) {
161 	case BUS_USB:
162 		return "USB";
163 		break;
164 	case BUS_HIL:
165 		return "HIL";
166 		break;
167 	case BUS_BLUETOOTH:
168 		return "Bluetooth";
169 		break;
170 	case BUS_VIRTUAL:
171 		return "Virtual";
172 		break;
173 	default:
174 		return "Other";
175 		break;
176 	}
177 }
178