FIDO-Raw
view release on metacpan or search on metacpan
deps/hidapi/libusb/hid.c view on Meta::CPAN
}
else {
/* Unable to open any devices. */
free_hid_device(dev);
return NULL;
}
}
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
{
int res;
int report_number = data[0];
int skipped_report_id = 0;
if (report_number == 0x0) {
data++;
length--;
skipped_report_id = 1;
}
if (dev->output_endpoint <= 0) {
/* No interrupt out endpoint. Use the Control Endpoint */
res = libusb_control_transfer(dev->device_handle,
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
0x09/*HID Set_Report*/,
(2/*HID output*/ << 8) | report_number,
dev->interface,
(unsigned char *)data, length,
1000/*timeout millis*/);
if (res < 0)
return -1;
if (skipped_report_id)
length++;
return length;
}
else {
/* Use the interrupt out endpoint */
int actual_length;
res = libusb_interrupt_transfer(dev->device_handle,
dev->output_endpoint,
(unsigned char*)data,
length,
&actual_length, 1000);
if (res < 0)
return -1;
if (skipped_report_id)
actual_length++;
return actual_length;
}
}
/* Helper function, to simplify hid_read().
This should be called with dev->mutex locked. */
static int return_data(hid_device *dev, unsigned char *data, size_t length)
{
/* Copy the data out of the linked list item (rpt) into the
return buffer (data), and delete the liked list item. */
struct input_report *rpt = dev->input_reports;
size_t len = (length < rpt->len)? length: rpt->len;
if (len > 0)
memcpy(data, rpt->data, len);
dev->input_reports = rpt->next;
free(rpt->data);
free(rpt);
return len;
}
static void cleanup_mutex(void *param)
{
hid_device *dev = param;
pthread_mutex_unlock(&dev->mutex);
}
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{
int bytes_read = -1;
#if 0
int transferred;
int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
LOG("transferred: %d\n", transferred);
return transferred;
#endif
pthread_mutex_lock(&dev->mutex);
pthread_cleanup_push(&cleanup_mutex, dev);
/* There's an input report queued up. Return it. */
if (dev->input_reports) {
/* Return the first one */
bytes_read = return_data(dev, data, length);
goto ret;
}
if (dev->shutdown_thread) {
/* This means the device has been disconnected.
An error code of -1 should be returned. */
bytes_read = -1;
goto ret;
}
if (milliseconds == -1) {
/* Blocking */
while (!dev->input_reports && !dev->shutdown_thread) {
pthread_cond_wait(&dev->condition, &dev->mutex);
}
if (dev->input_reports) {
bytes_read = return_data(dev, data, length);
}
}
else if (milliseconds > 0) {
/* Non-blocking, but called with timeout. */
( run in 0.504 second using v1.01-cache-2.11-cpan-5b529ec07f3 )