Virtual COM Port STM32 and Qt Serial Port - linux

My aim is to enable communication via USB CDC HS on STM32 with Ubuntu 20.04 based PC in Qt app created in QtCreator.
So far I've managed to run communication via UART and everything is working fine. Then I decided to switch to USB and I still can read incoming data (but only in CuteCom) and in my Qt app nothing appears.
To be honest I have no idea what is going on and where to look for mistakes. Here I put the code:
void MainWindow::on_pushButtonConnect_clicked()
{
if (ui->comboBoxDevices->count() == 0){
this->addToLogs("No devices found.");
return;
}
QString portName = ui->comboBoxDevices->currentText().split(" ").first();
this->device->setPortName(portName);
this->device->setBaudRate(QSerialPort::Baud115200);
this->device->setDataBits(QSerialPort::Data8);
this->device->setParity(QSerialPort::NoParity);
this->device->setStopBits(QSerialPort::OneStop);
this->device->setFlowControl(QSerialPort::NoFlowControl);
if(device->open(QIODevice::ReadWrite)){
this->addToLogs("Port opened. Setting the connection params...");
this->addToLogs("UART enabled.");
qDebug() << "Writing down the parameters...";
qDebug() << "Baud rate:" << this->device->baudRate();
qDebug() << "Data bits:" << this->device->dataBits();
qDebug() << "Stop bits:" << this->device->stopBits();
qDebug() << "Parity:" << this->device->parity();
qDebug() << "Flow control:" << this->device->flowControl();
qDebug() << "Read buffer size:" << this->device->readBufferSize();
qDebug() << "Read buffer size:" << this->device->portName();
connect(this->device, SIGNAL(readyRead()), this, SLOT(readFromPort()));
} else {
this->addToLogs("The port can not be opened.");
}
And the readFromPort() function:
void MainWindow::readFromPort()
{
while(this->device->canReadLine()){
QString line = this->device->readLine();
qDebug() << line;
QString terminator = "\r";
int pos = line.lastIndexOf(terminator);
qDebug()<<line.left(pos);
this->addToLogs(line.left(pos));
}
}
Do you have any idea what might be wrong or not set properly? Would be thankful for all help.

As it seems, in my code I put commands to read the port in if (with function canReadLine()). When I commented the whole condition out leaving just the reading, everything worked fine.

Related

winsock : bluetooth client-server not connecting

I have written a small bluetooth server and client progrem using winsock
I am not able to figure out why the client is not getting connected to the server. Both are running in different pcs and
both are paired through bluetooth.
The server code is
void server()
{
SOCKET server_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM), new_socket;
if (server_socket == INVALID_SOCKET)
{
cout << "socket creation failed...Error code : " << WSAGetLastError() << endl;
Sleep(2000);
return;
}
cout << "socket created" << endl;
SOCKADDR_BTH sa, sa2;
int channel = 0, len=sizeof(sa2);
memset(&sa, 0, sizeof(SOCKADDR_BTH));
sa.addressFamily = AF_BTH;
sa.port = channel & 0xff;
//bind
if (bind(server_socket, (SOCKADDR *)&sa, sizeof(sa)))
{
cout << "Binding failed...Error code : " << WSAGetLastError() << endl;
closesocket(server_socket);
Sleep(2000);
return;
}
cout << "binding done" << endl;
cout << "\nWaiting for client" << endl;
listen(server_socket, 3);
new_socket = accept(server_socket, (sockaddr *)&sa2, &len);
cout<<"connection accepted";
}
The client code is
void client()
{
SOCKET client_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
int channel = 0;
BTH_ADDR bt_addr;
char* server_address = "34:02:86:26:c1:62";
if (client_socket == INVALID_SOCKET)
{
cout << "socket creation failed...Error code : " << WSAGetLastError() << endl;
Sleep(2000);
return;
}
cout << "socket created" << endl;
if (str2ba(server_address, &bt_addr) == 1)
{
cout << "address conversion error..." << endl;
Sleep(2000);
return;
}
SOCKADDR_BTH sa;
sa.addressFamily = AF_BTH;
sa.port = channel & 0xff;
sa.btAddr = bt_addr;
cout << "\nconnecting..." << endl;
if (connect(client_socket, (sockaddr *)&sa, sizeof(sockaddr)))
{
cout << "Error in connecting...Error code : " << WSAGetLastError() << endl;
closesocket(client_socket);
Sleep(2000);
return;
}
cout << "\nConnected" << endl;
Sleep(2000);
}
int str2ba(char *str_bt_addr, BTH_ADDR *bt_addr)//for converting string to bluetooth address
{
unsigned int addr[6];
if (sscanf_s(str_bt_addr, "%02x:%02x:%02x:%02x:%02x:%02x",
&addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6)
{
return 1;
}
*bt_addr = 0;
BTH_ADDR tmpaddr;
int i;
for (i = 0;i < 6;++i)
{
tmpaddr = (BTH_ADDR)(addr[i] & 0xff);
*bt_addr = ((*bt_addr) << 8) + tmpaddr;
}
return 0;
}
Why are these not getting connected? What am I missing?
Please help me.
Thanks in advance for any help.
In my short Bluetooth experience, the problem is normally somewhere in the SOCKADDR_BTH declarations.
I hard coded the MAC Address of each Endpoint: "38:2D:E8:B9:FA:EB" in Hex
RemoteEndPoint.btAddr = BTH_ADDR(0x382DE8B9FAEB);
Also make sure your Ports are the same on each Endpoint, I used:
RemoteEndPoint.port = 0;
and
LocalEndpoint.port = 0;
I have some code here: C++ WinSock Bluetooth Connection - AT Command - Error Received where I have an issue also.
Bluetooth is not as easy as some may think, thus the lack of answers received by the OP's

Linux Netcat works as Expected but not QTCPSocket on Raspberry Pi

I have 2 Raspberry Pis, one sender and one receiver which acts as an Access Point using a USB WiFi dongle. I have Qt 5.4.0 code on the sender that uses a USB/FTDI XBee SB6 WiFi unit to send TCP packets to the receiver Pi after connecting to it's Access Point successfully as a client.
The code is sending TCP packets correctly through the XBee to the receiver Pi because I can use the Netcat program on the receiver and watch the packets arrive successfully on port 0x2616 ( 9750 ):
>> sudo nc -l 10.10.10.1 9750
>> HELLOHELLOHELLO
When I try to replace Netcat on the receiver Pi with the following Qt code using QTCPSocket, it never receives any data on the socket. By this I mean that the 'readyRead()' slot is never called. I've run it as sudo and the sender Pi is doing exactly the same transfer as it was when Netcat was capturing the output. What is going on? Am I connecting wrong with QTCPSocket to the local port? How can I make it work? Thanks!
#include "tcpreceiver.h"
// Debug
#include <QDebug>
#define API_DEBUG true
#include <QApplication>
TcpReceiver::TcpReceiver(QObject *parent) :
QObject(parent)
{
// Debug
qDebug() << "Setting up a TCP Socket...";
// Create a socket
m_Socket = new QTcpSocket(this);
// Bind to the 2616 port
m_Socket->connectToHost("10.10.10.1", 0x2616);
//m_Socket->connectToHost( QHostAddress::Any, 0x2616 );
qDebug() << "Socket is valid: " << m_Socket->isValid();
//qDebug() << "Socket value: " << m_Socket->
// Get notified that data is incoming to the socket
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
// Init to Zero
m_NumberTCPPacketsReceived = 0;
}
void TcpReceiver::readyRead() {
qDebug() << "Received data...";
// When data comes in
QByteArray buffer;
buffer.resize(m_Socket->bytesAvailable());
// Cap buffer size
int lenToRead = buffer.size();
if ( buffer.size() > NOMINAL_AUDIO_BUFFER_SIZE ) {
lenToRead = NOMINAL_AUDIO_BUFFER_SIZE;
}
// Read the data from the TCP Port
m_Socket->read(buffer.data(), lenToRead);
...
// Count up
m_NumberTCPPacketsReceived++;
}
Here is how you do it:
#include "tcpreceiver.h"
// Debug
#include <QDebug>
#include <QHostAddress>
TcpReceiver::TcpReceiver(QObject *parent) :
QObject(parent)
{
// Create a server
qDebug() << "Creating a TCP Server...";
// Create the server
m_Server = new QTcpServer(this);
// Listen on the proper port
m_Server->listen( QHostAddress::Any, 0x2616 );
// Hook up signal and slots
connect(m_Server, SIGNAL(newConnection()), this, SLOT(gotNewConnection()));
connect(m_Server, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(error()));
}
void TcpReceiver::gotNewConnection() {
qDebug() << "Got a new TCP Connection";
// Get the socket
m_Socket = m_Server->nextPendingConnection();
if(m_Socket->state() == QTcpSocket::ConnectedState)
{
qDebug() << "Socket was connected at: " << m_Socket->peerAddress();
}
// Hook up some signals / slots
connect(m_Socket, SIGNAL(disconnected()),this, SLOT(disconnected()));
connect(m_Socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
}
void TcpReceiver::disconnected() {
qDebug() << "Socket Disconnected...";
// Cleanup
m_Socket->deleteLater();
}
void TcpReceiver::error() {
qDebug() << "Error: " << m_Server->errorString();
}
void TcpReceiver::readyRead() {
qDebug() << "Received data...";
// Now read data
QByteArray buffer;
if (m_Socket->canReadLine()) {
buffer = m_Socket->readLine();
qDebug() << "Got Data: " << buffer;
}
}

Raspberry Pi GPIO /value file appears with wrong permissions momentarily

My son is implementing a server on a Raspberry Pi that allows control of the GPIO pins via a network connection. He has discovered some strange behaviour, which at first seemed like a bug (but see answer below).
First, the OS being used is Raspbian, a version of Debian Linux. He is using the standard system file to control the GPIO ports.
We start with a GPIO pin, e.g. pin 17, in a non-exported state. For example,
echo "17" > /sys/class/gpio/unexport
Now, if the server is asked to turn on pin 17, it does the following:
Opens the /sys/class/gpio/export, writes "17" to it, and closes the export file
Open the /sys/class/gpio/gpio17/direction file for read, examines it to see if it is set as input or output. Closes the file. Then, if necessary, re-opens the file for write and writes "out" to the file, to set the pin as an output pin, and closes the direction file.
At this point, we should be able to open /sys/class/gpio/gpio17/value for write, and write a "1" to it.
However, the permissions on the /sys/class/gpio/gpio17/value file exists but the group permissions is read-only. If we put in a "sleep" in order to wait for a fraction of a second, the permissions change so the group permission has write permissions.
I would have expected that the OS should not return from the write to the direction file until it had set the permissions on the value file correctly.
Why is this happening? It seems like a bug. Where should I report this (with more detail...)? See answer below.
What follows are the relevant bits of code. The code has been edited and paraphrased a bit, but it is essentially what is being used. (Keep in mind it's the code of a grade 12 student trying to learn C++ and Unix concepts):
class GpioFileOut
{
private:
const string m_fName;
fstream m_fs;
public:
GpioFileOut(const string& sName)
: m_fName(("/sys/class/gpio/" + sName).c_str())
{
m_fs.open(m_fName.c_str());
if (m_fs.fail())
{
cout<<"ERROR: attempted to open " << m_fName << " but failed" << endl << endl;
}
else
{
cout << m_fName << " opened" << endl;
}
}
~GpioFileOut()
{
m_fs.close();
cout << m_fName << " closed" << endl << endl;
}
void reOpen()
{
m_fs.close();
m_fs.open(m_fName);
if (m_fs.fail())
{
cout<<"ERROR: attempted to re-open " << m_fName << " but failed" << endl << endl;
}
else
{
cout << m_fName << " re-opened" << endl;
}
}
GpioFileOut& operator<<(const string &s)
{
m_fs << s << endl;
cout << s << " sent to " << m_fName << endl;
return *this;
}
GpioFileOut& operator<<(int n)
{
return *this << to_string(n); //ostringstream
}
bool fail()
{
return m_fs.fail();
}
};
class GpioFileIn
{
private:
ifstream m_fs;
string m_fName;
public:
GpioFileIn(const string& sName)
: m_fs( ("/sys/class/gpio/" + sName).c_str())
, m_fName(("/sys/class/gpio/" + sName).c_str())
{
if (m_fs <= 0 || m_fs.fail())
{
cout<<"ERROR: attempted to open " << m_fName << " but failed" << endl;
}
else
{
cout << m_fName << " opened" << endl;
}
}
~GpioFileIn()
{
m_fs.close();
cout << m_fName << " closed" << endl << endl;
}
void reOpen()
{
m_fs.close();
m_fs.open(m_fName);
if (m_fs <= 0 || m_fs.fail())
{
cout<<"ERROR: attempted to re-open " << m_fName << " but failed" << endl;
}
else
{
cout << m_fName << " re-opened" << endl;
}
}
GpioFileIn& operator>>(string &s)
{
m_fs >> s;
cout << s << " read from " << m_fName << endl;
return *this;
}
bool fail()
{
return m_fs.fail();
}
};
class Gpio
{
public:
static const bool OUT = true;
static const bool IN = false;
static const bool ON = true;
static const bool OFF = false;
static bool setPinDirection(const int pinId, const bool direction)
{
GpioFileOut dirFOut(("gpio" + to_string(pinId) + "/direction").c_str());
if (dirFOut.fail())
{
if (!openPin(pinId))
{
cout << "ERROR! Pin direction not set: Failed to export pin" << endl;
return false;
}
dirFOut.reOpen();
}
dirFOut << (direction == OUT ? "out" : "in");
}
static bool setPinValue(const int pinId, const bool pinValue)
{
string s;
{
GpioFileIn dirFIn(("gpio" + to_string(pinId) + "/direction").c_str());
if (dirFIn.fail())
{
if (!openPin(pinId))
{
cout << "ERROR! Pin not set: Failed to export pin"<<endl;
return false;
}
dirFIn.reOpen();
}
dirFIn >> s;
}
if (strncmp(s.c_str(), "out", 3) == 0)
{
struct stat _stat;
int nTries = 0;
string fname("/sys/class/gpio/gpio"+to_string(pinId)+"/value");
for(;;)
{
if (stat(fname.c_str(), &_stat) == 0)
{
cout << _stat.st_mode << endl;
if (_stat.st_mode & 020 )
break;
}
else
{
cout << "stat failed. (Did the pin get exported successfully?)" << endl;
}
cout << "sleeping until value file appears with correct permissions." << endl;
if (++nTries > 10)
{
cout << "giving up!";
return false;
}
usleep(100*1000);
};
GpioFileOut(("gpio" + to_string(pinId) + "/value").c_str()) << pinValue;
return true;
}
return false;
}
static bool openPin(const int pinId)
{
GpioFileOut fOut("export");
if (fOut.fail())
return false;
fOut << to_string(pinId);
return true;
}
}
int main()
{
Gpio::openPin(17);
Gpio::setPinDirection(17, Gpio::OUT)
Gpio::setPinValue(17, Gpio::ON);
}
The key point is this: without the for(;;) loop that stat's the file, the execution fails, and we can see the permissions change on the file within 100ms.
From a kernel perspective, the 'value' files for each GPIO pin that has been exported are created with mode 0644 and ownership root:root. The kernel does not do anything to change this when you write to the 'direction' file.
The behavior you are describing is due to the operation of the systemd udev service. This service listens for events from the kernel about changes in device state, and applies rules accordingly.
When I tested on my own Pi, I did not experience the behavior you described - the gpio files in /sys are all owned by root:root and have mode 0644, and did not change regardless of direction. However I am running Pidora, and I could not find any udev rules in my system relating to this. I am assuming that Raspbian (or maybe some package you have added to your system) has added such rules.
I did find this thread where some suggested rules are mentioned. In particular this rule which would have the effect you describe:
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio; chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio; chmod -R 770 /sys/devices/virtual/gpio'"
You can search in /lib/udev/rules.d, /usr/lib/udev/rules.d and /etc/udev/rules.d for any files containing the text 'gpio' to confirm if you have such rules. By the way, I would be surprised if the change was triggered by changing direction on the pin, more likely by the action of exporting the pin to userspace.
The reason you need to sleep for a while after exporting the device is that until your process sleeps, the systemd service may not get a chance to run and action the rules.
The reason it is done like this, rather than just having the kernel take care of it, is to push policy implementation to userspace in order to provide maximum flexibility without overly complicating the kernel itself.
See: systemd-udevd.service man page and udev man page.

Reserving stdiin for parent process

After several days of searching it's time to ask. Environment is Ubuntu 12.04/Gnome.
I'm developing some embedded code on the ubuntu box and testing as much as I can in that environment before porting over to the embedded processor. The current routine is a real time fast fourier transform and I want to use gnuplot to display the results. So I want my test code AND gnuplot to run in the foreground at the same time and communicate via a pipe.
I did the usual popen() call and that worked except for one thing. stdin for the child (gnuplot) is still attached to the console. It is in contention with the parent process. The parent process needs to receive keystrokes to modify its behaviour. Sometimes the parent gets the keystroke and sometimes gnuplot does.
So I've tried the fork/exec path. Specifically
pid_t pg = tcgetpgrp(1); // get process group associated with stdout
cerr << "pid_t pg = " << pg << endl;
cerr << "process pid is " << getpid() << endl;
if (pipe(pipefd) == -1) {// open the pipe
cerr << "pipe failure" << endl;
exit(3);
} // if pipe
cpid = fork();
if (cpid == -1) {
cerr << "fork failure" << endl;
exit(1);
}
if (cpid == 0) { // this is the child process
if (tcsetpgrp(1, pg) == -1) { // this should set the process associated with stdin (gnuplot) with the
cerr << "tcsetgrp failed" << endl; // foreground terminal.
exit(7);
}
close(pipefd[1]); // close child's writing handle
if (pipefd[0] != STDIN_FILENO) { // this changes the file descripter of stdin back to 0
if ( dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
cerr << "dup2 error on stdin" << endl;
exit(6);
}
}
if (execl("/usr/bin/gnuplot", "gnuplot", "-background", "white", "-raise", (char *) NULL)) {
cerr << "execl failed" << endl;
exit(2);
} else // if exec
close(pipefd[0]); // close parent's reading handle
} // if cpid
// back in parent process
This fires off gnuplot as I expect it should. I can see gnuplot consuming all the resources of one core as it normally does. The problem is that no graph appears on the screen.
So my question is, how do I start a child process, totally detach it from the console so it won't get any keystrokes and get the output of gnuplot to display?

QTcp[server and socket]: can't read file sent

Good morning, I’m looking for an example about sending a file from one pc to an other with QTcpSocket. I tried to create my own code. I have an application, in which, the user will choose a file from his DD ( all types) and send it to the TcpServer, this server will then send this file to the other clients.But, I have a problem, when i choose the file and i send it, in the client’s side, i have this message: file is sending , but in the server’s side, it shows me that the file isn’t recieved with it’s totaly bytes.
Any suggestion please. This is the function for sending the file in the client’s side:
void FenClient::on_boutonEnvoyer_2_clicked()
{
QString nomFichier = lineEdit->text();
QFile file(lineEdit->text());
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << "Error, file can't be opened successfully !";
return;
}
QByteArray bytes = file.readAll();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << quint32(0);
out << nomFichier;
out << bytes;
out.device()->seek(0);
out << quint32((block.size() - sizeof(quint32)));
qDebug() << "Etat : envoi en cours...";
listeMessages->append("status : sending the file...");
socket->write(block);
}
and the server side:
void FenServeur::datarecieved()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if(socket == 0)
{
qDebug() << "no Socket!";
return;
}
forever
{
QDataStream in(socket);
if(blockSize == 0)
{
if(socket->bytesAvailable() )
{
qDebug() << "Error < sizeof(quint32))";
return;
}
in >> blockSize;
}
if(socket->bytesAvailable() < blockSize)
{
qDebug() << "data not recieved with its total bytes";
return;
}
qDebug() << "!!!!!!";
QByteArray dataOut;
QString nameFile;
in >> nameFile >> dataOut;
QFile fileOut(nameFile);
fileOut.open(QIODevice::WriteOnly);
fileOut.write(dataOut);
fileOut.close();
blockSize = 0;
}
}
void FenServeur::sendToAll(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint32) 0;
out << message;
out.device()->seek(0);
out << (quint32) (paquet.size() - sizeof(quint32));
for (int i = 0; i < clients.size(); i++)
{
clients[i]->write(paquet);
}
}
So i can't write the file that the server recieved into a new file.
Any suggestion please!! and thanks in advance
Your code is waiting for the other side, but the other side is waiting for you. Any protocol that allows both sides to wait for each other is fundamentally broken.
TCP allows the sender to wait for the receiver but does not allow the receiver to wait for the sender. This makes sense because not allowing the sender to wait for the receiver requires an unlimited amount of buffering. Thus for any application layered on top of TCP, the receiver may not wait for the sender.
But you do:
if(socket->bytesAvailable() < blockSize)
{
qDebug() << "data not recieved with its total bytes";
return;
}
Here, you are waiting for the sender to make progress (bytesAvailable to increase) before you are willing to receive (pull data from the socket). But the sender is waiting for you to make progress before it is willing to send more data. This causes a deadlock. Don't do this.
Receive as much data as you can, as soon as you can, whenever you can. Never insist on receiving more data over the network before you will pull already received data from the network stack.

Resources