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