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 * If you need this, please have your distro update the kernel headers. 22 */ 23 #ifndef HIDIOCSFEATURE 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 51 /* Open the Device with non-blocking reads. In real life, 52 don't use a hard coded path; use libudev instead. */ 53 fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK); 54 55 if (fd < 0) { 56 perror("Unable to open device"); 57 return 1; 58 } 59 60 memset(&rpt_desc, 0x0, sizeof(rpt_desc)); 61 memset(&info, 0x0, sizeof(info)); 62 memset(buf, 0x0, sizeof(buf)); 63 64 /* Get Report Descriptor Size */ 65 res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size); 66 if (res < 0) 67 perror("HIDIOCGRDESCSIZE"); 68 else 69 printf("Report Descriptor Size: %d\n", desc_size); 70 71 /* Get Report Descriptor */ 72 rpt_desc.size = desc_size; 73 res = ioctl(fd, HIDIOCGRDESC, &rpt_desc); 74 if (res < 0) { 75 perror("HIDIOCGRDESC"); 76 } else { 77 printf("Report Descriptor:\n"); 78 for (i = 0; i < rpt_desc.size; i++) 79 printf("%hhx ", rpt_desc.value[i]); 80 puts("\n"); 81 } 82 83 /* Get Raw Name */ 84 res = ioctl(fd, HIDIOCGRAWNAME(256), buf); 85 if (res < 0) 86 perror("HIDIOCGRAWNAME"); 87 else 88 printf("Raw Name: %s\n", buf); 89 90 /* Get Physical Location */ 91 res = ioctl(fd, HIDIOCGRAWPHYS(256), buf); 92 if (res < 0) 93 perror("HIDIOCGRAWPHYS"); 94 else 95 printf("Raw Phys: %s\n", buf); 96 97 /* Get Raw Info */ 98 res = ioctl(fd, HIDIOCGRAWINFO, &info); 99 if (res < 0) { 100 perror("HIDIOCGRAWINFO"); 101 } else { 102 printf("Raw Info:\n"); 103 printf("\tbustype: %d (%s)\n", 104 info.bustype, bus_str(info.bustype)); 105 printf("\tvendor: 0x%04hx\n", info.vendor); 106 printf("\tproduct: 0x%04hx\n", info.product); 107 } 108 109 /* Set Feature */ 110 buf[0] = 0x9; /* Report Number */ 111 buf[1] = 0xff; 112 buf[2] = 0xff; 113 buf[3] = 0xff; 114 res = ioctl(fd, HIDIOCSFEATURE(4), buf); 115 if (res < 0) 116 perror("HIDIOCSFEATURE"); 117 else 118 printf("ioctl HIDIOCGFEATURE returned: %d\n", res); 119 120 /* Get Feature */ 121 buf[0] = 0x9; /* Report Number */ 122 res = ioctl(fd, HIDIOCGFEATURE(256), buf); 123 if (res < 0) { 124 perror("HIDIOCGFEATURE"); 125 } else { 126 printf("ioctl HIDIOCGFEATURE returned: %d\n", res); 127 printf("Report data (not containing the report number):\n\t"); 128 for (i = 0; i < res; i++) 129 printf("%hhx ", buf[i]); 130 puts("\n"); 131 } 132 133 /* Send a Report to the Device */ 134 buf[0] = 0x1; /* Report Number */ 135 buf[1] = 0x77; 136 res = write(fd, buf, 2); 137 if (res < 0) { 138 printf("Error: %d\n", errno); 139 perror("write"); 140 } else { 141 printf("write() wrote %d bytes\n", res); 142 } 143 144 /* Get a report from the device */ 145 res = read(fd, buf, 16); 146 if (res < 0) { 147 perror("read"); 148 } else { 149 printf("read() read %d bytes:\n\t", res); 150 for (i = 0; i < res; i++) 151 printf("%hhx ", buf[i]); 152 puts("\n"); 153 } 154 close(fd); 155 return 0; 156 } 157 158 const char * 159 bus_str(int bus) 160 { 161 switch (bus) { 162 case BUS_USB: 163 return "USB"; 164 break; 165 case BUS_HIL: 166 return "HIL"; 167 break; 168 case BUS_BLUETOOTH: 169 return "Bluetooth"; 170 break; 171 case BUS_VIRTUAL: 172 return "Virtual"; 173 break; 174 default: 175 return "Other"; 176 break; 177 } 178 } 179