/* HIDAPI - Multi-Platform library for communication with HID devices.
8/22/2009 Alan Ott, Signal 11 Software
Hidraw-Version
*/
#include "hidapi.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/hidraw.h>
static byte parseget(const byte*&desc,int¶m) {
byte r=*desc++;
switch (r&3) { // encodes number of following bytes
case 1: param=*desc++; break;
case 2: param=*(*reinterpret_cast<const int16_t**>(&desc))++; break;
case 3: param=*(*reinterpret_cast<const int32_t**>(&desc))++; break;
default: param=0;
}
return r;
}
static bool hidparse(const byte*desc,unsigned len,hid::Caps&caps) {
int globalitems[16],localitems[16];
memset(&caps,0,sizeof caps);
auto end=desc+len;
while (desc<end) {
int param;
byte r=parseget(desc,param);
//fprintf(stderr," %02X(%d)",r,param);
switch (r&0x0C) {
case 0x04: globalitems[r>>4]=param; break;
case 0x08: localitems[r>>4]=param; break;
case 0x00: {
int rsize=globalitems[7],rid=globalitems[8],rcount=globalitems[9];
if (rcount>1) rsize = (rsize+7)&~7; // byte-align!
rsize*=rcount;
switch (r&0xF0) {
case 0x80: caps.InputReportByteLength+=rsize; break;
case 0x90: caps.OutputReportByteLength+=rsize; break;
case 0xB0: caps.FeatureReportByteLength+=rsize; break;
}
}break;
}
}
auto adjust = [](int&x) {if (x) x = (x+15)>>3;};
adjust(caps.OutputReportByteLength);
adjust(caps.InputReportByteLength);
adjust(caps.FeatureReportByteLength);
return true;
}
HidDev::HidDev():handle(0) {}
bool HidDev::connect(unsigned n) {
++n;
for (unsigned i=0;;i++) {
char name[32];
snprintf(name,sizeof name,"/dev/hidraw%u",i);
int h=open(name,O_RDWR/*|O_NONBLOCK*/);
if (h<0) break;
hidraw_devinfo di;
ioctl(h,HIDIOCGRAWINFO,&di);
attr.VendorID=di.vendor;
attr.ProductID=di.product;
attr.VersionNumber=0; // Not available using hidraw
handle=h;
if (match() && !--n) {
hidraw_report_descriptor rd;
ioctl(h,HIDIOCGRDESCSIZE,&rd.size);
ioctl(h,HIDIOCGRDESC,&rd);
hidparse(rd.value,rd.size,caps);
//fprintf(stderr,"in=%u,out=%u,feat=%u",
// caps.InputReportByteLength,
// caps.OutputReportByteLength,
// caps.FeatureReportByteLength);
break;
}else{
close(h);
handle=0;
}
}
return operator bool();
}
HidDev::~HidDev() {
if (handle) close(handle);
}
bool HidDev::setOutputReport(const byte*data, unsigned attempts, unsigned ms) {
byte report_number = *data;
int len=caps.OutputReportByteLength;
// if (!report_number) ++data,--len;
do{
if (write(handle,data,len)>=0) return true;
}while(--attempts);
return false;
}
bool HidDev::getInputReport(byte*data, unsigned attempts, unsigned ms) {
byte report_number=*data;
int len=caps.InputReportByteLength;
if (!report_number) ++data,--len;
do{
if (read(handle,data,len)>=0) return true; // try interrupt pipe first
}while(--attempts);
return false;
}
bool HidDev::setFeatureReport(const byte*data, unsigned attempts) {
byte report_number = *data;
int len=caps.FeatureReportByteLength;
// if (!report_number) ++data,--len;
do{
if (ioctl(handle,HIDIOCSFEATURE(len),data)>=0) return true;
retry_msg();
}while(--attempts);
return false;
}
bool HidDev::getFeatureReport(byte*data, unsigned attempts) {
byte report_number = *data;
int len=caps.FeatureReportByteLength;
// if (!report_number) ++data,--len;
do{
if (ioctl(handle,HIDIOCGFEATURE(len),data)>=0) return true;
retry_msg();
}while(--attempts);
return false;
}
HidDev::RetStr HidDev::getIndexedStr(byte idx) const{
return {0};
}
HidDev::RetStr HidDev::getManufacturerStr() const{
RetStr r; // will be optimized-out
if (ioctl(handle,HIDIOCGRAWNAME(256),&r.s)<0) r.s[0]=0;
return r;
}
HidDev::RetStr HidDev::getProductStr() const{
return {0};
}
HidDev::RetStr HidDev::getSerialStr() const{
return {0};
}
uint32_t HidDev::vidpid() const{
return *reinterpret_cast<const uint32_t*>(&attr);
}
Vorgefundene Kodierung: UTF-8 | 0
|