//=================================================================================================== /// <summary> /// Overriden to load data into the device's FPGA /// </summary> /// <param name="buffer">The data to load</param> /// <returns>The error code</returns> //=================================================================================================== internal override ErrorCodes LoadFPGA(byte request, byte[] buffer) { m_controlTransferMutex.WaitOne(); ErrorCodes errorCode; UsbSetupPacket packet = new UsbSetupPacket(buffer.Length); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = request; packet.Value = 0; packet.Index = 0; packet.Length = (ushort)buffer.Length; Array.Copy(buffer, packet.Buffer, buffer.Length); errorCode = UsbControlOutRequest(packet); m_controlTransferMutex.ReleaseMutex(); return errorCode; }
//================================================================== /// <summary> /// Virtual method for a USB control OUT request /// </summary> /// <returns>The result</returns> //================================================================== internal override ErrorCodes UsbControlOutRequest(UsbSetupPacket packet) { System.Diagnostics.Debug.Assert(false, "UsbControlOutRequest not implemented in SynchronousUsbInterop"); return ErrorCodes.MethodRequiresImplementation; }
//================================================================== /// <summary> /// Check's the device status for a data overrun /// </summary> /// <returns>The error code</returns> //================================================================== internal override ErrorCodes CheckUnderrun() { ErrorCodes errorCode = m_errorCode; ControlTransferMutex.WaitOne(); UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = ControlRequest.MESSAGE_REQUEST; packet.Index = 0; packet.Value = 0; packet.Length = (ushort)m_aoScanStatusMessage.Length; Array.Copy(m_aoScanStatusMessage, packet.Buffer, m_aoScanStatusMessage.Length); // send the status message UsbControlOutRequest(packet); // get the status response packet.TransferType = UsbTransferTypes.ControlIn; UsbControlInRequest(packet); ControlTransferMutex.ReleaseMutex(); string response = m_ae.GetString(packet.Buffer, 0, packet.Buffer.Length); if (response.Contains(PropertyValues.UNDERRUN)) errorCode = ErrorCodes.DataUnderrun; return errorCode; }
//================================================================== /// <summary> /// Method for a USB control Out request /// </summary> /// <returns>The result</returns> //================================================================== internal override ErrorCodes UsbControlOutRequest(UsbSetupPacket packet) { int result; result = LibUsbInterop.LibUsbControlTransfer(m_devHandle, ControlRequestType.VENDOR_CONTROL_OUT, packet.Request, packet.Value, packet.Index, packet.Buffer, (ushort)packet.Buffer.Length, CTRL_TIMEOUT); if (result >= 0) { return ErrorCodes.NoErrors; } else if (result == -4) { return ErrorCodes.DeviceNotResponding; } else if (result == -9) { return ErrorCodes.InvalidMessage; } System.Diagnostics.Debug.Assert(false, String.Format("Unknown error in UsbControlOutRequest: {0}", result)); return ErrorCodes.UnknownError; }
//============================================================================================================= /// <summary> /// Virtual method for a USB control OUT request /// </summary> /// <returns>The result</returns> //============================================================================================================= internal override ErrorCodes UsbControlOutRequest(UsbSetupPacket packet) { System.Diagnostics.Debug.Assert(false, "UsbControlOutRequest must be implemented in a derived class"); return ErrorCodes.MethodRequiresImplementation; }
//=================================================================================================== /// <summary> /// Virutal method to unlock a device's memory for writing to it /// </summary> /// <param name="address">The address of the unlock code</param> /// <param name="unlockCode">The unlock code</param> /// <returns>The error code</returns> //=================================================================================================== internal override ErrorCodes UnlockDeviceMemory(ushort address, ushort unlockCode) { ErrorCodes errorCode = ErrorCodes.NoErrors; // send memory unlock code UsbSetupPacket packet = new UsbSetupPacket(64); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = MEM_ADDR; packet.Value = 0; packet.Index = 0; packet.Length = 2; packet.Buffer[0] = (byte)(0x00FF & address); packet.Buffer[1] = (byte)((0xFF00 & address) >> 8); // MemAddress command errorCode = UsbControlOutRequest(packet); if (errorCode != ErrorCodes.NoErrors) return errorCode; packet.Request = MEM_WRITE; packet.Value = 0; packet.Index = 0; packet.Length = 2; packet.Buffer[0] = (byte)(0x00FF & unlockCode); packet.Buffer[1] = (byte)((0xFF00 & unlockCode) >> 8); // MemWrite command errorCode = UsbControlOutRequest(packet); return errorCode; }
//============================================================================================================================================================================== /// <summary> /// Overriden to Write data to a device's memory /// </summary> /// <param name="memAddrCmd">The device's memory address command</param> /// <param name="memWriteCmd">The device's memory write command</param> /// <param name="memoryOffset">The memory offset to start writing to</param> /// <param name="memOffsetLength">The size of the memoryOffset value (typically 2 bytes)</param> /// <param name="bufferOffset">The buffer offset</param> /// <param name="buffer">The buffer containg the data to write to memory</param> /// <param name="count">The number of bytes to write</param> /// <returns></returns> //============================================================================================================================================================================== internal override ErrorCodes WriteDeviceMemory1(byte memAddrCmd, byte memWriteCmd, ushort memoryOffset, ushort memOffsetLength, ushort bufferOffset, byte[] buffer, byte count) { m_controlTransferMutex.WaitOne(); ErrorCodes errorCode = ErrorCodes.NoErrors; UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_COMMAND_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = memAddrCmd; packet.Value = 0; packet.Index = 0; packet.Length = 2; packet.Buffer[0] = (byte)(0x00FF & memoryOffset); packet.Buffer[1] = (byte)((0xFF00 & memoryOffset) >> 8); if (count > Constants.MAX_COMMAND_LENGTH) { m_controlTransferMutex.ReleaseMutex(); return ErrorCodes.CountGreaterThanMaxLength; } // MemAddress command errorCode = UsbControlOutRequest(packet); // Check current MemAddress packet.TransferType = UsbTransferTypes.ControlIn; errorCode = UsbControlInRequest(packet); if (errorCode == ErrorCodes.NoErrors) { packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = memWriteCmd; packet.Value = 0x0; for (int i = 0; i < count; i++) packet.Buffer[i] = buffer[i + bufferOffset]; packet.Length = count; // MemWrite command errorCode = UsbControlOutRequest(packet); } if (errorCode != ErrorCodes.NoErrors) errorCode = ErrorCodes.ErrorWritingDeviceMemory; m_controlTransferMutex.ReleaseMutex(); return errorCode; }
protected void CheckTriggerRearm() { string triggerSupport = m_daqDevice.GetDevCapsString("AISCAN:TRIG", false); if (triggerSupport.Contains(DevCapImplementations.PROG)) { string response; m_daqDevice.SendMessageDirect(Messages.AISCAN_TRIG_QUERY); response = ReadStringDirect(); UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); // if the trigger is enabled, check the AISCAN:REARM setting if (response.Contains(PropertyValues.ENABLE)) { string rearmSupport = m_daqDevice.GetDevCapsString("AITRIG:REARM", false); if (rearmSupport.Contains(DevCapImplementations.PROG)) { // check if rearm is enabled m_daqDevice.SendMessageDirect(Messages.AITRIG_REARM_QUERY); response = ReadStringDirect(); if (response.Contains(PropertyValues.ENABLE)) { // transfer size must be integer multiple of the packet size because // we're going to switch to continuous mode while (m_criticalParams.BulkInXferSize % m_criticalParams.AiChannelCount != 0) m_criticalParams.BulkInXferSize += m_deviceInfo.MaxPacketSize; // switch to continuous mode so the device can continually re-trigger m_criticalParams.InputSampleMode = SampleMode.Continuous; // get the current sample count m_daqDevice.SendMessageDirect(Messages.AISCAN_SAMPLES_QUERY); response = ReadStringDirect(); response = response.Trim(new char[] { Constants.NULL_TERMINATOR }); int samples = MessageTranslator.GetSamples(response); m_criticalParams.AdjustedRearmSamplesPerTrigger = samples; // calculate the number of bytes in each transfer int inputBytes = m_criticalParams.AiChannelCount * m_criticalParams.DataInXferSize * samples; int rearmBytes = 0; int rearmSamples = 0; if (inputBytes % m_criticalParams.BulkInXferSize != 0) { // when xfer mode is not SINGLEIO, the rearm bytes need to be an integer multiple of the xfer size // because we're using continuous mode if (m_criticalParams.InputTransferMode != TransferMode.SingleIO) rearmBytes = (int)Math.Floor((double)inputBytes / (double)m_criticalParams.BulkInXferSize) * m_criticalParams.BulkInXferSize; else rearmBytes = inputBytes; // adjust the number of samples rearmSamples = rearmBytes / (m_criticalParams.AiChannelCount * m_criticalParams.DataInXferSize); // now update the device's SAMPLE property string msg = Messages.AISCAN_SAMPLES; msg = Messages.InsertValue(msg, rearmSamples); m_criticalParams.AdjustedRearmSamplesPerTrigger = rearmSamples; } // Delta rearm samples will non-zero when xfer mode is not SINGLEIO if (m_criticalParams.InputTransferMode != TransferMode.SingleIO) m_criticalParams.DeltaRearmInputSamples = rearmSamples - samples; else m_criticalParams.DeltaRearmInputSamples = 0; m_totalSamplesToReadPerChannel = INTERNAL_READ_BUFFER_SIZE / 2; m_totalSamplesToReadPerChannel = (int)Math.Ceiling((double)m_totalSamplesToReadPerChannel / (double)m_criticalParams.AiChannelCount) * m_criticalParams.AiChannelCount; m_criticalParams.InputScanSamples = m_totalSamplesToReadPerChannel; if (m_onDataAvailableCallbackControl != null && m_onDataAvailableCallbackControl.NumberOfSamples > m_criticalParams.AdjustedRearmSamplesPerTrigger) m_onDataAvailableCallbackControl.NumberOfSamples = m_criticalParams.AdjustedRearmSamplesPerTrigger; } else { m_criticalParams.DeltaRearmInputSamples = 0; } } } } }
//================================================================= /// <summary> /// Gets the state of an Output scan operation /// </summary> /// <returns>The scan state</returns> //================================================================= protected ScanState GetOutputScanState() { m_platformInterop.ControlTransferMutex.WaitOne(); UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = ControlRequest.MESSAGE_REQUEST; packet.Index = 0; packet.Value = 0; packet.Length = (ushort)m_aoStatusMessage.Length; Array.Copy(m_aoStatusMessage, packet.Buffer, m_aoStatusMessage.Length); // send the status message m_platformInterop.UsbControlOutRequest(packet); // get the status response packet.TransferType = UsbTransferTypes.ControlIn; m_platformInterop.UsbControlInRequest(packet); string response = m_ae.GetString(packet.Buffer, 0, packet.Buffer.Length); m_platformInterop.ControlTransferMutex.ReleaseMutex(); if (response.Contains("RUNNING")) { m_outputScanState = ScanState.Running; } else if (response.Contains("UNDERRUN")) { if (!m_stopOutputScan) { m_errorCode = ErrorCodes.DataUnderrun; m_outputScanState = ScanState.Underrun; } else { // Let ProcessOutputScanThread clear the data underrun when it exits. //m_platformInterop.ClearDataUnderrun(); m_outputScanState = ScanState.Idle; } } else { m_outputScanState = ScanState.Idle; } return m_outputScanState; }
internal DriverInterface(DaqDevice daqDevice, DeviceInfo deviceInfo, Object deviceLock) { m_deviceInfo = deviceInfo; m_daqDevice = daqDevice; m_deviceLock = deviceLock; m_platformInterop = PlatformInterop.GetUsbPlatformInterop(deviceInfo, m_criticalParams); // the error code may be set if the device did not initialzie m_errorCode = m_platformInterop.ErrorCode; m_usbPackets = new List<UsbSetupPacket>(); m_usbPacketsDirect = new List<UsbSetupPacket>(); m_ae = new ASCIIEncoding(); string message; // convert following messages to an array of bytes for direct use by this driver interface message = "?AISCAN:STATUS"; Array.Clear(m_aiStatusMessage, 0, m_aiStatusMessage.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiStatusMessage, 0); message = "?AISCAN:TRIG"; Array.Clear(m_aiTrigStatus, 0, m_aiTrigStatus.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiTrigStatus, 0); message = "?AITRIG:REARM"; Array.Clear(m_aiRearmStatus, 0, m_aiRearmStatus.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiRearmStatus, 0); message = "?AISCAN:SAMPLES"; Array.Clear(m_aiQuerySamples, 0, m_aiQuerySamples.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiQuerySamples, 0); message = "AISCAN:SAMPLES="; Array.Clear(m_aiScanSamples, 0, m_aiScanSamples.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiScanSamples, 0); message = "?AOSCAN:STATUS"; Array.Clear(m_aoStatusMessage, 0, m_aoStatusMessage.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aoStatusMessage, 0); message = "AISCAN:STOP"; Array.Clear(m_aiScanStopMessage, 0, m_aiScanStopMessage.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aiScanStopMessage, 0); message = "AOSCAN:STOP"; Array.Clear(m_aoScanStopMessage, 0, m_aoScanStopMessage.Length); m_ae.GetBytes(message.ToCharArray(), 0, message.Length, m_aoScanStopMessage, 0); m_deferredResponsePacket = new UsbSetupPacket(Constants.MAX_COMMAND_LENGTH); m_deferredResponsePacket.TransferType = UsbTransferTypes.ControlIn; m_deferredResponsePacket.Request = ControlRequest.MESSAGE_REQUEST; m_deferredResponsePacket.DeferTransfer = false; m_deferredResponsePacket.Index = 0; m_deferredResponsePacket.Value = 0; m_deferredResponsePacket.Length = Constants.MAX_COMMAND_LENGTH; m_inputBufferSizeOverride = false; m_controlInPacket = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); m_controlInPacket.TransferType = UsbTransferTypes.ControlIn; m_controlInPacket.Request = ControlRequest.MESSAGE_REQUEST; m_controlOutPacket = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); m_controlOutPacket.TransferType = UsbTransferTypes.ControlOut; m_controlOutPacket.Request = ControlRequest.MESSAGE_REQUEST; m_controlInPacketDirect = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); m_controlInPacketDirect.TransferType = UsbTransferTypes.ControlIn; m_controlInPacketDirect.Request = ControlRequest.MESSAGE_REQUEST; m_controlOutPacketDirect = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); m_controlOutPacketDirect.TransferType = UsbTransferTypes.ControlOut; m_controlOutPacketDirect.Request = ControlRequest.MESSAGE_REQUEST; m_criticalParams.ScanType = ScanType.AnalogInput; m_currentOutputScanWriteIndex = 0; m_outputTransferStartIndex = 0; unsafe { m_externalReadBuffer = null; } m_inputBlockSize = PropertyValues.DEFAULT; // by default, don't let old data that hasn't been read yet get overwritten m_criticalParams.InputScanOverwrite = false; m_internalReadBuffer = new byte[INTERNAL_READ_BUFFER_SIZE]; m_internalWriteBuffer = new byte[INTERNAL_WRITE_BUFFER_SIZE]; m_stopOutputScanDelegate = new StopOutputScanDelegate(StopOutputScan); m_stopOutputScanCallback = new AsyncCallback(StopOutputScanCallback); }
//===================================================================== /// <summary> /// Checks to see if the trigger level needs to be resent /// in case other messages sent after the AITRIG:LEVEL message /// effects its scaling /// </summary> //===================================================================== protected void CheckForTriggerLevelResend() { if (m_daqDevice.CriticalParams.InputTriggerEnabled && m_daqDevice.CriticalParams.ResendInputTriggerLevelMessage && m_daqDevice.CriticalParams.InputTriggerSource.Contains("SWSTART")) { // release the control transfer mutex so the trigger message can be sent m_platformInterop.ControlTransferMutex.WaitOne(); UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.Request = ControlRequest.MESSAGE_REQUEST; packet.TransferType = UsbTransferTypes.ControlOut; packet.Index = 0; packet.Length = (ushort)packet.Buffer.Length; packet.Value = 0; string msg = Messages.AITRIG_LEVEL; msg = Messages.InsertValue(msg, m_criticalParams.InputTriggerLevel); for (int i = 0; i < msg.Length; i++) packet.Buffer[i] = (byte)msg[i]; m_errorCode = m_platformInterop.UsbControlOutRequest(packet); // reaquire the control transfer mutex m_platformInterop.ControlTransferMutex.ReleaseMutex(); } }
//====================================================================================== /// <summary> /// Transfers the incoming message to the device using one of the platform interop objects /// Each message results in a Send/Receive transfer. The Send is to send the message to /// the device through a Control Out transfer and the Receive is to receive a response /// through a Control In transfer /// </summary> /// <param name="incomingMessage">The incoming message string</param> /// <returns>The error code</returns> //====================================================================================== internal ErrorCodes TransferMessage(byte[] incomingMessage) { if (m_deviceLost) m_deviceLost = !m_platformInterop.AcquireDevice(); ErrorCodes errorCode = ErrorCodes.NoErrors; UsbSetupPacket packet; if (!m_platformInterop.DeviceInitialized) { errorCode = ErrorCodes.DeviceNotInitialized; } else { // Acquire the mutex so that a Control Out m_platformInterop.ControlTransferMutex.WaitOne(); // create packets for the incoming message // each message will get a packet for a Control Out transfer and a Control In transfer CreateUsbPackets(incomingMessage); if (errorCode == ErrorCodes.NoErrors) { //////////////////////////////////////////// // Control Out request //////////////////////////////////////////// packet = m_usbPackets[0]; if (m_usbPackets.Count == 1 && packet.TransferType == UsbTransferTypes.ControlOut) { m_internalReadString = String.Empty; m_internalReadValue = double.NaN; } // Convert any decimal separators back to en-US for (int i = 0; i < packet.Buffer.Length; i++) { if (packet.Buffer[i] == (byte)PlatformInterop.LocalNumberDecimalSeparator) packet.Buffer[i] = (byte)Constants.DECIMAL.ToCharArray()[0]; } // define a packet for deferred messages UsbSetupPacket deferredPacket = null; // send the Control Out request to the device if (!packet.DeferTransfer) { errorCode = m_platformInterop.UsbControlOutRequest(packet); } else { // queue the message packet. It will be sent at the beginning of a scan thread // first make a copy so it doesn't get overwritten since its an instance member of this class deferredPacket = new UsbSetupPacket(packet.Buffer.Length); deferredPacket.DeferTransfer = packet.DeferTransfer; deferredPacket.TransferType = packet.TransferType; deferredPacket.Request = packet.Request; deferredPacket.Value = packet.Value; deferredPacket.Index = packet.Index; deferredPacket.Length = packet.Length; Array.Copy(packet.Buffer, deferredPacket.Buffer, packet.Buffer.Length); } //////////////////////////////////////////// // Control In request //////////////////////////////////////////// if (m_usbPackets.Count > 1) { packet = m_usbPackets[1]; errorCode = m_platformInterop.UsbControlInRequest(packet); if (packet.Request == ControlRequest.MESSAGE_REQUEST) { if (errorCode == ErrorCodes.NoErrors) { m_internalReadString = m_ae.GetString(packet.Buffer, 0, packet.Buffer.Length); if (m_internalReadString.IndexOf(Constants.NULL_TERMINATOR) >= 0) { int indexOfNt = m_internalReadString.IndexOf(Constants.NULL_TERMINATOR); m_internalReadString = m_internalReadString.Remove(indexOfNt, m_internalReadString.Length - indexOfNt); } if (m_internalReadString == PropertyValues.INVALID) { errorCode = ErrorCodes.InvalidMessage; } else { m_internalReadValue = TryConvertData(ref m_internalReadString); } } else { m_internalReadString = String.Empty; m_internalReadValue = double.NaN; } } } if (m_startInputScan) { if (errorCode == ErrorCodes.NoErrors) { if (deferredPacket != null) m_deferredInputMessages.Enqueue(deferredPacket); ScanState scanState = GetInputScanState(); if (scanState == ScanState.Running) { errorCode = ErrorCodes.InputScanAlreadyInProgress; } else if (m_deviceInfo.EndPointIn == 0) { errorCode = ErrorCodes.InvalidMessage; } else { // m_startInputScan is set to true in CheckForCriticalParams m_deferredInputResponses.Clear(); CheckTriggerRearm(); if (m_criticalParams.InputSampleMode == SampleMode.Continuous) { if (m_onDataAvailableCallbackControl != null) { if (m_criticalParams.AiChannelCount * m_criticalParams.DataInXferSize * m_onDataAvailableCallbackControl.NumberOfSamples > m_internalReadBuffer.Length / 2) { errorCode = ErrorCodes.CallbackCountTooLarge; } } } // release the control transfer mutex so that the deferred messages can be sent m_platformInterop.ControlTransferMutex.ReleaseMutex(); if (errorCode == ErrorCodes.NoErrors) errorCode = StartInputScan(); // reaquire the control transfer mutex m_platformInterop.ControlTransferMutex.WaitOne(); if (errorCode == ErrorCodes.NoErrors) { if (m_inputScanErrorCode != ErrorCodes.NoErrors) { errorCode = m_inputScanErrorCode; } else if (packet.DeferTransfer) { m_internalReadString = m_deferredInputResponses[0].Trim(new char[] { Constants.NULL_TERMINATOR }); } } else { // if an error occurred dont't send the deferred message m_deferredInputMessages.Clear(); } } } } else if (m_startOutputScan) { if (errorCode == ErrorCodes.NoErrors) { if (deferredPacket != null) m_deferredOutputMessages.Enqueue(deferredPacket); ScanState scanState = GetOutputScanState(); if (scanState == ScanState.Running) { errorCode = ErrorCodes.OutputScanAlreadyInProgress; } else if (m_deviceInfo.EndPointIn == 0) { errorCode = ErrorCodes.InvalidMessage; } else { // m_startInputScan is set to true in CheckForCriticalParams m_deferredOutputResponses.Clear(); // release the control transfer mutex so that the deferred messages can be sent m_platformInterop.ControlTransferMutex.ReleaseMutex(); if (errorCode == ErrorCodes.NoErrors) errorCode = StartOutputScan(); // reaquire the control transfer mutex m_platformInterop.ControlTransferMutex.WaitOne(); if (errorCode == ErrorCodes.NoErrors) { if (m_outputScanErrorCode != ErrorCodes.NoErrors) { errorCode = m_outputScanErrorCode; } else if (packet.DeferTransfer) { if (m_deferredOutputResponses.Count > 0) m_internalReadString = m_deferredOutputResponses[0].Trim(new char[] { Constants.NULL_TERMINATOR }); else System.Diagnostics.Debug.Assert(false, "Deferred response list is empty"); } } else { // if an error occurred don't send the deferred message m_deferredOutputMessages.Clear(); } } } } else if (m_initiateStopForInput && m_deviceInfo.EndPointIn != 0) { // release the control transfer mutex so that the Input scan thread can exit m_platformInterop.ControlTransferMutex.ReleaseMutex(); // m_initiateStopForInput is set to true in CheckForCriticalParams if (deferredPacket != null) { // executes on Linux - this must be called first before sending // the deferred STOP command StopInputScan(false); errorCode = m_platformInterop.UsbControlOutRequest(deferredPacket); if (m_deferredOutputResponses.Count > 0) m_internalReadString = m_deferredOutputResponses[0].Trim(new char[] { Constants.NULL_TERMINATOR }); else System.Diagnostics.Debug.Assert(false, "Deferred response list is empty"); m_platformInterop.FlushInputDataFromDevice(); m_initiateStopForInput = false; } else { // executes on Windows StopInputScan(true); } // reaquire the control transfer mutex m_platformInterop.ControlTransferMutex.WaitOne(); } else if (m_initiateStopForOutput && m_deviceInfo.EndPointOut != 0) { // release the control transfer mutex so that the Input scan thread can exit m_platformInterop.ControlTransferMutex.ReleaseMutex(); // m_initiateStopForInput is set to true in CheckForCriticalParams if (deferredPacket != null) { // executes on Linux - this must be called first before sending // the deferred STOP command StopOutputScan(false); errorCode = m_platformInterop.UsbControlOutRequest(deferredPacket); if (m_deferredOutputResponses.Count > 0) m_internalReadString = m_deferredOutputResponses[0].Trim(new char[] { Constants.NULL_TERMINATOR }); else System.Diagnostics.Debug.Assert(false, "Deferred response list is empty"); m_initiateStopForOutput = false; } else { // executes on Windows StopOutputScan(true); } // reaquire the control transfer mutex m_platformInterop.ControlTransferMutex.WaitOne(); } } m_platformInterop.ControlTransferMutex.ReleaseMutex(); } if (errorCode == ErrorCodes.DeviceNotResponding) { ReleaseDevice(); m_deviceLost = true; return errorCode; } // check if the device refused the message because a scan is running... if (errorCode == ErrorCodes.InvalidMessage) { ErrorCodes status = m_daqDevice.CheckUsage(); if (status != ErrorCodes.NoErrors) { errorCode = status; } } return errorCode; }
//============================================================================= /// <summary> /// Stops an input scan directly using a control transfer /// </summary> //============================================================================= internal void StopInputScanDirect() { UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = ControlRequest.MESSAGE_REQUEST; packet.Index = 0; packet.Value = 0; packet.Length = (ushort)m_aiScanStopMessage.Length; Array.Copy(m_aiScanStopMessage, packet.Buffer, m_aiScanStopMessage.Length); // send the status message m_platformInterop.ControlTransferMutex.WaitOne(); m_platformInterop.UsbControlOutRequest(packet); m_platformInterop.ControlTransferMutex.ReleaseMutex(); m_platformInterop.StopInputTransfers(); m_stopInputScan = true; }
//================================================================== /// <summary> /// Clears the pipe's stall state /// </summary> //================================================================== protected void ClearStall(byte pipe, UsbSetupPacket resetPacket) { m_controlTransferMutex.WaitOne(); UsbControlOutRequest(resetPacket); m_controlTransferMutex.ReleaseMutex(); LibUsbClearHalt(m_devHandle, pipe); }
//============================================================================================================================================================ /// <summary> /// Reads a device's memory /// </summary> /// <param name="offset">The starting addresss</param> /// <param name="count">The number of bytes to read</param> /// <param name="buffer">The buffer containing the memory contents</param> /// <returns>The error code</returns> //============================================================================================================================================================ internal override ErrorCodes ReadDeviceMemory1(byte memAddrCmd, byte memReadCmd, ushort memoryOffset, ushort memoryOffsetLength, byte count, out byte[] buffer) { ErrorCodes errorCode = ErrorCodes.NoErrors; if (count > Constants.MAX_COMMAND_LENGTH) errorCode = ErrorCodes.CountGreaterThanMaxLength; UsbSetupPacket packet; buffer = null; if (errorCode == ErrorCodes.NoErrors) { // create a packet to send the memory address command packet = new UsbSetupPacket(memoryOffsetLength); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = memAddrCmd; packet.Value = 0; packet.Index = 0; packet.Length = 2; // store the memory offset in the first two bytes of the buffer packet.Buffer[0] = (byte)(0x00FF & memoryOffset); packet.Buffer[1] = (byte)((0xFF00 & memoryOffset) >> 8); buffer = null; // send the mem address command errorCode = UsbControlOutRequest(packet); if (errorCode == ErrorCodes.NoErrors) { // create a new packet for reading a block of device memory packet = new UsbSetupPacket(count); packet.TransferType = UsbTransferTypes.ControlIn; packet.Request = memReadCmd; packet.Length = count; // read a block of memory (up to max packet size) errorCode = UsbControlInRequest(packet); buffer = packet.Buffer; } if (errorCode != ErrorCodes.NoErrors) errorCode = ErrorCodes.ErrorReadingDeviceMemory; } return errorCode; }
//=================================================================================================== /// <summary> /// Get the device ID that a user set to store in the device info object /// </summary> /// <returns>The device ID</returns> //=================================================================================================== internal override string GetDeviceID(DeviceInfo deviceInfo) { m_controlTransferMutex.WaitOne(); string deviceID = String.Empty; InitializeDevice(deviceInfo); if (m_deviceInitialized) { UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = 0x80; packet.DeferTransfer = false; packet.BytesTransfered = 0; for (int i = 0; i < m_devIdMessage.Length; i++) packet.Buffer[i] = m_devIdMessage[i]; UsbControlOutRequest(packet); packet.TransferType = UsbTransferTypes.ControlIn; UsbControlInRequest(packet); m_deviceHandle.Close(); string response = m_ae.GetString(packet.Buffer).Trim(new char[] { Constants.NULL_TERMINATOR }); int index = response.IndexOf('='); if (index >= 0) deviceID = response.Substring(index + 1); m_controlTransferMutex.ReleaseMutex(); } ReleaseDevice(); return deviceID; }
//============================================================================================================================================================ /// <summary> /// Reads a device's memory /// </summary> /// <param name="offset">The starting addresss</param> /// <param name="count">The number of bytes to read</param> /// <param name="buffer">The buffer containing the memory contents</param> /// <returns>The error code</returns> //============================================================================================================================================================ internal override ErrorCodes ReadDeviceMemory4(byte memReadCmd, ushort memoryOffset, ushort memoryOffsetLength, byte count, out byte[] buffer) { ErrorCodes errorCode = ErrorCodes.NoErrors; if (count > Constants.MAX_COMMAND_LENGTH) errorCode = ErrorCodes.CountGreaterThanMaxLength; UsbSetupPacket packet; buffer = null; if (errorCode == ErrorCodes.NoErrors) { if (errorCode == ErrorCodes.NoErrors) { // create a new packet for reading a block of device memory packet = new UsbSetupPacket(count); packet.TransferType = UsbTransferTypes.ControlIn; packet.Request = memReadCmd; packet.Value = memoryOffset; packet.Index = 0; packet.Length = count; // read a block of memory (up to max packet size) errorCode = UsbControlInRequest(packet); buffer = packet.Buffer; } if (errorCode != ErrorCodes.NoErrors) errorCode = ErrorCodes.ErrorReadingDeviceMemory; } return errorCode; }
//================================================================== /// <summary> /// Method for a USB control OUT request /// </summary> /// <returns>The result</returns> //================================================================== internal override ErrorCodes UsbControlOutRequest(UsbSetupPacket packet) { bool result; WindowsUsbSetupPacket winUsbPacket = new WindowsUsbSetupPacket(); winUsbPacket.RequestType = ControlRequestType.VENDOR_CONTROL_OUT; winUsbPacket.Request = packet.Request; winUsbPacket.Value = packet.Value; winUsbPacket.Index = packet.Index; winUsbPacket.Length = packet.Length; uint bytesTransfered = 0; //System.Diagnostics.Debug.WriteLine(String.Format("Starting Control Out transfer on thread {0}", Thread.CurrentThread.ManagedThreadId)); try { result = McUsb_ControlTransfer(m_deviceHandle, winUsbPacket, packet.Buffer, (ushort)winUsbPacket.Length, ref bytesTransfered, IntPtr.Zero); //System.Diagnostics.Debug.WriteLine(String.Format("Completed Control Out transfer on thread {0}", Thread.CurrentThread.ManagedThreadId)); } catch (Exception) { return ErrorCodes.UsbIOError; } packet.BytesTransfered = bytesTransfered; if (result == true) { return ErrorCodes.NoErrors; } else { int lastError = GetLastError(); if (lastError == 22 || lastError == 1176) return ErrorCodes.DeviceNotResponding; else if (lastError == 2 || lastError == 31) return ErrorCodes.InvalidMessage; else if (lastError == 6) return ErrorCodes.InvalidDeviceHandle; System.Diagnostics.Debug.Assert(false, String.Format("Unknown Error Code: {0}", lastError)); return ErrorCodes.UnknownError; } }
//================================================================== /// <summary> /// Virtual method for a USB control OUT request /// </summary> /// <returns>The result</returns> //================================================================== internal abstract ErrorCodes UsbControlOutRequest(UsbSetupPacket packet);
//================================================================== /// <summary> /// Clears the pipe's stall state /// </summary> //================================================================== protected void ClearStall(byte pipe, UsbSetupPacket resetCommandPacket) { m_controlTransferMutex.WaitOne(); UsbControlOutRequest(resetCommandPacket); m_controlTransferMutex.ReleaseMutex(); McUsb_ResetPipe(m_deviceHandle, pipe); }
//============================================================================================================================================================================== /// <summary> /// Virtual method to Write data to a device's memory /// </summary> /// <param name="unlockKey">The unlock key</param> /// <param name="memCmd">The device's memory read/write command</param> /// <param name="memoryOffset">The memory offset to start writing to</param> /// <param name="memOffsetLength">The size of the memoryOffset value (typically 2 bytes)</param> /// <param name="bufferOffset">The buffer offset</param> /// <param name="buffer">The buffer containg the data to write to memory</param> /// <param name="count">The number of bytes to write</param> /// <returns></returns> //============================================================================================================================================================================== internal override ErrorCodes WriteDeviceMemory3(ushort unlockKey, byte memCmd, ushort memoryOffset, ushort memOffsetLength, ushort bufferOffset, byte[] buffer, byte count) { m_controlTransferMutex.WaitOne(); ErrorCodes errorCode = ErrorCodes.NoErrors; if (count > Constants.MAX_COMMAND_LENGTH) errorCode = ErrorCodes.CountGreaterThanMaxLength; if (errorCode == ErrorCodes.NoErrors) { UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_COMMAND_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = memCmd; packet.Value = unlockKey; packet.Index = memoryOffset; packet.Length = count; for (int i = 0; i < count; i++) packet.Buffer[i] = buffer[i + bufferOffset]; // MemWrite command errorCode = UsbControlOutRequest(packet); } if (errorCode != ErrorCodes.NoErrors) errorCode = ErrorCodes.ErrorWritingDeviceMemory; m_controlTransferMutex.ReleaseMutex(); return errorCode; }
//=================================================================================================== /// <summary> /// Get the device ID that a user set to store in the device info object /// </summary> /// <returns>The device ID</returns> //=================================================================================================== internal override string GetDeviceID(DeviceInfo deviceInfo) { m_controlTransferMutex.WaitOne(); string deviceID = String.Empty; InitializeDevice(deviceInfo); // get the device ID UsbSetupPacket packet = new UsbSetupPacket(Constants.MAX_MESSAGE_LENGTH); packet.TransferType = UsbTransferTypes.ControlOut; packet.Request = 0x80; packet.DeferTransfer = false; packet.BytesTransfered = 0; for (int i = 0; i < m_devIdMessage.Length; i++) packet.Buffer[i] = m_devIdMessage[i]; UsbControlOutRequest(packet); packet.TransferType = UsbTransferTypes.ControlIn; UsbControlInRequest(packet); string response; int index; response = m_ae.GetString(packet.Buffer, 0, packet.Buffer.Length).Trim(new char[] { Constants.NULL_TERMINATOR }); index = response.IndexOf('='); if (index >= 0) deviceID = response.Substring(index + 1); // replace the serial number that came from the device descriptor with // the mfg serial number for (int i = 0; i < m_sernoMessage.Length; i++) packet.Buffer[i] = m_sernoMessage[i]; UsbControlOutRequest(packet); packet.TransferType = UsbTransferTypes.ControlIn; UsbControlInRequest(packet); response = m_ae.GetString(packet.Buffer, 0, packet.Buffer.Length).Trim(new char[] { Constants.NULL_TERMINATOR }); index = response.IndexOf('='); if (index >= 0) deviceInfo.SerialNumber = response.Substring(index + 1); LibUsbInterop.LibUsbReleaseInterface(deviceInfo.DeviceHandle, 0); LibUsbInterop.LibUsbClose(deviceInfo.DeviceHandle); deviceInfo.DeviceHandle = IntPtr.Zero; m_controlTransferMutex.ReleaseMutex(); return deviceID; }