Im trying to purge the FX-Buffer of the FT201X I2C-Slave. Somehow it seems not to work, the master still reads old data sets even after the purge-function is called. Im using C++(Visual Studio 2019) with the D2XX-functions given in the D2XX-Programmers-Guide.
I did try to use the StopInTask and RestartInTask functions before and after the purge command, but it still does not clear my buffer.
status = FT_StopInTask(fthandle);
if (status != FT_OK) {
printf("status not ok %d\n", status);
}
status = FT_Purge(fthandle, FT_PURGE_TX); // Purge Tx buffer
if (status != FT_OK) {
printf("status not ok %d\n", status);
}
status = FT_RestartInTask(fthandle);
if (status != FT_OK) {
printf("status not ok %d\n", status);
}
I did even try FT_W32_PurgeComm(fthandle, PURGE_TXABORT | PURGE_TXCLEAR), the buffer still appears to not be cleared, even if the function returns true.
Somehow FT_Purge(fthandle, FT_PURGE_RX) clears both buffers, the buffer that stores the data coming from the host (sent via FT_Write) as well as the buffer that stores data coming from an external I2C-Master. Mapping the signal RXF (value: 10) to a CBUS-pin and reading the pins with FT_GetBitMode works to indicate if the buffer that stores data from the host is empty.
Related
I'm currently experimenting with Apple's I/O Kit to develop a kernel module. I'm trying to create a device driver for a USB Wireless Card (TP-Link WN722N-v1) using IOUSBHostDevice.
I managed to get the kext loaded and it probes correctly with the card, but I need to send the firmware to the card, which I am trying to do in probe().
I don't have the perfect knowledge of how everything goes, but it seems that I need to send a request to the configuration endpoint 0, but the ways I have tried I get kernel panic, and the other examples I have are using an obsolete DeviceRequest with no exchangeable arguments with the new deviceRequest.
I have a reference for writing the firmware from github project "BrcmPatchRAM" but all the forks use old IOUSBInterface instead of IOUSBHostInterface.
I have search this site for similar questions but found none helpful in this matter, I also searched Apple developer website documentation and it references also the old ways of DeviceRequest.
Which is the right way of re-writing this for example:
IOReturn USBInterfaceShim::hciCommand(void* command, UInt16 length)
{
IOUSBDevRequest request =
{
.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBDevice),
.bRequest = 0,
.wValue = 0,
.wIndex = 0,
.wLength = length,
.pData = command
};
return m_pInterface->DeviceRequest(&request);
}
Using some other implementation of this function gives me an error when loading the driver and tells me that I am sending the request before calling prepare, but I did called prepare before sending the request.
Here is a section of my messy code:
<pre>IOReturn AirPort_Atheros9271::pipeCommand(UInt8 requestType, UInt8 command, UInt16 address, IOMemoryDescriptor *buffer)
{
DeviceRequest request;
request.bmRequestType = requestType;
request.bRequest = command;
request.wValue = address;
request.wIndex = 0;
request.wLength = buffer->getLength();
uint32_t bytesTransferred;
return fInterface->deviceRequest(request, buffer, bytesTransferred, kUSBHostStandardRequestCompletionTimeout);
}
IOReturn AirPort_Atheros9271::pipeCommand(UInt8 requestType, UInt8 command, UInt16 address, void *buffer, UInt16 length)
{
DeviceRequest request;
request.bmRequestType = requestType;
request.bRequest = command;
request.wValue = address;
request.wIndex = 0;
request.wLength = length;
uint32_t bytesTransferred;
return fInterface->deviceRequest(request, buffer, bytesTransferred, kUSBHostStandardRequestCompletionTimeout);
}
bool TL_WN722N::performUpgrade()
{
IOLog("TL_WN722N::[%04x:%04x]: Performing firmware upgrade.\n", fVendorId, fProductId);
OSData *firmwareData = OSData::withBytes(ar9271_fw, ar9271_fw_len);
IOMemoryDescriptor *buffer = IOMemoryDescriptor::withAddress((void*)firmwareData->getBytesNoCopy(), firmwareData->getLength(), kIODirectionIn);
bool success = true;
IOLog("TL_WN722N::[%04x:%04x]: I have firmwareData and created the buffer\n", fVendorId, fProductId);
IOLockLock(fCompletionLock);
IOReturn result;
if (buffer!=NULL)
{
IOLog("TL_WN722N::[%04x:%04x]: Buffer is not null, now calling prepare()\n", fVendorId, fProductId);
if ((result = buffer->prepare(kIODirectionNone)) == kIOReturnSuccess)
{
IOLog("TL_WN722N::[%04x:%04x]: prepare() called and pass! Piping I - writing firmware\n", fVendorId, fProductId);
IOLog("TL_WN722N::[%04x:%04x]: Resultado de prepare: Result: %d\n", fVendorId, fProductId,result);
IOLog("TL_WN722N::[%04x:%04x]: About to excecute pipeCommand\n", fVendorId, fProductId);
result = pipeCommand(0x40, FIRMWARE_DOWNLOAD, AR9271_FIRMWARE >> 8, buffer); //TODO: EXPLOTION LINE
if (result>0) {
IOLog("TL_WN722N::[%04x:%04x]: Resultado de pipeCommand: %d\n", fVendorId, fProductId,result);
}
if (result != kIOReturnSuccess)
IOLog("TL_WN722N::[%04x:%04x]: Unable to write the firmware (0x%08x).\n", fVendorId, fProductId, result);
else
{
if ((result = pipeCommand(0x40, FIRMWARE_DOWNLOAD_COMP, AR9271_FIRMWARE_TEXT >> 8, NULL, 0)) != kIOReturnSuccess)
IOLog("TL_WN722N::[%04x:%04x]: Unable to write the firmware complete sequence (0x%08x).\n", fVendorId, fProductId, result);
else
{
IOLog("TL_WN722N::[%04x:%04x]: Success in writing the firmware sequence.\n", fVendorId, fProductId);
success = true;
}
}
}
else
IOLog("TL_WN722N::[%04x:%04x]: Failed to prepare write memory buffer (0x%08x).\n", fVendorId, fProductId, result);
if ((result = buffer->complete()) != kIOReturnSuccess)
IOLog("TL_WN722N::[%04x:%04x]: Failed to complete write memory buffer (0x%08x).\n", fVendorId, fProductId, result);
}
else
IOLog("TL_WN722N::[%04x:%04x]: Unable to allocate write memory buffer.\n", fVendorId, fProductId);
IOLockUnlock(fCompletionLock);
OSSafeReleaseNULL(buffer);
OSSafeReleaseNULL(firmwareData);
return success;
}</pre>
Putting together a few pieces here:
Using some other implementation of this function gives me an error when loading the driver and tells me that I am sending the request before calling prepare, but I did called prepare before sending the request.
This gives us a pretty big clue that your issue is with the memory buffer. So let's see where the creation and prepare() are happening:
IOMemoryDescriptor *buffer = IOMemoryDescriptor::withAddress(
(void*)firmwareData->getBytesNoCopy(), firmwareData->getLength(),
kIODirectionIn);
// ^^^^^^^^^^^^^^^^
So you're creating an input (read) memory descriptor.
if ((result = buffer->prepare(kIODirectionNone)) == kIOReturnSuccess)
kIODirectionNone just uses the creation direction, so you're preparing for reading data from the device.
And then, the I/O:
result = pipeCommand(0x40, FIRMWARE_DOWNLOAD, AR9271_FIRMWARE >> 8, buffer); //TODO: EXPLOTION LINE
// --------------------------^^^^
This means your bmRequestType is 0x40, and therefore does not have the 0x80 bit set. This means it's host-to-device, i.e. an output/write.
So you've got a direction mismatch: you're preparing some memory for reading from the USB device and then try to use it to write to the device. This won't work.
A few more comments:
An OSData isn't really an ideal candidate for I/O buffer allocation. If you want to allocate system memory for I/O, use an IOBufferMemoryDescriptor. If ar9271_fw is a statically allocated array, you can also simply wrap it using IOMemoryDescriptor::withAddress() - this avoids the copy that OSData::withBytes() performs.
You're performing I/O while holding the IOLockLock(fCompletionLock); lock. This isn't a great idea even when launching async I/O, but it looks like you're using the blocking version of deviceRequest? That's almost certainly not what you want: the function call can literally take seconds to complete or fail. You should not be holding locks for that long.
I am writing some code that involves using an inertia cube tracker, that actively changes its yaw pitch and roll (in degrees) and I need to set up a server that reads that information in order to network the info. So far I have created a client and server, but the problem I am having is either to send the information in one chunck then read it back as three and print it, or to specify which send matches with which recieve.
if( currentTrackerH > 0 )
{
int iSendResult1;
int iSendResult2;
int iSendResult3;
char EulerBuffer0[64];
char EulerBuffer1[64];
char EulerBuffer2[64];
showStationData( currentTrackerH, &TrackerInfo,
&Stations[station-1], &data.Station[station-1],
&StationsHwInfo[currentTrackerH-1][station-1],
showTemp);
//send to the server
do{
sprintf(EulerBuffer0, "%f", data.Station[station-1].Euler[0]);
iSendResult1= send(Connection, EulerBuffer0, sizeof(data.Station[station-1].Euler[0]), NULL);
sprintf(EulerBuffer1, "%f", data.Station[station-1].Euler[1]);
iSendResult2= send(Connection, EulerBuffer1, sizeof(data.Station[station-1].Euler[1]), NULL);
sprintf(EulerBuffer2, "%f", data.Station[station-1].Euler[2]);
iSendResult3= send(Connection, EulerBuffer2, sizeof(data.Station[station-1].Euler[2]), NULL);
}while ((iSendResult1 || iSendResult2 || iSendResult3)>0);
//shutdown the socket when there is no more data to send
iSendResult1 = shutdown(Connection, SD_SEND);
if (iSendResult1 == SOCKET_ERROR)
{
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(Connection);
WSACleanup();
return 1;
}
}
}
This is my client side and here I will put my server side. The networks connect and my tracker code works just fine but sending and recieving is where it all gets wonky.
//begin recieving data
char yaw[256];
char pitch[256];
char roll[256];
int iResult1;
int iResult2;
int iResult3;
float fyaw, fpitch, froll;
do{
do {
iResult1= recv(newConnection, yaw,sizeof(yaw),NULL);
} while( iResult1 == 0 );
fyaw = atof(yaw);
do {
iResult2= recv(newConnection, pitch,sizeof(pitch),NULL);
} while( iResult1 == 0 );
fpitch = atof(pitch);
do {
iResult3= recv(newConnection, roll,sizeof(roll),NULL);
} while( iResult1 == 0 );
froll = atof(roll);
printf("(%f,%f,%f)deg \n",
fyaw, fpitch, froll);
}while(1);
my knowledge of c++ is not fantastic and any help would be lovely. Thanks!
There is all kinds of wrong in your code. Let's try to break down and correct misconceptions (I assume you're using TCP.) You are sending buffers of one size, but recv'ing potentially a buffer of another size. sizeof(yaw) which is a float, is not the same as the size of the string representation of this float.
Calling send/recv for individual item is slow. Ideally you would define a simple protocol. A message in this protocol would be a string containing all the values you wish to transmit. You send that message using a single send() On the receiving side you read in the stream of data, and look for specific markers that tell you when you have received a complete message. You then process that message, splitting out the different components into your yaw/pitch/roll variables.
An example of a string message would be: "{yaw=1.34;pitch=2.45;roll=5.67}"
Then on the client you continually read into a buffer your data until you reach the "}" Then you can process this message and parse out the different components.
I am trying to use the windows.h library to communicate through RS232 with a device (SCPI communication). I have looked at several tutorials and guides on how to set this up and think my code should work correctly. I am able to send data to the device using WriteFile. However, I am not able to receive any data using ReadFile (ReadFile generates no errors but the buffer size is 0). Here is my code:
#include <stdio.h>
#include <windows.h>
void main ()
{
// CreateFile
HANDLE rs232 = CreateFileA ("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (rs232 == INVALID_HANDLE_VALUE)
{
printf ("fail CreateFile: %d\n", GetLastError ()); system ("pause"); return;
}
// Get & Set CommState
DCB port_configuration;
int err = GetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail GetCommState: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
port_configuration.BaudRate = 19200;
port_configuration.ByteSize = 8;
port_configuration.Parity = 0;
port_configuration.StopBits = 0;
port_configuration.DCBlength = sizeof (port_configuration);
err = SetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail SetCommState\n"); CloseHandle (rs232); system ("pause"); return;
}
// SetCommTimeouts
COMMTIMEOUTS timeout_configuration;
timeout_configuration.ReadIntervalTimeout = 1;// MAXDWORD;
timeout_configuration.ReadTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.ReadTotalTimeoutConstant = 1;// 0;
timeout_configuration.WriteTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.WriteTotalTimeoutConstant = 1;// 0;
err = SetCommTimeouts (rs232, &timeout_configuration);
if (err <= 0)
{
printf ("fail SetCommTimeouts: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
// WriteFile
DWORD buffer_size_w;
char buffer_w[128] = "*IDN?\n";
err = WriteFile (rs232, buffer_w, strlen (buffer_w), &buffer_size_w, 0);
if (err <= 0)
{
printf ("fail WriteFile: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
printf ("written %d characters: %s\n", buffer_size_w, buffer_w);
// ReadFile
for (int x = 0; x < 10; ++x)
{
DWORD buffer_size_r;
char buffer_r[128] = {0};
err = ReadFile (rs232, buffer_r, 128, &buffer_size_r, 0);
if (err <= 0)
{
printf ("fail ReadFile: %d\n", GetLastError ()); Sleep (250); continue;
}
printf ("read %d characters: %s\n", buffer_size_r, buffer_r);
Sleep (250);
}
CloseHandle (rs232);
system ("pause");
}
Here is some more information about my setup:
I am using Windows 7 x64 and Microsoft Visual Studio 2013
The project is compiled as a Win32 Console
I use a FTDI Chipi-X USB to COM port converter cable
I have tried connecting with a Newport Motion Controller and a Thorlabs Piezo Controller
Here are the things I have tried so far:
Update the drivers of the Chipi-X VCOM
Change the COMMTIMEOUTS to various different values as seen in guides online
Using a HyperTerminal I am able to fully communicate back and forth with the device. If I use my own program to send commands that request something of the device, such as "*IDN?\n", my own ReadFile would thus return nothing. However, when I connect the HyperTerminal again I can press ENTER to receive the requested information.
Change the buffer sizes using SetupComm()
Change the ReadFile buffer size to 1 byte at a time
Implement the OVERLAPPED method as explained in this guide: https://msdn.microsoft.com/en-us/library/ff802693.aspx. It gave exactly the same problem as the non-overlapped code above: The windows functions would not generate errors but the read buffer would stay empty.
I tried communicating with a different device, this was interesting: Again I was able to fully communicate back and forth using the HyperTerminal. Whenever I used my own program to send, I would always receive the exact string I sent back using ReadFile. And again the actual requested information could be retrieved by reconnecting the HyperTerminal.
It seems to me there is some problem with buffers but I don't know what. I am also not sure if it is expectable that the HyperTerminal is able to pick up requested information that was requested several seconds earlier through a different COM port connection. Presumably the problem is related to my coding since the HyperTerminal works fine, but I cannot seem to find what is wrong with my code if I compare it with other code I find online.
Can someone help me out here?
EDIT:
I have created a new CLR/C++ test application using the following example: https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx. This again gives the exact same problem of not being able to receive requests.
I have tried a Roline USB to RS232 cable: HyperTerminal works and my programming does not. The underlying hardware or drivers are likely not the problem here.
I solved the issue:
I forgot to send the carriage return (\r) at the end of my commands. Apparently the devices I was testing with both were waiting for the combination \r\n before actually parsing the request.
Somehow by using the hyperterminal I would be able to append the \r\n to the current COM port output buffer and get results delayed like that.
I'm implementing gstreamer media player with my own source of data using appsrc. Everything works fine except one thing:
When stream reaches it's end, callback emits "end-of-stream" signal. Signals sending fucntion g_signal_emit_by_name(appsrc, "end-of-stream", &ret) returns GstFlowReturn value GST_FLOW_OK. But then it calls need-data my callback again, so it returns "end-of-stream" signal again. And this time GstFlowReturn value is (-3) which is GST_FLOW UNEXPECTED. I assume that it does not expect "end-of-stream" signal when it already recieved one, but why it requests more data than? Maybe it is because I didn't set size value iof the steam?
Gstreamer version is 0.10.
Callback function code (appsrc type is seekable btw):
static void cb_need_data (GstElement *appsrc, guint size, gpointer user_data)
{
GstBuffer *buffer;
GstFlowReturn ret;
AppsrcData* data = static_cast<AppsrcData*>(user_data);
buffer = gst_buffer_new_and_alloc(size);
int read = fread(GST_BUFFER_DATA(buffer), 1, size, data->file);
GST_BUFFER_SIZE(buffer) = read;
g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
if (ret != GST_FLOW_OK) {
/* something wrong, stop pushing */
g_printerr("GST_FLOW != OK, return value is %d\n", ret);
g_main_loop_quit (data->loop);
}
if(feof(data->file) || read == 0)
{
g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
if (ret != GST_FLOW_OK) {
g_printerr("EOF reached, GST_FLOW != OK, return value is %d\nAborting...", ret);
g_main_loop_quit (data->loop);
}
}
}
You should provide some corrections to your code(if they are not there already) that should alleviate your issue and help the overall application:
Never try and send a buffer without first checking if it actually has data. So, simply check the buffer data and length to make sure that the data is not NULL and that the length is >0
You can flag that a stream is ended in your user_data. When you send your EOS, set an item in your userdata to indicate that it has been sent and if the appsrc requests more data, simply check if it has been sent and then do not send anything else to the buffer.
Listen for the EOS on your pipeline bus so that it can destroy the stream and close the loop when the EOS message is handled so that you can be sure that your mediasink has received the EOS and you can safely dispose of the pipeline and loop without losing any data.
Have you tried the method gst_app_src_end_of_stream()? I'm not sure what return code you should use after invoking it, but it should be either GST_FLOW_OK or GST_FLOW_UNEXPECTED.
In GStreamer 1.x you return GST_FLOW_EOS.
I tried to read in the raw packet with libpcap (1.4.0 on CentOS 6).
However, for some reasons, rawPacket is always NULL after pcap_next_ex().
However, pcap_next_ex() does return 1 though it could mean timeout expired (where the timeout is set by the way?).
First, I thought that the filter string I passed into pcap_compile() was wrong. But I tried to copy and paste the same string to tcpdump, it worked fine -- I see expected packets being captured.
struct pcap_pkthdr *pHeader;
const u_char* rawPacket = NULL;
int rc = 0;
while (1) {
rc = pcap_next_ex(pDevice, &pHeader, &rawPacket);
if (-1 != rc && NULL != rawPacket) {
// process
struct ether_header* eptr = (struct ether_header *) rawPacket;
if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
printf("Ethernet type hex:%x dec:%d is an IP packet\n",
ntohs(eptr->ether_type),
ntohs(eptr->ether_type));
}
}
}
Any idea?
Thanks in advance.
Actually, what the pcap_next_ex() man page says is
pcap_next_ex() returns 1 if the packet was read without problems, 0 if
packets are being read from a live capture, and the timeout expired, -1
if an error occurred while reading the packet, and -2 if packets are
being read from a ``savefile'', and there are no more packets to read
from the savefile. If -1 is returned, pcap_geterr() or pcap_perror()
may be called with p as an argument to fetch or display the error text.
I need to edit it to remove the comment between "live capture" and "and the timeout expired", because what that means is that pcap_next_ex() returns:
1, if a packet was read or captured, in which case the pointer should be set to the raw packet;
0, if this is a live capture and the timeout (as specified in pcap_open_live() or, if you used pcap_create() and pcap_activate(), pcap_set_timeout()) expired while waiting for a packet, in which case no packet was read and the pointer will be set to NULL;
-1, if an error occurred while reading or capturing, in which case no packet was read and the pointer will be set to NULL;
-2, if this is a file being read and there are no more packets left to be read, in which case no packet was read and the pointer will be set to NULL.
So what you should do, after the pcap_next_ex() call, is:
if (1 == rc) {
// process
struct ether_header* eptr = (struct ether_header *) rawPacket;
if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
printf("Ethernet type hex:%x dec:%d is an IP packet\n",
ntohs(eptr->ether_type),
ntohs(eptr->ether_type));
}
} else if (0 == rc) {
// do nothing here - this isn't an error, but you have no packet
;
} else if (-1 == rc) {
// error
fprintf(stderr, "Error capturing or reading: %s\n", pcap_geterr(pDevice));
// quit trying to read or capture packets here
} else if (-2 == rc) {
// end of file if you're reading from a file
// this isn't an error, but there are no more packets to read
// so quit trying to read packets here
}