Trying to communicate with DMC20xx through USB interface NET2888 - c++

I am trying to communicate with a galil motion controler DMC2070 through its USB interface.
The USB interface of the DMC2070 is made with a NET2888 chip but it is not supported by windows 7 or 10.
I currently load the winusb driver and try to communicate with it with libusb-1.0 (statically linked 32bit version) and compile with mingw32-gcc under windows 10 (64bit).
I managed to claim the interface but could not send or receive messages.
Here is my test program :
#include <cstring>
#include <stdio.h>
#include "libusb/libusb.h"
int main(){
char entry;
libusb_context *context = nullptr;
int status, nwrite;
unsigned char buffer[64] = "TP\0";
libusb_device_handle *handle = nullptr;
printf("start usb test (y/n) ?");
scanf("%c", &entry);
if(entry=='n') return 0;
libusb_init(&context);
handle = libusb_open_device_with_vid_pid(context, 0x06B3, 0x07D1);
if(handle){
printf("Device %04x:%04x opened with success\n",0x06B3,0x07D1);
}
else {
libusb_exit(nullptr);
printf("device %04x:%04x not found\n",0x06B3,0x07D1);
system("pause");
return 1;
}
libusb_set_auto_detach_kernel_driver(handle, 1);
status = libusb_claim_interface(handle,0);
if(status!=0){
libusb_close(handle);
libusb_exit(nullptr);
fprintf(stderr, "usb_claim_interface error %d\n", status);
system("pause");
return 2;
}
printf("Interface claimed successfully\n");
status = libusb_bulk_transfer(handle, USB_ENDPOINT_OUT,
buffer, 64, &nwrite, TIMEOUT);
if(status==0) printf("send %d bytes to device\n", nwrite);
else printf("error %d, writing to device\n", status);
libusb_release_interface(handle,0);
libusb_close(handle);
libusb_exit(nullptr);
system("pause");
return 0;
}
Here is the resulting output :
start usb test (y/n) ?y
Device 06b3:07d1 opened with success
Interface claimed successfully
error -5, writing to device
Error -5 corresponds to LIBUSB_ERROR_NOT_FOUND which means "Entity not found".
I am not used to deal with USB interface directly, and hope someone with far more experience could enlighten my path.
I am thinking about installing a vm with windows xp and try reverse the driver.

you have to set the configuration before claim interface.

Related

QSerialPort is in use before application starts

I am developing an application for Apalis iMX6 with Qt C++ in Linux and I've added this application into the startup by means of profile.d
this code must set ttymxc1 into RS485 mode like below:
int enableRS485(){
struct serial_rs485 rs485conf;
int fd = open ("/dev/ttymxc1", O_RDWR);
if (fd < 0) {
printf("Error: Can't open: /dev/ttymxc1 %d\n",fd);
return fd;
}
rs485conf.flags |= SER_RS485_ENABLED;
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
rs485conf.flags |= SER_RS485_RX_DURING_TX;
err = ioctl (fd, TIOCSRS485, &rs485conf);
if (err < 0) {
printf("Error: TIOCSRS485 ioctl not supported.\n");
return err;
}
err = close (fd);
if (err < 0) {
printf("Error: Can't close: /dev/ttyLP1 %d\n",err);
return err;
}
return 0;
}
this function is working as well and has no problem. but when I try to open the serial port sometimes during startup application couldn't get this serial port and QSerialPortInfo shows me ttymxc1 is in use. my initiation of the serial port is like below:
void SerialClass::initSerial()
{
m_serialPort = new QSerialPort();
enableRS485();
sleep(1);
m_serialPort->setPortName("/dev/ttymxc1");
m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
m_serialPort->setBaudRate(9600);
m_serialPort->setRequestToSend(false);
bool res = m_serialPort->open(QIODevice::ReadWrite);
}
"QSerialPort::errorOccured" signal will emit with value "PermissionError"
but mysteriously "ls -l /proc/[0-9]/fd/ |grep /dev/ttymxc1" shows me ttymxc1 is in used by my application.
there is no application that works with serial port and my application is just for one time run.
Is there any idea?
Thanks
You need to call close() on m_serialPort when you close your application. Otherwise your serial port will keep in-use state.
I've found a new remedy, so I want to share it here.
in SerialClass constructor I've added initSerial(), in this way application at the beginning of starting, will open the ttymxc1.
There is no more problem with such a solution.
I don't have such an issue with Raspberry Pi (Raspberry Pi3 + Qt 5.6 + Raspbian). But Toradex Apalis is in another way.
Would you please tell me why?

getting iaxclient to send audio to/get audio from buffer instead of audio-device

I'm trying to write a C++ program (altough python would've been fine as well in case someone knows a better (IAX/SIP) alternative) which connects to an Asterisk server.
After connecting, it should listen for audio and process that. It should also send audio back. I'm using https://sourceforge.net/projects/iaxclient/ for that (note that there are several versions (betas, regular releases, svn version) which all behave differently).
Now if I understood the code of the library correct, then it can call a callback function with an event. One of those events is IAXC_EVENT_AUDIO. In the structure of that IAXC_EVENT_AUDIO there's a direction; incoming outgoing. And that's where I'm lost: with some versions of iaxclient I only receive the IAXC_SOURCE_REMOTE messages, with some both. And if I switch to test-mode (which should only disable the audio-device) I often receive nothing at all. When I receive both IAXC_SOURCE_LOCAL and IAXC_SOURCE_REMOTE, I tried to set the buffers of those events to random data but that doesn't reach the other end at all (I set it to RAW mode).
As anyone any suggestions how to resolve this?
My test-code is:
#include <iaxclient.h>
#include <unistd.h>
int iaxc_event_callback(iaxc_event e)
{
if (e.type == IAXC_EVENT_TEXT) {
printf("text\n");
}
else if (e.type == IAXC_EVENT_LEVELS) {
printf("level\n");
}
else if (e.type == IAXC_EVENT_STATE) {
struct iaxc_ev_call_state *st = iaxc_get_event_state(&e);
printf("\tcallno %d state %d format %d remote %s(%s)\n", st->callNo, st->state, st->format,st->remote, st->remote_name);
iaxc_key_radio(st->callNo);
}
else if (e.type == IAXC_EVENT_NETSTAT) {
printf("\tcallno %d rtt %d\n", e.ev.netstats.callNo, e.ev.netstats.rtt);
}
else if (e.type == IAXC_EVENT_AUDIO) {
printf("\t AUDIO!!!! %d %u %d\n", e.ev.audio.source, e.ev.audio.ts, e.ev.audio.size);
for(int i=0; i<e.ev.audio.size; i++)
printf("%02x ", e.ev.audio.data[i]);
printf("\n");
}
else {
printf("type: %d\n", e.type);
}
return 1;
}
int main(int argc, char *argv[])
{
iaxc_set_test_mode(1);
printf("init %d\n", iaxc_initialize(1));
iaxc_set_formats(IAXC_FORMAT_SPEEX, IAXC_FORMAT_SPEEX);
iaxc_set_event_callback(iaxc_event_callback);
printf("get audio pref %d\n", iaxc_get_audio_prefs());
//printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED));
printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW | IAXC_AUDIO_PREF_RECV_LOCAL_RAW));
printf("get audio pref %d\n", iaxc_get_audio_prefs());
printf("start thread %d\n", iaxc_start_processing_thread());
int id = -1;
printf("register %d\n", id = iaxc_register("6003", "1923", "192.168.64.1"));
int callNo = -1;
printf("call %d\n", callNo = iaxc_call("6003:1923#192.168.64.1/6001"));
printf("unquelch: %d\n", iaxc_unquelch(callNo));
pause();
printf("finish\n");
printf("%d\n", iaxc_unregister(id));
printf("%d\n", iaxc_stop_processing_thread());
iaxc_shutdown();
return 0;
}
Please have a look in iaxclient_lib.c too see how the logic works. To hook or replace input/output you can change function iaxci_do_audio_callback at memcpy(e.ev.audio.data, data, size); where the buffer is set. Also have a look at service_audio to understand how you can replace the buffer/stream sent to the remote location (e.g. want_send_audio and want_local_audio). You can also create virtual input/output devices in portaudio that iaxclient use for process audio using buffers instead.
For a more concrete example please look at the main method in the simplecall source to get a good start. However, the source code is to long for copy and paste, sorry about that.

Linux C++ LibUSB Write Register in USB HUB

In Linux, I have a USB hub with the 'register' shown in the image below. This register is supposed to disable power on a certain port on the hub.
I tried to use LibUSB ( my code is shown below ) to write the register, 0x0A, with all zeros to disable all ports. The problem is, the hub is controlled by the standard Linux USB Hub driver and so the Kernel driver is detached. The write also fails. The failure messages are shown below.
Error messages:
$ /mnt/apps/UsbPowerControl
5 Devices in list.
Vendor:Device = 1908:1320
Vendor:Device = 0403:6001
Vendor:Device = 289d:0010
Vendor:Device = 0424:2513
Vendor:Device = 1d6b:0002
Opening Device = 0424:2513
Device Opened
Kernel Driver Active
Kernel Driver Detached!
Claimed Interface
Data-><-
Writing Data...
libusb: error [submit_bulk_transfer] submiturb failed error -1 errno=2
Write Error
Released Interface
How can I use LibUSB to write this Hub register, to dynamically disable and enable the ports, without unregistering the Linux driver and having my write fail?
#include <iostream>
#include <cassert>
#include <libusb-1.0/libusb.h>
using namespace std;
#define VENDOR_ID 0x0424
#define PRODUCT_ID 0x2513
int main() {
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0) {
cout<<"Init Error "<<r<<endl; //there was an error
return 1;
}
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
cout<<"Get Device Error"<<endl; //there was an error
return 1;
}
cout<<cnt<<" Devices in list."<<endl;
for (size_t idx = 0; idx < cnt; ++idx) {
libusb_device *device = devs[idx];
libusb_device_descriptor desc = {0};
int rc = libusb_get_device_descriptor(device, &desc);
assert(rc == 0);
printf("Vendor:Device = %04x:%04x\n", desc.idVendor, desc.idProduct);
}
printf("Opening Device = %04x:%04x\n", VENDOR_ID, PRODUCT_ID);
dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL)
cout<<"Cannot open device"<<endl;
else
cout<<"Device Opened"<<endl;
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
unsigned char *data = new unsigned char[1]; //data to write
data[0]=0b00000000;
int actual; //used to find out how many bytes were written
if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached
cout<<"Kernel Driver Active"<<endl;
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
cout<<"Kernel Driver Detached!"<<endl;
}
r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
if(r < 0) {
cout<<"Cannot Claim Interface"<<endl;
return 1;
}
cout<<"Claimed Interface"<<endl;
cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
cout<<"Writing Data..."<<endl;
r = libusb_bulk_transfer(dev_handle, (0x0A | LIBUSB_ENDPOINT_OUT), data, 1, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
if(r == 0 && actual == 1) //we wrote the 1 bytes successfully
cout<<"Writing Successful!"<<endl;
else
cout<<"Write Error"<<endl;
r = libusb_release_interface(dev_handle, 0); //release the claimed interface
if(r!=0) {
cout<<"Cannot Release Interface"<<endl;
return 1;
}
cout<<"Released Interface"<<endl;
libusb_close(dev_handle); //close the device we opened
libusb_exit(ctx); //needs to be called to end the
delete[] data; //delete the allocated memory for data
return 0;
}
int libusb_detach_kernel_driver ( libusb_device_handle * dev,
int interface_number
)
...
If successful, you will then be able to claim the interface and perform I/O.
...
int libusb_kernel_driver_active ( libusb_device_handle * dev,
int interface_number
)
...
If a kernel driver is active, you cannot claim the interface, and libusb will be unable to perform I/O.
...
Due to what is written above, the short answer to the question "How to do I/O without detaching driver" is "You can't".
Why write fails? This is another matter. I'd suggest looking into a number of things:
Check out the value returned from libusb_bulk_transfer, maybe it will give you the idea of what is happening.
Sounds stupid, but I always check it out before anything else: process privileges.
Also, I can suggest another way of approaching the solution, namely sysfs.
I assume that your device(am I right?) supports EEPROM and SMBus access. It means that this support should be manifested in the kernel somewhere around /sys/bus/i2c/devices/[some_device_id]/eeprom (probably another device number, another directory position, etc, because it is all driver-related), but if it can be found and read just as any other file (which is likely, unless something is wrong with the device), then it probably should be able to write into it as well. If the read works, then I suggest to compare the hexdump -C of the found file to the datasheet, and if the data seems legit, try writing directly into your register(file offset).
Anyway, accessing character device files and sysfs files is a general way of accessing drivers' data in linux. Probably you don't even need to use libusb's API to write that single byte.

c++ Jackaudio can't get stereo sound

I am trying JackAudio with c++ on Windows 8.1 and it works.
I am using a simple client code that can be found on the git. This code should send a low pitch signal to one hear and a high pitch signal to the other but for me it sends both signals to both hear.
I don't know what is wrong since two are registered and both get access to the correct speakers.
/** #file simple_client.c
*
* #brief This simple client demonstrates the basic features of JACK
* as they would be used by many applications.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <jack/jack.h>
jack_port_t *output_port1, *output_port2;
jack_client_t *client;
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
static void signal_handler(int sig)
{
jack_client_close(client);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}
/**
* The process callback for this JACK application is called in a
* special realtime thread once for each audio cycle.
*
* This client follows a simple rule: when the JACK transport is
* running, copy the input port to the output. When it stops, exit.
*/
int
process(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *out1, *out2;
paTestData *data = (paTestData*)arg;
int i;
out1 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port1, nframes);
out2 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port2, nframes);
for (i = 0; i<nframes; i++)
{
out1[i] = data->sine[data->left_phase]; // left
out2[i] = data->sine[data->right_phase]; // right
data->left_phase += 1;
if (data->left_phase >= TABLE_SIZE) data->left_phase -= TABLE_SIZE;
data->right_phase += 10; // higher pitch so we can distinguish left and right.
if (data->right_phase >= TABLE_SIZE) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/**
* JACK calls this shutdown_callback if the server ever shuts down or
* decides to disconnect the client.
*/
void
jack_shutdown(void *arg)
{
exit(1);
}
int
main(int argc, char *argv[])
{
const char **ports;
const char *client_name;
const char *server_name = NULL;
jack_options_t options = JackNullOption;
jack_status_t status;
paTestData data;
int i;
/*if (argc >= 2) { // client name specified?
client_name = argv[1];
if (argc >= 3) { // server name specified?
server_name = argv[2];
int my_option = JackNullOption | JackServerName;
options = (jack_options_t)my_option;
}
}
else { // use basename of argv[0]
client_name = strrchr(argv[0], '/');
if (client_name == 0) {
client_name = argv[0];
}
else {
client_name++;
}
}*/
client_name = "mytest";
for (i = 0; i<TABLE_SIZE; i++)
{
data.sine[i] = 0.2 * (float)sin(((double)i / (double)TABLE_SIZE) * M_PI * 2.);
}
data.left_phase = data.right_phase = 0;
// open a client connection to the JACK server
client = jack_client_open(client_name, options, &status, server_name);
if (client == NULL) {
fprintf(stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
if (status & JackServerFailed) {
fprintf(stderr, "Unable to connect to JACK server\n");
}
exit(1);
}
if (status & JackServerStarted) {
fprintf(stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
client_name = jack_get_client_name(client);
fprintf(stderr, "unique name `%s' assigned\n", client_name);
}
// tell the JACK server to call `process()' whenever
//there is work to be done.
jack_set_process_callback(client, process, &data);
// tell the JACK server to call `jack_shutdown()' if
//it ever shuts down, either entirely, or if it
//just decides to stop calling us.
jack_on_shutdown(client, jack_shutdown, 0);
// create two ports
output_port1 = jack_port_register(client, "output1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
output_port2 = jack_port_register(client, "output2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ((output_port1 == NULL) || (output_port2 == NULL)) {
fprintf(stderr, "no more JACK ports available\n");
exit(1);
}
//Tell the JACK server that we are ready to roll. Our
// process() callback will start running now.
if (jack_activate(client)) {
fprintf(stderr, "cannot activate client");
exit(1);
}
// Connect the ports. You can't do this before the client is
// activated, because we can't make connections to clients
// that aren't running. Note the confusing (but necessary)
// orientation of the driver backend ports: playback ports are
// "input" to the backend, and capture ports are "output" from
// it.
ports = jack_get_ports(client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if (ports == NULL) {
fprintf(stderr, "no physical playback ports\n");
exit(1);
}
if (jack_connect(client, jack_port_name(output_port1), ports[0])) {
fprintf(stderr, "cannot connect output ports\n");
}
if (jack_connect(client, jack_port_name(output_port2), ports[1])) {
fprintf(stderr, "cannot connect output ports\n");
}
jack_free(ports);
// install a signal handler to properly quits jack client
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif
// keep running until the Ctrl+C
while (1) {
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
jack_client_close(client);
exit(0);
}
Did you ever figure this out? I'm quite new to coding with and configuring Jack myself but my hunch is, the problem is not in the code, rather it's a mixer issue. I suspect there's a setting somewhere that has put the jack server in a mono mode of sorts which would mean all output streams are multed (yes spell checker, multed is a word in the audio engineering world :) ) to all physical audio outputs. So... stream 1 would be connected to the left and right physical output, and stream 2 would also be connected to the physical left and right outputs.
There is nothing anywhere that would necessarily say that stream 1 goes to the left output and stream 2 goes to the right... in fact, if you're running an SDDS configuration the first stream might be the left output, and the 2nd might be the left center... you wouldn't get to the right channel until you hit the 5th stream (with the 2nd, 3rd, and 4th being left center, center, and right center respectively).
Again, this is just a guess but check to see if there's a mixer or "patch bay" style application on your platform that allows you to route streams to physical outputs. In the meantime, I'll give this code a go on my system (Debian unstable/w experimental 4.3 kernel) to see what happens.
Cheers, Joe
Pardon, me - it's an old question, but for the benefit of whoever reads it... I tested this program on my System and found it works correctly!
Question to the original poster: Would you object to having this example included in the JackD example repository (https://github.com/jackaudio/example-clients)? I feel that it's a very good example on how to use the audio streaming part of the JackD API. It would probably need some small rewrite as a generic platform C program; it would be under the same license as the other examples in the JackD example repo (GPL 2). I've sent a mail to the JackD developer's list (jack-devel#lists.jackaudio.org) asking what they think.
Anyway - shewhorn had the correct hunch - nothing wrong with your code, but when you tested your program there was something wrong with the port mappings on your system (i.e. how the ports were mapped to the physical ports on your soundcard). The way to fix it is outside your application: Use some mixer or patch bay style application to route your program's streams correctly. Not your (code's) fault, your program works fine and does what you intended.

Unable to use windows.h ReadFile correctly on COM port. WriteFile seems to work fine

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.