public UsbCbiCommandResult ExecuteCommand(byte[] command, byte[] dataBuffer, int dataIndex, int dataLength, UsbDataDirection dataDirection) { adsc.wLength = (short)command.Length; var commandTransferResult = host.ExecuteControlTransfer(adsc, command, 0, deviceAddress); if (commandTransferResult.IsErrorButNotStall) { return(new UsbCbiCommandResult(commandTransferResult.TransactionResult, 0, null)); } UsbCbiCommandResult ResultOnError(int transferredLength) { if (command[0] == requestSenseCommand[0]) { return(new UsbCbiCommandResult(commandTransferResult.TransactionResult, transferredLength, null)); } var requestSenseResult = ExecuteRequestSense(); if (requestSenseResult.IsErrorResult) { return(new UsbCbiCommandResult(commandTransferResult.TransactionResult, transferredLength, null)); } else { return(new UsbCbiCommandResult(UsbPacketResult.Ok, transferredLength, requestSenseResult.ToByteArray())); } } if (commandTransferResult.IsError) { return(ResultOnError(0)); } var transferredDataCount = 0; if (dataLength != 0) { var dataTransferResult = dataDirection == UsbDataDirection.IN ? host.ExecuteDataInTransfer(dataBuffer, dataIndex, dataLength, deviceAddress, bulkInEndpoint.Number) : host.ExecuteDataOutTransfer(dataBuffer, dataIndex, dataLength, deviceAddress, bulkOutEndpoint.Number); transferredDataCount = dataTransferResult.TransferredDataCount; if (dataTransferResult.IsErrorButNotStall) { return(new UsbCbiCommandResult(dataTransferResult.TransactionResult, transferredDataCount, null)); } else if (dataTransferResult.IsError) { ClearEndpointHalt(dataDirection == UsbDataDirection.IN ? bulkInEndpoint.Number : bulkOutEndpoint.Number); return(ResultOnError(transferredDataCount)); } } var intTransferResult = host.ExecuteDataInTransfer(senseCodeBuffer, 0, 2, deviceAddress, interruptEndpoint.Number); if (intTransferResult.IsErrorButNotStall) { return(new UsbCbiCommandResult(intTransferResult.TransactionResult, transferredDataCount, null)); } else if (intTransferResult.IsError) { ClearEndpointHalt(interruptEndpoint.Number); return(ResultOnError(transferredDataCount)); } else if (senseCodeBuffer[0] != 0) { return(ResultOnError(transferredDataCount)); //Request Sense needed to clear the error condition } return(new UsbCbiCommandResult(commandTransferResult.TransactionResult, transferredDataCount, senseCodeBuffer.ToArray())); }
public static UsbCbiCommandResult ExecuteCommandWithRetry(this IUsbCbiTransport cbi, byte[] command, byte[] dataBuffer, int dataIndex, int dataLength, UsbDataDirection dataDirection, bool retryOnMediaChanged = true) { return(ExecuteCommandWithRetry(cbi, command, dataBuffer, dataIndex, dataLength, dataDirection, out bool dummyMediaChanged, retryOnMediaChanged)); }
private UsbTransferResult ExecuteDataTransfer(byte[] dataBuffer, int dataBufferIndex, int dataLength, int deviceAddress, int endpointNumber, UsbDataDirection dataDirection) { if (deviceAddress != UsbDeviceAddress) { throw new InvalidOperationException($"There's no device connected with address {deviceAddress}"); } if (!connectedDevice.EndpointsByNumber.ContainsKey((byte)endpointNumber)) { throw new InvalidOperationException($"The device with address {deviceAddress} doesn't have an endpoint with number 0x{endpointNumber:X} in any of the interfaces of the current configuration"); } if ((UsbDataDirection)(endpointNumber & 0x80) != dataDirection) { throw new InvalidOperationException($"Can't perform {dataDirection} transfers on endpoint 0x{endpointNumber:X}, it's not an {dataDirection} endpoint"); } var endpointType = connectedDevice.EndpointsByNumber[(byte)endpointNumber].Type; if (endpointType != UsbEndpointType.Bulk && endpointType != UsbEndpointType.Interrupt) { throw new InvalidOperationException($"Can't perform data transfers on endpoint 0x{endpointNumber:X}, it's a {endpointType} endpoint"); } if (dataDirection == UsbDataDirection.OUT && endpointType == UsbEndpointType.Interrupt) { throw new InvalidOperationException($"Can't perform OUT data transfers on endpoint 0x{endpointNumber:X}, it's an Interrupt endpoint"); } var endpoint = connectedDevice.EndpointsByNumber[(byte)endpointNumber]; var result = dataDirection == UsbDataDirection.IN ? hw.ExecuteDataInTransfer(dataBuffer, dataBufferIndex, dataLength, deviceAddress, endpointNumber, endpoint.MaxPacketSize, endpoint.ToggleBit) : hw.ExecuteDataOutTransfer(dataBuffer, dataBufferIndex, dataLength, deviceAddress, endpointNumber, endpoint.MaxPacketSize, endpoint.ToggleBit); endpoint.ToggleBit = result.NextTogleBit; return(result); }
public static UsbCbiCommandResult ExecuteCommandWithRetry(this IUsbCbiTransport cbi, byte[] command, byte[] dataBuffer, int dataIndex, int dataLength, UsbDataDirection dataDirection, out bool mediaChanged, bool retryOnMediaChanged = true) { UsbCbiCommandResult result; mediaChanged = false; while (true) { result = cbi.ExecuteCommand(command, dataBuffer, dataIndex, dataLength, dataDirection); if (!result.IsError || result.SenseData == null) { return(result); } if (result.SenseData == null) { Debug.WriteLine("!!! No sense data on int endpoint!"); } else { Debug.WriteLine($"!!! ASC: {result.SenseData[0]:X2}h, ASCQ: {result.SenseData[1]:X2}h"); } cbi.ExecuteCommand(requestSenseCommand, requestSenseBuffer, 0, 1, UsbDataDirection.IN); var asc = result.SenseData[0]; var ascq = result.SenseData[1]; //4,1 = LOGICAL DRIVE NOT READY - BECOMING READY //4,FF = LOGICAL DRIVE NOT READY - DEVICE IS BUSY //28 = NOT READY TO READY TRANSITION - MEDIA CHANGED //28..2F = UNIT ATTENTION if ((asc < 0x28 || asc > 0x2F) && !(asc == 4 && (ascq == 1 || ascq == 0xFF))) { return(result); } if (asc == 0x28) { mediaChanged = true; if (!retryOnMediaChanged) { return(result); } } } }