Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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;
}