monado/src/xrt/auxiliary/os/os_hid_hidraw.c

107 lines
1.9 KiB
C
Raw Normal View History

2019-05-03 14:47:45 +00:00
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Hid implementation based on hidraw.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup aux_os
*/
#include "os_hid.h"
#ifdef XRT_OS_LINUX
#include "util/u_misc.h"
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/hidraw.h>
#include <stdio.h>
struct hid_hidraw
{
struct os_hid_device base;
int fd;
};
static int
os_hidraw_read(struct os_hid_device *ohdev,
uint8_t *data,
size_t length,
int milliseconds)
{
struct hid_hidraw *hrdev = (struct hid_hidraw *)ohdev;
struct pollfd fds;
int ret;
if (milliseconds >= 0) {
fds.fd = hrdev->fd;
fds.events = POLLIN;
fds.revents = 0;
ret = poll(&fds, 1, milliseconds);
if (ret == -1 || ret == 0) {
// Error or timeout.
return ret;
} else if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) {
// Device disconnect?
return -1;
}
}
ret = read(hrdev->fd, data, length);
if (ret < 0 && (errno == EAGAIN || errno == EINPROGRESS)) {
// Process most likely received a signal.
ret = 0;
}
return ret;
}
static int
os_hidraw_write(struct os_hid_device *ohdev, const uint8_t *data, size_t length)
{
struct hid_hidraw *hrdev = (struct hid_hidraw *)ohdev;
return write(hrdev->fd, data, length);
}
static void
os_hidraw_destroy(struct os_hid_device *ohdev)
{
struct hid_hidraw *hrdev = (struct hid_hidraw *)ohdev;
close(hrdev->fd);
free(hrdev);
}
int
os_hid_open_hidraw(const char *path, struct os_hid_device **out_ohdev)
{
struct hid_hidraw *hrdev = U_TYPED_CALLOC(struct hid_hidraw);
hrdev->base.read = os_hidraw_read;
hrdev->base.write = os_hidraw_write;
hrdev->base.destroy = os_hidraw_destroy;
hrdev->fd = open(path, O_RDWR);
if (hrdev->fd < 0) {
free(hrdev);
return -1;
}
*out_ohdev = &hrdev->base;
return 0;
}
#endif