UsbEndpoint * usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) { UsbEndpoint *endpoint; const UsbEndpointDescriptor *descriptor; if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint; if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) { { const char *direction; const char *transfer; switch (USB_ENDPOINT_DIRECTION(descriptor)) { default: direction = "?"; break; case UsbEndpointDirection_Input: direction = "in"; break; case UsbEndpointDirection_Output: direction = "out"; break; } switch (USB_ENDPOINT_TRANSFER(descriptor)) { default: transfer = "?"; break; case UsbEndpointTransfer_Control: transfer = "ctl"; break; case UsbEndpointTransfer_Isochronous: transfer = "iso"; break; case UsbEndpointTransfer_Bulk: transfer = "blk"; break; case UsbEndpointTransfer_Interrupt: transfer = "int"; break; } logMessage(LOG_DEBUG, "USB: ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms", descriptor->bEndpointAddress, direction, transfer, getLittleEndian16(descriptor->wMaxPacketSize), descriptor->bInterval); } if ((endpoint = malloc(sizeof(*endpoint)))) { memset(endpoint, 0, sizeof(*endpoint)); endpoint->device = device; endpoint->descriptor = descriptor; switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) { case UsbEndpointDirection_Input: endpoint->direction.input.pending = NULL; endpoint->direction.input.completed = NULL; endpoint->direction.input.buffer = NULL; endpoint->direction.input.length = 0; endpoint->direction.input.asynchronous = 0; break; } endpoint->extension = NULL; if (usbAllocateEndpointExtension(endpoint)) { if (enqueueItem(device->endpoints, endpoint)) return endpoint; usbDeallocateEndpointExtension(endpoint->extension); } free(endpoint); } } return NULL; }
ssize_t usbReadEndpoint ( UsbDevice *device, unsigned char endpointNumber, void *buffer, size_t length, int timeout ) { UsbDeviceExtension *devx = device->extension; const UsbEndpoint *endpoint; if ((endpoint = usbGetInputEndpoint(device, endpointNumber))) { const UsbEndpointDescriptor *descriptor = endpoint->descriptor; UsbEndpointTransfer transfer = USB_ENDPOINT_TRANSFER(descriptor); ssize_t result = -1; switch (transfer) { case UsbEndpointTransfer_Bulk: result = usb_bulk_read(devx->handle, descriptor->bEndpointAddress, buffer, length, timeout); break; case UsbEndpointTransfer_Interrupt: result = usb_interrupt_read(devx->handle, descriptor->bEndpointAddress, buffer, length, timeout); break; default: logMessage(LOG_ERR, "USB endpoint input transfer not supported: 0X%02X", transfer); result = -ENOSYS; break; } if (result >= 0) { if (!usbApplyInputFilters(device, buffer, length, &result)) { result = -EIO; } } if (result >= 0) return result; errno = -result; } #if defined(__MINGW32__) && !defined(ETIMEDOUT) # define ETIMEDOUT 116 #endif /* __MINGW32__ && !ETIMEDOUT */ #ifdef ETIMEDOUT if (errno == ETIMEDOUT) errno = EAGAIN; #endif /* ETIMEDOUT */ if (errno != EAGAIN) logSystemError("USB endpoint read"); return -1; }
ssize_t usbReadEndpoint ( UsbDevice *device, unsigned char endpointNumber, void *buffer, size_t length, int timeout ) { UsbDeviceExtension *devx = device->extension; if (usbGetHandle(devx)) { const UsbEndpoint *endpoint; if ((endpoint = usbGetInputEndpoint(device, endpointNumber))) { const UsbEndpointDescriptor *descriptor = endpoint->descriptor; UsbEndpointTransfer transfer = USB_ENDPOINT_TRANSFER(descriptor); int actual_length; int result; switch (transfer) { case UsbEndpointTransfer_Bulk: result = libusb_bulk_transfer(devx->handle, descriptor->bEndpointAddress, buffer, length, &actual_length, timeout); break; case UsbEndpointTransfer_Interrupt: result = libusb_interrupt_transfer(devx->handle, descriptor->bEndpointAddress, buffer, length, &actual_length, timeout); break; default: logMessage(LOG_ERR, "USB endpoint input transfer not supported: 0X%02X", transfer); result = LIBUSB_ERROR_NOT_SUPPORTED; break; } if (result == LIBUSB_SUCCESS) { ssize_t count = result; if (usbApplyInputFilters(device, buffer, length, &count)) return count; result = LIBUSB_ERROR_IO; } usbSetErrno(result, NULL); } } if (errno != EAGAIN) logSystemError("USB endpoint read"); return -1; }
ssize_t usbReadEndpoint ( UsbDevice *device, unsigned char endpointNumber, void *buffer, size_t length, int timeout ) { ssize_t count = -1; UsbEndpoint *endpoint; if ((endpoint = usbGetInputEndpoint(device, endpointNumber))) { UsbEndpointTransfer transfer = USB_ENDPOINT_TRANSFER(endpoint->descriptor); switch (transfer) { case UsbEndpointTransfer_Bulk: count = usbBulkTransfer(endpoint, buffer, length, timeout); break; case UsbEndpointTransfer_Interrupt: { struct usbdevfs_urb *urb = usbInterruptTransfer(endpoint, NULL, length, timeout); if (urb) { count = urb->actual_length; if (count > length) count = length; memcpy(buffer, urb->buffer, count); free(urb); } break; } default: logMessage(LOG_ERR, "USB input transfer not supported: %d", transfer); errno = ENOSYS; break; } if (count != -1) { if (!usbApplyInputFilters(device, buffer, length, &count)) { errno = EIO; count = -1; } } } return count; }
ssize_t usbWriteEndpoint ( UsbDevice *device, unsigned char endpointNumber, const void *buffer, size_t length, int timeout ) { UsbDeviceExtension *devx = device->extension; UsbEndpoint *endpoint; if ((endpoint = usbGetOutputEndpoint(device, endpointNumber))) { const UsbEndpointDescriptor *descriptor = endpoint->descriptor; UsbEndpointTransfer transfer = USB_ENDPOINT_TRANSFER(descriptor); int result = -1; usbLogEndpointData(endpoint, "output", buffer, length); switch (transfer) { case UsbEndpointTransfer_Bulk: result = usb_bulk_write(devx->handle, descriptor->bEndpointAddress, (char *)buffer, length, timeout); break; case UsbEndpointTransfer_Interrupt: result = usb_interrupt_write(devx->handle, descriptor->bEndpointAddress, (char *)buffer, length, timeout); break; default: logMessage(LOG_ERR, "USB endpoint output transfer not supported: 0X%02X", transfer); result = -ENOSYS; break; } if (result >= 0) return result; errno = -result; } logSystemError("USB endpoint write"); return -1; }
static const UsbEndpointDescriptor * usbFindInterruptInputEndpoint (UsbDevice *device, const UsbInterfaceDescriptor *interface) { const UsbDescriptor *descriptor = (const UsbDescriptor *)interface; while (usbNextDescriptor(device, &descriptor)) { if (descriptor->header.bDescriptorType == UsbDescriptorType_Interface) break; if (descriptor->header.bDescriptorType == UsbDescriptorType_Endpoint) { if (USB_ENDPOINT_DIRECTION(&descriptor->endpoint) == UsbEndpointDirection_Input) { if (USB_ENDPOINT_TRANSFER(&descriptor->endpoint) == UsbEndpointTransfer_Interrupt) { return &descriptor->endpoint; } } } } logMessage(LOG_WARNING, "USB: interrupt input endpoint descriptor not found"); errno = ENOENT; return NULL; }
ssize_t usbWriteEndpoint ( UsbDevice *device, unsigned char endpointNumber, const void *buffer, size_t length, int timeout ) { UsbEndpoint *endpoint; if ((endpoint = usbGetOutputEndpoint(device, endpointNumber))) { UsbEndpointTransfer transfer = USB_ENDPOINT_TRANSFER(endpoint->descriptor); switch (transfer) { case UsbEndpointTransfer_Interrupt: case UsbEndpointTransfer_Bulk: return usbBulkTransfer(endpoint, (void *)buffer, length, timeout); /* case UsbEndpointTransfer_Interrupt: { struct usbdevfs_urb *urb = usbInterruptTransfer(endpoint, (void *)buffer, length, timeout); if (urb) { ssize_t count = urb->actual_length; free(urb); return count; } break; } */ default: logMessage(LOG_ERR, "USB output transfer not supported: %d", transfer); errno = ENOSYS; break; } } return -1; }
void * usbSubmitRequest ( UsbDevice *device, unsigned char endpointAddress, void *buffer, size_t length, void *context ) { UsbDeviceExtension *devx = device->extension; if (usbOpenUsbfsFile(devx)) { UsbEndpoint *endpoint; if ((endpoint = usbGetEndpoint(device, endpointAddress))) { struct usbdevfs_urb *urb; if ((urb = malloc(sizeof(*urb) + length))) { memset(urb, 0, sizeof(*urb)); urb->endpoint = endpointAddress; urb->flags = 0; urb->signr = 0; urb->usercontext = context; urb->buffer = (urb->buffer_length = length)? (urb + 1): NULL; if (buffer) if (USB_ENDPOINT_DIRECTION(endpoint->descriptor) == UsbEndpointDirection_Output) memcpy(urb->buffer, buffer, length); switch (USB_ENDPOINT_TRANSFER(endpoint->descriptor)) { case UsbEndpointTransfer_Control: urb->type = USBDEVFS_URB_TYPE_CONTROL; break; case UsbEndpointTransfer_Isochronous: urb->type = USBDEVFS_URB_TYPE_ISO; break; case UsbEndpointTransfer_Interrupt: case UsbEndpointTransfer_Bulk: urb->type = USBDEVFS_URB_TYPE_BULK; break; } /* logMessage(LOG_DEBUG, "USB submit: urb=%p typ=%02X ept=%02X flg=%X sig=%d buf=%p len=%d ctx=%p", urb, urb->type, urb->endpoint, urb->flags, urb->signr, urb->buffer, urb->buffer_length, urb->usercontext); */ submit: if (ioctl(devx->usbfsFile, USBDEVFS_SUBMITURB, urb) != -1) return urb; if ((errno == EINVAL) && (USB_ENDPOINT_TRANSFER(endpoint->descriptor) == UsbEndpointTransfer_Interrupt) && (urb->type == USBDEVFS_URB_TYPE_BULK)) { urb->type = USBDEVFS_URB_TYPE_INTERRUPT; goto submit; } /* UHCI support returns ENXIO if a URB is already submitted. */ if (errno != ENXIO) logSystemError("USB URB submit"); free(urb); } else { logSystemError("USB URB allocate"); } } } return NULL; }
UsbEndpoint * usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) { UsbEndpoint *endpoint; const UsbEndpointDescriptor *descriptor; if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint; if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) { { const char *direction; const char *transfer; switch (USB_ENDPOINT_DIRECTION(descriptor)) { default: direction = "?"; break; case UsbEndpointDirection_Input: direction = "in"; break; case UsbEndpointDirection_Output: direction = "out"; break; } switch (USB_ENDPOINT_TRANSFER(descriptor)) { default: transfer = "?"; break; case UsbEndpointTransfer_Control: transfer = "ctl"; break; case UsbEndpointTransfer_Isochronous: transfer = "iso"; break; case UsbEndpointTransfer_Bulk: transfer = "blk"; break; case UsbEndpointTransfer_Interrupt: transfer = "int"; break; } logMessage(LOG_CATEGORY(USB_IO), "ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms", descriptor->bEndpointAddress, direction, transfer, getLittleEndian16(descriptor->wMaxPacketSize), descriptor->bInterval); } if ((endpoint = malloc(sizeof(*endpoint)))) { memset(endpoint, 0, sizeof(*endpoint)); endpoint->device = device; endpoint->descriptor = descriptor; endpoint->extension = NULL; endpoint->prepare = NULL; switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) { case UsbEndpointDirection_Input: endpoint->direction.input.pending.requests = NULL; endpoint->direction.input.pending.alarm = NULL; endpoint->direction.input.pending.delay = 0; endpoint->direction.input.completed.request = NULL; endpoint->direction.input.completed.buffer = NULL; endpoint->direction.input.completed.length = 0; endpoint->direction.input.pipe.input = INVALID_FILE_DESCRIPTOR; endpoint->direction.input.pipe.output = INVALID_FILE_DESCRIPTOR; endpoint->direction.input.pipe.monitor = NULL; endpoint->direction.input.pipe.error = 0; break; } if (usbAllocateEndpointExtension(endpoint)) { if (enqueueItem(device->endpoints, endpoint)) { if (device->disableEndpointReset) { logMessage(LOG_CATEGORY(USB_IO), "endpoint reset disabled"); } else { usbClearHalt(device, endpoint->descriptor->bEndpointAddress); } if (!endpoint->prepare || endpoint->prepare(endpoint)) return endpoint; deleteItem(device->endpoints, endpoint); } usbDeallocateEndpointExtension(endpoint->extension); usbDestroyInputPipe(endpoint); } free(endpoint); } } return NULL; }