Exemplo n.º 1
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;
}
Exemplo n.º 2
0
void
usbMakeSetupPacket (
  UsbSetupPacket *setup,
  uint8_t direction,
  uint8_t recipient,
  uint8_t type,
  uint8_t request,
  uint16_t value,
  uint16_t index,
  uint16_t length
) {
  setup->bRequestType = direction | recipient | type;
  setup->bRequest = request;
  putLittleEndian16(&setup->wValue, value);
  putLittleEndian16(&setup->wIndex, index);
  putLittleEndian16(&setup->wLength, length);
  usbLogSetupPacket(setup);
}
Exemplo n.º 3
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;
  UsbSetupPacket setup;

  setup.bRequestType = direction | recipient | type;
  setup.bRequest = request;
  putLittleEndian16(&setup.wValue, value);
  putLittleEndian16(&setup.wIndex, index);
  putLittleEndian16(&setup.wLength, length);

  switch (direction) {
    case UsbControlDirection_Input: {
      size_t size = sizeof(setup);
      ssize_t count;

      if ((count = write(devx->data, &setup, size)) == -1) {
        logSystemError("USB control request");
      } else if (count != size) {
        logMessage(LOG_ERR, "USB truncated control request: %d < %d", count, size);
        errno = EIO;
      } else if ((count = read(devx->data, buffer, length)) == -1) {
        logSystemError("USB control read");
      } else {
        return count;
      }
      break;
    }

    case UsbControlDirection_Output: {
      unsigned char packet[sizeof(setup) + length];
      size_t size = 0;
      ssize_t count;

      memcpy(&packet[size], &setup, sizeof(setup));
      size += sizeof(setup);

      memcpy(&packet[size], buffer, length);
      size += length;

      if ((count = write(devx->data, packet, size)) == -1) {
        logSystemError("USB control write");
      } else if (count != size) {
        logMessage(LOG_ERR, "USB truncated control write: %d < %d", count, size);
        errno = EIO;
      } else {
        return size;
      }
      break;
    }

    default:
      logMessage(LOG_ERR, "USB unsupported control direction: %02X", direction);
      errno = ENOSYS;
      break;
  }

  return -1;
}