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