| Alan Ott | c54ea49 | 2011-03-19 20:29:44 -0400 | [diff] [blame] | 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 |  | 
| Jiri Kosina | cb3e85f | 2011-04-09 01:43:18 +0200 | [diff] [blame] | 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 |  | 
| Alan Ott | c54ea49 | 2011-03-19 20:29:44 -0400 | [diff] [blame] | 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 | } |