crashtest-r0ket/misc/openbeacon/lpc13xx/hid-client/rawhid.c

153 lines
4.3 KiB
C

/* Raw HID I/O Routines
* Copyright 2008, PJRC.COM, LLC
* paul@pjrc.com
*
* You may redistribute this program and/or modify it under the terms
* of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/
*/
// This code will someday be turned into "librawhid", an easy-to-use
// and truly cross platform library for accessing HID reports. But
// there are many complexities not properly handled by this simple
// code that would be expected from a high quality library. In
// particular, how report IDs are handled is not uniform on the 3
// platforms. The mac code uses a single buffer which assumes no
// other functions can cause the "run loop" to process HID callbacks.
// The linux version doesn't extract usage and usage page from the
// report descriptor and just hardcodes a signature for the Teensy
// USB debug example. Lacking from all platforms are functions to
// manage multiple devices and robust detection of device removal
// and attachment. There are probably lots of other issues... this
// code has really only been used in 2 projects. If you use it,
// please report bugs to paul@pjrc.com
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "rawhid.h"
#ifdef OPERATING_SYSTEM
#undef OPERATING_SYSTEM
#endif
/*************************************************************************/
/** **/
/** Linux **/
/** **/
/*************************************************************************/
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/hidraw.h>
struct rawhid_struct {
int fd;
int name;
int isok;
};
rawhid_t * rawhid_open_only1(int vid, int pid, int usage_page, int usage)
{
struct rawhid_struct *hid;
struct stat devstat;
struct hidraw_devinfo info;
struct hidraw_report_descriptor *desc;
char buf[512];
int r, i, fd=-1, len, found=0;
printf("Searching for device using hidraw....\n");
for (i=0; i<HIDRAW_MAX_DEVICES; i++) {
if (fd > 0) close(fd);
snprintf(buf, sizeof(buf), "/dev/hidraw%d", i);
r = stat(buf, &devstat);
if (r < 0) continue;
printf("device: %s\n", buf);
fd = open(buf, O_RDWR);
if (fd < 0) continue;
printf(" opened\n");
r = ioctl(fd, HIDIOCGRAWINFO, &info);
if (r < 0) continue;
printf(" vid=%04X, pid=%04X\n", info.vendor & 0xFFFF, info.product & 0xFFFF);
r = ioctl(fd, HIDIOCGRDESCSIZE, &len);
if (r < 0 || len < 1) continue;
printf(" len=%u\n", len);
desc = (struct hidraw_report_descriptor *)buf;
if (len > sizeof(buf)-sizeof(int)) len = sizeof(buf)-sizeof(int);
desc->size = len;
r = ioctl(fd, HIDIOCGRDESC, desc);
if (r < 0) continue;
printf(" Match\n");
found = 1;
break;
}
if (!found) {
if (fd > 0) close(fd);
return NULL;
}
hid = (struct rawhid_struct *)malloc(sizeof(struct rawhid_struct));
if (!hid) {
close(fd);
return NULL;
}
hid->fd = fd;
return hid;
}
int rawhid_status(rawhid_t *hid)
{
// TODO: how to check if device is still online?
return -1;
}
int rawhid_read(rawhid_t *h, void *buf, int bufsize, int timeout_ms)
{
struct rawhid_struct *hid;
int num;
hid = (struct rawhid_struct *)h;
if (!hid || hid->fd < 0) return -1;
while (1) {
num = read(hid->fd, buf, bufsize);
if (num < 0) {
if (errno == EINTR || errno == EAGAIN) continue;
if (errno == EIO) {
return -1;
printf("I/O Error\n");
}
printf("read error, r=%d, errno=%d\n", num, errno);
return -1;
}
//printf("read %d bytes\n", num);
return num;
}
}
void rawhid_close(rawhid_t *h)
{
struct rawhid_struct *hid;
hid = (struct rawhid_struct *)h;
if (!hid || hid->fd < 0) return;
close(hid->fd);
hid->fd = -1;
}