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