183 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Hidraw Userspace Example4 *5 * Copyright (c) 2010 Alan Ott <alan@signal11.us>6 * Copyright (c) 2010 Signal 11 Software7 *8 * The code may be used by anyone for any purpose,9 * and can serve as a starting point for developing10 * 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't20 * yet populate new version of hidraw.h to userspace.21 */22#ifndef HIDIOCSFEATURE23#warning Please have your distro update the userspace kernel headers24#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)25#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)26#endif27 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 41const char *bus_str(int bus);42 43int 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 else73 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 else92 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 else99 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 else122 printf("ioctl HIDIOCSFEATURE 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:\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 162const char *163bus_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