- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear all,
My company has purchased a few PassMark USB 3.0 Loopback plugs.
The company has an API for C++ for using this plug, but since we mostly develop in C# I asked them if they supplied their API for .NET which they don't.
However their hardware uses Cypress hardware (they link to Cypress EZ-USB FX3 SDK) so I thought of using the Cypress SDK in conjunction with SuiteUSB 3.4.
So far I've managed to establish a connection and send data back and forth, using SuiteUSB 3.4, over USB and this works fine.
However, there are a few vendor specific (PassMark) commands that I would like to send to the plug.
I've looked into how this is done in PassMarks C++ console implementation and it works fine.
My idea is to mimic this behaviour using SuiteUSB3.4.
For instance they perform
double Voltage = 0;
SendVendorCommand(CurUSBDevice, VENDOR_REQ_READ, GET_VOLTAGE, (UCHAR*)&Voltage, sizeof(Voltage));
bool SendVendorCommand(CCyUSBDevice *USBDevice, USB30_VENDOR RequestType, WORD wValue, UCHAR *buf, LONG buflen)
{
CCyControlEndPoint *ept;
if (USBDevice->IsOpen() == false)
return false;
ept = USBDevice->ControlEndPt;
ept->Target = TGT_DEVICE;
ept->ReqType = REQ_VENDOR;
ept->ReqCode = 0x00;
ept->Value = wValue;
ept->Index = 0;
if (RequestType == VENDOR_REQ_READ)
ept->Read(buf, buflen);
else
ept->Write(buf, buflen);
return true;
}
which is fairly straight forward for reading the voltage for the device.
I want to perform the same in C#
ReadVendorCommand(device, GET_VOLTAGE, sizeof(double));
private byte[] ReadVendorCommand(CyUSBDevice device, ushort wValue, int lengthToRead)
{
var controlEndPoint = device.ControlEndPt;
controlEndPoint.Target = TGT_DEVICE;
controlEndPoint.ReqType = REQ_VENDOR;
controlEndPoint.ReqCode = 0x00;
controlEndPoint.Value = wValue;
controlEndPoint.Index = 0;
controlEndPoint.Direction = 1;
byte[] data = new byte[lengthToRead];
var result = controlEndPoint.Read(ref data, ref lengthToRead);
if (result) return data;
return null;
}
However, the data returned is all zeros (8 of them to be exact) and the lengthToRead (which was 8 when calling controlEndPoint.Read) is now only two bytes.
I've checked and the data and all patterns up to the call seem exactly the same as in the C++ code.
Since SuiteUSB 3.4 has not been updated for some quite some time (9 years) I was wondering if anyone else has any leads or tip that could point me in the right direction to resolve the issue.
Thanks a lot in advance,
Magnus Sydoff
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Looks like there is a problem setting the configuration or in passing the arguments.
Please use the code below without changing inside your function:
var controlEndPoint = device.ControlEndPt;
CyControlEndPoint ctrlEpt = controlEndPoint as CyControlEndPoint;
if (ctrlEpt is null) throw new Exception("Endpoint is not available");
else
{
ctrlEpt .Direction = CyConst.DIR_FROM_DEVICE;
ctrlEpt .Target = CyConst.TGT_DEVICE;
ctrlEpt .ReqType = CyConst.REQ_VENDOR;
ctrlEpt .ReqCode = 0x00;
ctrlEpt .Value = 0x0007;
ctrlEpt .Index = 0;
ctrlEpt .TimeOut = 3000;
int len = 8;
byte[] data = new byte[len];
bool result = controlEndPoint.XferData(ref data, ref len );
if (result)
return data;
return null;
}
Please let me know if this works, and the value returned by the XferData function.
Thanks,
Yatheesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please try the below in your function:
CyControlEndPoint controlEndPoint = device.ControlEndPt;
If (controlEndPoint != null)
{
controlEndPoint.Target = CyConst.TGT_DEVICE;
controlEndPoint.ReqType = CyConst.REQ_VENDOR;
controlEndPoint.ReqCode = 0x00;
controlEndPoint.Value = wValue;
controlEndPoint.Index = 0;
controlEndPoint.Direction = CyConst.DIR_FROM_DEVICE;
byte[] data = new byte[lengthToRead];
bool result = controlEndPoint.XferData(ref data, ref lengthToRead);
if (result) return data;
return null;
}
else
return null;
Best Regards,
Yatheesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thanks for you reply!
(I realize that I by mistake posted the line controlEndPoint.Direction = 1)
If I look in the CyEndPoints.cs file (which implements the read function) it is already defined as so.
public bool Read(ref byte[] buf, ref int len)
{
Direction = CyConst.DIR_FROM_DEVICE;
return XferData(ref buf, ref len);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
..but I tried your suggestion.
private byte[] ReadVendorCommand(CyUSBDevice device, ushort wValue, int lengthToRead)
{
var controlEndPoint = device.ControlEndPt;
if (controlEndPoint is null) throw new Exception("Endpoint is not available");
controlEndPoint.Target = TGT_DEVICE;
controlEndPoint.ReqType = REQ_VENDOR;
controlEndPoint.ReqCode = 0x00;
controlEndPoint.Value = wValue;
controlEndPoint.Index = 0;
controlEndPoint.Direction = CyConst.DIR_FROM_DEVICE;
byte[] data = new byte[lengthToRead];
var result = controlEndPoint.XferData(ref data, ref lengthToRead);
if (result) return data;
return null;
}
Unfortunately it is the same result. The data array still contains zeros and lengthToRead is now set to 2 as opposed to previous 8.
Again, thank you for your reply !
King regards
Magnus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello again,
One thing that I notice, that makes me curious, is that in file CyEndPoints.cs, which implements your suggested function XferData, is that in the section
fixed (int* lenTemp = &len)
{
bResult = BeginDataXfer(ref tmpBuf, ref *lenTemp, ref ovLap);
wResult = WaitForIO(ovLapStatus->hEvent);
fResult = FinishDataXfer(ref buf, ref tmpBuf, ref *lenTemp, ref ovLap);
}
bResult is always false when I run it whereas wResult and fResult are true.
Debugging this I can see that the call to PInvoke.DeviceIoControl fails, but it is not entirely clear to me why this happens or if it is a problem since calling function does not take notice of the returned false.
King regards
Magnus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Magnus,
Is the vendor command handled in the firmware properly?
To verify this please use the control center and do a control IN transfer with the required data filled in the fields. Please let me know if the transfer is successful in the control center.
Also, UsbdStatus member contains the error code returned from the last XferData or BeginDataXfer call.
Please let me know what is returned by the usbdStatus. you can refer to the CyUSB.NET.pdf document from the FX3 SDK for the API details.
Thanks,
Yatheesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Yatheesh,
Thank you again for your prompt reply !
This is the reply from the USB Control center.
When I run the code in the C++ project that is working this is what is being sent......
... and this is the reply I get when asking for the current USB voltage.
When calling BeginDataXfer the
_lastError = (uint)Marshal.GetLastWin32Error();
is 997
Again, thank you for helping out !
King regards
Magnus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
....and in hex for your convenience...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
From CyEndPoint.cs when running
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Looks like there is a problem setting the configuration or in passing the arguments.
Please use the code below without changing inside your function:
var controlEndPoint = device.ControlEndPt;
CyControlEndPoint ctrlEpt = controlEndPoint as CyControlEndPoint;
if (ctrlEpt is null) throw new Exception("Endpoint is not available");
else
{
ctrlEpt .Direction = CyConst.DIR_FROM_DEVICE;
ctrlEpt .Target = CyConst.TGT_DEVICE;
ctrlEpt .ReqType = CyConst.REQ_VENDOR;
ctrlEpt .ReqCode = 0x00;
ctrlEpt .Value = 0x0007;
ctrlEpt .Index = 0;
ctrlEpt .TimeOut = 3000;
int len = 8;
byte[] data = new byte[len];
bool result = controlEndPoint.XferData(ref data, ref len );
if (result)
return data;
return null;
}
Please let me know if this works, and the value returned by the XferData function.
Thanks,
Yatheesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Yatheesh,
This looks really good !!!
I'm getting the voltage back now !!
I see that the ReqType is different and you added a timeout !!
I realize that the PassMark console application had a different value for ReqType which is probably what threw me under the bus....
Currently I have no idea why that works, but you helping me along the way is great !!
Anyway, I hope that this means that I can continue my development !
Thank you very much for your support !!!
King regards
Magnus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
...and it works great without the timeout (i.e. using the default) and using the Read function !!
The problem was the ReqType all along...
This is my final version.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Confusing as it is....
ReqType seems to be defined as 2 unless I don't understand C++ at all (which of course is quite possible.... )
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Magnus,
It's great to see that the application is working !!
There are few differences in implementing CyAPI.lib for C++ and CyUSB.dll for C#.
The Timeout can be removed as it is not necessary for control transfers.
Best wishes on the development with our product and please do create threads on community in case you face any issues.
Best Regards,
Yatheesh