1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2c54ea491SAlan Ott /* 3c54ea491SAlan Ott * Hidraw Userspace Example 4c54ea491SAlan Ott * 5c54ea491SAlan Ott * Copyright (c) 2010 Alan Ott <alan@signal11.us> 6c54ea491SAlan Ott * Copyright (c) 2010 Signal 11 Software 7c54ea491SAlan Ott * 8c54ea491SAlan Ott * The code may be used by anyone for any purpose, 9c54ea491SAlan Ott * and can serve as a starting point for developing 10c54ea491SAlan Ott * applications using hidraw. 11c54ea491SAlan Ott */ 12c54ea491SAlan Ott 13c54ea491SAlan Ott /* Linux */ 14c54ea491SAlan Ott #include <linux/types.h> 15c54ea491SAlan Ott #include <linux/input.h> 16c54ea491SAlan Ott #include <linux/hidraw.h> 17c54ea491SAlan Ott 18cb3e85feSJiri Kosina /* 19cb3e85feSJiri Kosina * Ugly hack to work around failing compilation on systems that don't 20cb3e85feSJiri Kosina * yet populate new version of hidraw.h to userspace. 21cb3e85feSJiri Kosina */ 22cb3e85feSJiri Kosina #ifndef HIDIOCSFEATURE 23f3713053SJiri Kosina #warning Please have your distro update the userspace kernel headers 24cb3e85feSJiri Kosina #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) 25cb3e85feSJiri Kosina #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) 26cb3e85feSJiri Kosina #endif 27cb3e85feSJiri Kosina 28c54ea491SAlan Ott /* Unix */ 29c54ea491SAlan Ott #include <sys/ioctl.h> 30c54ea491SAlan Ott #include <sys/types.h> 31c54ea491SAlan Ott #include <sys/stat.h> 32c54ea491SAlan Ott #include <fcntl.h> 33c54ea491SAlan Ott #include <unistd.h> 34c54ea491SAlan Ott 35c54ea491SAlan Ott /* C */ 36c54ea491SAlan Ott #include <stdio.h> 37c54ea491SAlan Ott #include <string.h> 38c54ea491SAlan Ott #include <stdlib.h> 39c54ea491SAlan Ott #include <errno.h> 40c54ea491SAlan Ott 41c54ea491SAlan Ott const char *bus_str(int bus); 42c54ea491SAlan Ott 43c54ea491SAlan Ott int main(int argc, char **argv) 44c54ea491SAlan Ott { 45c54ea491SAlan Ott int fd; 46c54ea491SAlan Ott int i, res, desc_size = 0; 47c54ea491SAlan Ott char buf[256]; 48c54ea491SAlan Ott struct hidraw_report_descriptor rpt_desc; 49c54ea491SAlan Ott struct hidraw_devinfo info; 5004303f8eSPavel Machek char *device = "/dev/hidraw0"; 5104303f8eSPavel Machek 5204303f8eSPavel Machek if (argc > 1) 5304303f8eSPavel Machek device = argv[1]; 54c54ea491SAlan Ott 55c54ea491SAlan Ott /* Open the Device with non-blocking reads. In real life, 56c54ea491SAlan Ott don't use a hard coded path; use libudev instead. */ 5704303f8eSPavel Machek fd = open(device, O_RDWR|O_NONBLOCK); 58c54ea491SAlan Ott 59c54ea491SAlan Ott if (fd < 0) { 60c54ea491SAlan Ott perror("Unable to open device"); 61c54ea491SAlan Ott return 1; 62c54ea491SAlan Ott } 63c54ea491SAlan Ott 64c54ea491SAlan Ott memset(&rpt_desc, 0x0, sizeof(rpt_desc)); 65c54ea491SAlan Ott memset(&info, 0x0, sizeof(info)); 66c54ea491SAlan Ott memset(buf, 0x0, sizeof(buf)); 67c54ea491SAlan Ott 68c54ea491SAlan Ott /* Get Report Descriptor Size */ 69c54ea491SAlan Ott res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size); 70c54ea491SAlan Ott if (res < 0) 71c54ea491SAlan Ott perror("HIDIOCGRDESCSIZE"); 72c54ea491SAlan Ott else 73c54ea491SAlan Ott printf("Report Descriptor Size: %d\n", desc_size); 74c54ea491SAlan Ott 75c54ea491SAlan Ott /* Get Report Descriptor */ 76c54ea491SAlan Ott rpt_desc.size = desc_size; 77c54ea491SAlan Ott res = ioctl(fd, HIDIOCGRDESC, &rpt_desc); 78c54ea491SAlan Ott if (res < 0) { 79c54ea491SAlan Ott perror("HIDIOCGRDESC"); 80c54ea491SAlan Ott } else { 81c54ea491SAlan Ott printf("Report Descriptor:\n"); 82c54ea491SAlan Ott for (i = 0; i < rpt_desc.size; i++) 83c54ea491SAlan Ott printf("%hhx ", rpt_desc.value[i]); 84c54ea491SAlan Ott puts("\n"); 85c54ea491SAlan Ott } 86c54ea491SAlan Ott 87c54ea491SAlan Ott /* Get Raw Name */ 88c54ea491SAlan Ott res = ioctl(fd, HIDIOCGRAWNAME(256), buf); 89c54ea491SAlan Ott if (res < 0) 90c54ea491SAlan Ott perror("HIDIOCGRAWNAME"); 91c54ea491SAlan Ott else 92c54ea491SAlan Ott printf("Raw Name: %s\n", buf); 93c54ea491SAlan Ott 94c54ea491SAlan Ott /* Get Physical Location */ 95c54ea491SAlan Ott res = ioctl(fd, HIDIOCGRAWPHYS(256), buf); 96c54ea491SAlan Ott if (res < 0) 97c54ea491SAlan Ott perror("HIDIOCGRAWPHYS"); 98c54ea491SAlan Ott else 99c54ea491SAlan Ott printf("Raw Phys: %s\n", buf); 100c54ea491SAlan Ott 101c54ea491SAlan Ott /* Get Raw Info */ 102c54ea491SAlan Ott res = ioctl(fd, HIDIOCGRAWINFO, &info); 103c54ea491SAlan Ott if (res < 0) { 104c54ea491SAlan Ott perror("HIDIOCGRAWINFO"); 105c54ea491SAlan Ott } else { 106c54ea491SAlan Ott printf("Raw Info:\n"); 107c54ea491SAlan Ott printf("\tbustype: %d (%s)\n", 108c54ea491SAlan Ott info.bustype, bus_str(info.bustype)); 109c54ea491SAlan Ott printf("\tvendor: 0x%04hx\n", info.vendor); 110c54ea491SAlan Ott printf("\tproduct: 0x%04hx\n", info.product); 111c54ea491SAlan Ott } 112c54ea491SAlan Ott 113c54ea491SAlan Ott /* Set Feature */ 114c54ea491SAlan Ott buf[0] = 0x9; /* Report Number */ 115c54ea491SAlan Ott buf[1] = 0xff; 116c54ea491SAlan Ott buf[2] = 0xff; 117c54ea491SAlan Ott buf[3] = 0xff; 118c54ea491SAlan Ott res = ioctl(fd, HIDIOCSFEATURE(4), buf); 119c54ea491SAlan Ott if (res < 0) 120c54ea491SAlan Ott perror("HIDIOCSFEATURE"); 121c54ea491SAlan Ott else 122*31a8b3eeSJonathan Davies printf("ioctl HIDIOCSFEATURE returned: %d\n", res); 123c54ea491SAlan Ott 124c54ea491SAlan Ott /* Get Feature */ 125c54ea491SAlan Ott buf[0] = 0x9; /* Report Number */ 126c54ea491SAlan Ott res = ioctl(fd, HIDIOCGFEATURE(256), buf); 127c54ea491SAlan Ott if (res < 0) { 128c54ea491SAlan Ott perror("HIDIOCGFEATURE"); 129c54ea491SAlan Ott } else { 130c54ea491SAlan Ott printf("ioctl HIDIOCGFEATURE returned: %d\n", res); 131c54ea491SAlan Ott printf("Report data (not containing the report number):\n\t"); 132c54ea491SAlan Ott for (i = 0; i < res; i++) 133c54ea491SAlan Ott printf("%hhx ", buf[i]); 134c54ea491SAlan Ott puts("\n"); 135c54ea491SAlan Ott } 136c54ea491SAlan Ott 137c54ea491SAlan Ott /* Send a Report to the Device */ 138c54ea491SAlan Ott buf[0] = 0x1; /* Report Number */ 139c54ea491SAlan Ott buf[1] = 0x77; 140c54ea491SAlan Ott res = write(fd, buf, 2); 141c54ea491SAlan Ott if (res < 0) { 142c54ea491SAlan Ott printf("Error: %d\n", errno); 143c54ea491SAlan Ott perror("write"); 144c54ea491SAlan Ott } else { 145c54ea491SAlan Ott printf("write() wrote %d bytes\n", res); 146c54ea491SAlan Ott } 147c54ea491SAlan Ott 148c54ea491SAlan Ott /* Get a report from the device */ 149c54ea491SAlan Ott res = read(fd, buf, 16); 150c54ea491SAlan Ott if (res < 0) { 151c54ea491SAlan Ott perror("read"); 152c54ea491SAlan Ott } else { 153c54ea491SAlan Ott printf("read() read %d bytes:\n\t", res); 154c54ea491SAlan Ott for (i = 0; i < res; i++) 155c54ea491SAlan Ott printf("%hhx ", buf[i]); 156c54ea491SAlan Ott puts("\n"); 157c54ea491SAlan Ott } 158c54ea491SAlan Ott close(fd); 159c54ea491SAlan Ott return 0; 160c54ea491SAlan Ott } 161c54ea491SAlan Ott 162c54ea491SAlan Ott const char * 163c54ea491SAlan Ott bus_str(int bus) 164c54ea491SAlan Ott { 165c54ea491SAlan Ott switch (bus) { 166c54ea491SAlan Ott case BUS_USB: 167c54ea491SAlan Ott return "USB"; 168c54ea491SAlan Ott break; 169c54ea491SAlan Ott case BUS_HIL: 170c54ea491SAlan Ott return "HIL"; 171c54ea491SAlan Ott break; 172c54ea491SAlan Ott case BUS_BLUETOOTH: 173c54ea491SAlan Ott return "Bluetooth"; 174c54ea491SAlan Ott break; 175c54ea491SAlan Ott case BUS_VIRTUAL: 176c54ea491SAlan Ott return "Virtual"; 177c54ea491SAlan Ott break; 178c54ea491SAlan Ott default: 179c54ea491SAlan Ott return "Other"; 180c54ea491SAlan Ott break; 181c54ea491SAlan Ott } 182c54ea491SAlan Ott } 183