Example #1
0
static ssize_t
usbBulkTransfer (
  UsbEndpoint *endpoint,
  void *buffer,
  size_t length,
  int timeout
) {
  UsbDeviceExtension *devx = endpoint->device->extension;

  if (usbOpenUsbfsFile(devx)) {
    struct usbdevfs_bulktransfer arg;

    memset(&arg, 0, sizeof(arg));
    arg.ep = endpoint->descriptor->bEndpointAddress;
    arg.data = buffer;
    arg.len = length;
    arg.timeout = timeout;

    {
      int count = ioctl(devx->usbfsFile, USBDEVFS_BULK, &arg);
      if (count != -1) return count;
      if (USB_ENDPOINT_DIRECTION(endpoint->descriptor) == UsbEndpointDirection_Input)
        if (errno == ETIMEDOUT)
          errno = EAGAIN;
      if (errno != EAGAIN) logSystemError("USB bulk transfer");
    }
  }

  return -1;
}
Example #2
0
int
usbClaimInterface (
  UsbDevice *device,
  unsigned char interface
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    int disconnected = 0;

    while (1) {
      unsigned int arg = interface;

      if (ioctl(devx->usbfsFile, USBDEVFS_CLAIMINTERFACE, &arg) != -1) return 1;
      if (errno != EBUSY) break;
      if (disconnected) break;

      if (!usbDisconnectInterface(device, interface)) {
        errno = EBUSY;
        break;
      }
      disconnected = 1;
    }

    logSystemError("USB interface claim");
  }

  return 0;
}
Example #3
0
static int
usbReapUrb (
  UsbDevice *device,
  int wait
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    struct usbdevfs_urb *urb;

    if (ioctl(devx->usbfsFile,
              wait? USBDEVFS_REAPURB: USBDEVFS_REAPURBNDELAY,
              &urb) != -1) {
      if (urb) {
        UsbEndpoint *endpoint;

        if ((endpoint = usbGetEndpoint(device, urb->endpoint))) {
          UsbEndpointExtension *eptx = endpoint->extension;

          if (enqueueItem(eptx->completedRequests, urb)) return 1;
          logSystemError("USB completed request enqueue");
          free(urb);
        }
      } else {
        errno = EAGAIN;
      }
    } else {
      if (wait || (errno != EAGAIN)) logSystemError("USB URB reap");
    }
  }

  return 0;
}
Example #4
0
int
usbResetDevice (UsbDevice *device) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    if (ioctl(devx->usbfsFile, USBDEVFS_RESET, NULL) != -1) return 1;
    logSystemError("USB device reset");
  }

  return 0;
}
Example #5
0
ssize_t
usbControlTransfer (
  UsbDevice *device,
  uint8_t direction,
  uint8_t recipient,
  uint8_t type,
  uint8_t request,
  uint16_t value,
  uint16_t index,
  void *buffer,
  uint16_t length,
  int timeout
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    union {
      struct usbdevfs_ctrltransfer transfer;
      UsbSetupPacket setup;
    } arg;

    memset(&arg, 0, sizeof(arg));
    arg.setup.bRequestType = direction | recipient | type;
    arg.setup.bRequest = request;
    putLittleEndian16(&arg.setup.wValue, value);
    putLittleEndian16(&arg.setup.wIndex, index);
    putLittleEndian16(&arg.setup.wLength, length);
    arg.transfer.data = buffer;
    arg.transfer.timeout = timeout;

    usbLogSetupPacket(&arg.setup);
    if (direction == UsbControlDirection_Output) {
      if (length) logBytes(LOG_CATEGORY(USB_IO), "control output", buffer, length);
    }

    {
      int count = ioctl(devx->usbfsFile, USBDEVFS_CONTROL, &arg);

      if (count != -1) {
        if (direction == UsbControlDirection_Input) {
          logBytes(LOG_CATEGORY(USB_IO), "control input", buffer, length);
        }

        return count;
      }

      logSystemError("USB control transfer");
    }
  }

  return -1;
}
Example #6
0
int
usbClearEndpoint (UsbDevice *device, unsigned char endpointAddress) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    unsigned int arg = endpointAddress;

    if (ioctl(devx->usbfsFile, USBDEVFS_CLEAR_HALT, &arg) != -1) return 1;
    logSystemError("USB endpoint clear");
  }

  return 0;
}
Example #7
0
int
usbReleaseInterface (UsbDevice *device, unsigned char interface) {
  UsbDeviceExtension *devx = device->extension;

  logMessage(LOG_CATEGORY(USB_IO), "releasing interface: %u", interface);

  if (usbOpenUsbfsFile(devx)) {
    unsigned int arg = interface;
    if (ioctl(devx->usbfsFile, USBDEVFS_RELEASEINTERFACE, &arg) != -1) return 1;
    if (errno == ENODEV) return 1;
    logSystemError("USB interface release");
  }

  return 0;
}
Example #8
0
int
usbSetConfiguration (UsbDevice *device, unsigned char configuration) {
  UsbDeviceExtension *devx = device->extension;

  logMessage(LOG_CATEGORY(USB_IO), "setting configuration: %u", configuration);

  if (usbOpenUsbfsFile(devx)) {
    unsigned int arg = configuration;

    if (ioctl(devx->usbfsFile, USBDEVFS_SETCONFIGURATION, &arg) != -1) return 1;
    logSystemError("USB configuration set");
  }

  return 0;
}
Example #9
0
int
usbCancelRequest (
  UsbDevice *device,
  void *request
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    int reap = 1;

    if (ioctl(devx->usbfsFile, USBDEVFS_DISCARDURB, request) == -1) {
      if (errno == ENODEV)  {
        reap = 0;
      } else if (errno != EINVAL) {
        logSystemError("USB URB discard");
      }
    }
    
    {
      struct usbdevfs_urb *urb = request;
      UsbEndpoint *endpoint;

      if ((endpoint = usbGetEndpoint(device, urb->endpoint))) {
        UsbEndpointExtension *eptx = endpoint->extension;
        int found = 1;

        while (!deleteItem(eptx->completedRequests, request)) {
          if (!reap) break;

          if (!usbReapUrb(device, 0)) {
            found = 0;
            break;
          }
        }

        if (found) {
          free(request);
          return 1;
        }

        logMessage(LOG_ERR, "USB request not found: urb=%p ept=%02X",
                   urb, urb->endpoint);
      }
    }
  }

  return 0;
}
Example #10
0
int
usbSetAlternative (
  UsbDevice *device,
  unsigned char interface,
  unsigned char alternative
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    struct usbdevfs_setinterface arg;

    memset(&arg, 0, sizeof(arg));
    arg.interface = interface;
    arg.altsetting = alternative;

    if (ioctl(devx->usbfsFile, USBDEVFS_SETINTERFACE, &arg) != -1) return 1;
    logSystemError("USB alternative set");
  }

  return 0;
}
Example #11
0
static char *
usbGetDriver (UsbDevice *device, unsigned char interface) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    struct usbdevfs_getdriver arg;

    memset(&arg, 0, sizeof(arg));
    arg.interface = interface;

    if (ioctl(devx->usbfsFile, USBDEVFS_GETDRIVER, &arg) != -1) {
      char *name = strdup(arg.driver);
      if (name) return name;
      logMallocError();
    } else {
      logSystemError("USB get driver name");
    }
  }

  return NULL;
}
Example #12
0
static int
usbControlDriver (
  UsbDevice *device,
  unsigned char interface,
  int code,
  void *data
) {
  UsbDeviceExtension *devx = device->extension;

  if (usbOpenUsbfsFile(devx)) {
    struct usbdevfs_ioctl arg;

    memset(&arg, 0, sizeof(arg));
    arg.ifno = interface;
    arg.ioctl_code = code;
    arg.data = data;

    if (ioctl(devx->usbfsFile, USBDEVFS_IOCTL, &arg) != -1) return 1;
    logSystemError("USB driver control");
  }

  return 0;
}
Example #13
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;
}