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; }
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); }
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; }