What I want to achieve: I want to set custom baud rate values for some tty*-like UART-mapped terminals.
How: The only way I found by far is to use the struct termios2 structure which is located in<asm/termios> header (as mentioned here, first answer).
My solution works very well by far, but now I need to use some functions:
speed_t cfgetispeed(const struct termios *);
int tcdrain(int);
int tcflow(int, int);
int tcflush(int, int);
int tcgetattr(int, struct termios *);
pid_t tcgetsid(int);
int tcsendbreak(int, int);
int tcsetattr(int, int, struct termios *);
The problem is that in <asm/termios.h> there are no such functions, and I need to include <termios.h> for being able to use them.
Problem: If I include both headers (<asm/termios.h> and <termios.h>) the compiler will scream about functions and structure re-declaration, and he's right.
How can I solve this without using some obscure practice (like wrapping one of headers in a namespace, like mentioned here)?
How can I solve this without using some obscure practice (like wrapping one of headers in a namespace, like mentioned here)?
If you find namespaces obscure, I don't know how you'd call this:
#define termios asmtermios
#include <asm/termios.h>
#undef termios
#include <termios.h>
Anyway, this too gets you rid of the error: redefinition of 'struct termios'.
I had a similar issue - wanted custom baud rate support with definitions like termios2, TCGETS2 and BOTHER, while still making use of the traditional termios calls. I instinctively wrapped the termios2 stuff in its own compilation unit and had no problems. So my structure looks like this:
serial_driver.c/.h
#include <termios.h>
#include <fcntl.h>
#include <dirent.h>
int open_port(int fd, int baudrate, eParitySetting parity, int numStopBits)
{
if(baudrate_is_non_standard(baudrate)
setNonStandardBaudRateTermios(fd, baudrate, parity, numStopBits);
else
//all the normal tcgetattr/cfsetospeed/tcsetattr
}
int do_other_things(void)
{
//all the normal tcsendbreak/tcflush/etc things
}
serial_driver_abr.c/.h
#include <asm/termios.h> /* asm gives us the all important BOTHER and TCGETS2 */
#include <fcntl.h>
#include <dirent.h>
#include <stropts.h> /* Oddly, for ioctl, because ioctl.h causes include dramas */
setNonStandardBaudRateTermios(int fd, int baudrate, eParitySetting parity, int numStopBits)
{
//All the termios2/ioctl/TCGETS2/BOTHER things
}
Works well for me.
I hit the same problem with an old arm cross compiler, but found the latest one, gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf, solved the problem with a different header file. Here is my code:
[uart_config.c]
#include <asm/termbits.h>
#include <sys/ioctl.h>
/* functions */
int uart_config_baudrate(int fd)
{
struct termios2 tio;
ioctl(fd, TCGETS2, &tio);
tio.c_cflag &= ~CBAUD;
tio.c_cflag |= BOTHER;
tio.c_ispeed = MY_SPECIAL_BAUDRATE_NUMBER;
tio.c_ospeed = MY_SPECIAL_BAUDRATE_NUMBER;
return ioctl(fd, TCSETS2, &tio);
}
[main.c]
static int init_uart(void)
{
struct termios tp;
int rc;
memset(&tp, 0, sizeof(tp));
tp.c_cflag = MY_SPECIAL_BAUDRATE | CS8 | CLOCAL | CREAD | PARENB | PARODD;
tp.c_iflag = IGNPAR;
tp.c_oflag = 0;
tp.c_lflag = 0; /* set input mode to non-canonical */
tp.c_cc[VTIME] = 0; /* inter-character timer unused */
tp.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
tcflush(fd, TCIFLUSH);
rc = tcsetattr(fd, TCSANOW, &tp);
return rc;
}
int main()
{
int fd;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
init_uart(fd); // add your error handling
uart_config_baudrate(fd); // add your error handling
...
}
I don't think any of these answer address the issue correctly (they are rather hacky). The sources of glibc gives you a good idea on how to implement those functions quite easily:
For exemple tcdrain is a simple ioctl call:
ioctl (fd, TCSBRK, 1)
Related
I'm developing a control c++ library that needs to expose controller::open() function. However inside this function I have to call to the POSIX::open() function to open a file descriptor. The compiler complains I send Invalid Arguments to the controller function and doesn't understand I would like to call to the POSIX open() file function.
This is my code:
class declaration:
class PosixReadController {
int open();
}
implementation:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
int PosixReadController::open()
{
int fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyf1 - ");
}
else
fcntl(fd, F_SETFL, 0);
return fd;
}
Error message (eclipse):
Invalid Arguments: 'Candidates are: int open()'
Changing the call to open to the global namespace with ::open doesn't help. Because I see the library already contains open function and I get the following error:
Invalid Arguments: 'Candidates are: int open(const char*, int, ...)
ImageCtrl* open(image) ''
Any idea?
Invalid Arguments: 'Candidates are: int open(char*, int, ...)
This is extremely suspicious. From where did you get this declaration of open? Did you include <fcntl.h>?
The prototype should actually look like this:
int open(const char *, int, ...);
const char * would have matched the string literal you passed, but char * obviously does not because a string literal is not writable.
I'm making a c++ serial class in Linux. I'm trying to register an event when incoming data is received.
I'm working on a Olimex Lime2 board.
gcc version 4.6.3 (Debian 4.6.3-14)
This is the error i get when trying to compile.
conSerial.cpp: In function ‘void signal_handler_IO(int)’:
conSerial.cpp:15:6: error: ‘EventHandler’ was not declared in this scope
I think this means that it doesn't have access to the class. Perhaps I've gone about this the wrong way. Any advice would be appreciated.
Thank you,
Steve
Header File
#ifndef CONSERIAL_H_
#define CONSERIAL_H_
#include "termios.h"
#include <sys/signal.h>
class conSerialEvents
{
public:
virtual void onReceive();
};
class conSerial
{
public:
conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_);
conSerial(const char *port_, termios *options_);
int open_port(void);
int send(const char *s, size_t len);
void close_port( void );
private:
conSerialEvents *EventHandler;
static const int PORT_OPEN = 0;
termios *options;
const char *port;
int fd;
struct sigaction saio;
};
#endif
Class File
#include <stdio.h> //Standard input/output definitions
#include <string.h> //String function definitions
#include <unistd.h> //UNIX standard function definitions
#include <fcntl.h> //File control definitions
#include <errno.h> //Error number definitions
#include <termios.h> //POSIX terminal control definitions
#include <iostream> //Input-Output Streams
#include "conSerial.h" //Header for this file
using namespace std;
void signal_handler_IO (int status);
void signal_handler_IO (int status)
{
std::cout << "Signal" << std::endl;
//This section fails because it can't see the class I think.
if (EventHandler)
{
EventHandler->onReceive();
}
//End this section
}
conSerial::conSerial(const char *port_, termios *options_)
{
this->EventHandler = 0L;
const char *port;
termios *options;
fd = -1;
}
conSerial::conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_)
{
this->EventHandler = EventHandler_;
const char *port;
termios *options;
fd = -1;
}
int conSerial::open_port(void){
struct termios options;
fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1){
//Could not open the port.
std::cout << "Port Failed to Open";
}else{
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
saio.sa_flags = 0;
saio.sa_flags = SA_NODEFER;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, FNDELAY); // Sets the read() function to return NOW and not wait for data to enter buffer if there isn't anything there.
//Configure port for 8N1 transmission
tcgetattr(fd, &options); //Gets the current options for the port
cfsetispeed(&options, B38400); //Sets the Input Baud Rate
cfsetospeed(&options, B38400); //Sets the Output Baud Rate
options.c_cflag |= (CLOCAL | CREAD); //? all these set options for 8N1 serial operations
options.c_cflag |= PARENB; //?
options.c_cflag &= ~CSTOPB; //?
options.c_cflag &= ~CSIZE; //?
options.c_cflag |= CS7; //?
tcsetattr(fd, TCSANOW, &options); //Set the new options for the port "NOW"
std::cout << "seems like everything is ok, keep going\n";
};
return (fd);
};
int conSerial::send(const char *s, size_t len){
int written;
written = 0;
if (fd==-1){ //
// If this is -1 it means that the port is not open.
std::cout << "The port is not open." << std::endl;
}else{
// The port is open
tcdrain(fd);
written = write(fd, s, len);
}
return written;
}
void conSerial::close_port( void ){
if (fd !=-1){
close(fd);
}
}
In your "Class File", you declared a function:
void signal_handler_IO (int status)
which refers to some object called "EventHandler".
No such object is declared anywhere, hence the compilation error. It's as simple as that.
It is true that you declared a class named "conSerial", which happens to have a class member called "EventHandler".
However, that's a class right there. And a class member. The fact that you have some class that happens to declare a class member of the same name makes absolutely no difference, whatsoever. C++ doesn't work this way. signal_handler_IO is not a method in the same class. It is not even a static class function in that class. To access a class member you need one of two things: either an instance of a class, somewhere, in order to access its member; or access it from a non-static method in the same class, which automatically access the corresponding member of whatever class instance whose method it is. That's how C++ works.
And that's the fundamental explanation for your compilation error.
It is true that in a different class method called "open_port", you take a pointer to this signal_handler_IO function, and install it as a signal handler for SIGIO. Again, that doesn't really change anything.
It appears that you intend your conSerial class to be a singleton. In that case, the cleanest solution for your conundrum is:
Refactor the class so that it's construction and destruction uses the singleton design pattern, as much as possible.
Install the signal handler in the class's constructor, and uninstall the signal handler in its destructor.
Have the constructor save a pointer to this in a private static class member, before installing the signal handler.
Move the bulk of signal_handler_IO into a static class method, and have signal_handler_IO do nothing except invoke the static class method.
Have you static class method use the pointer that was set up in step 3 access the actual instance of your singleton class. Now, it can do whatever it wants to do with its "EventHandler" class member.
I'm currently working on I2C between a Raspberry Pi 3 and a PsoC 4. I'm using the I2C-dev library to handle the I2C communication. So the I2C bus is up and running, and the read and write function has been implemented correctly. I want however to make functions pointer the read and write functions hence the to functions uses the same types of arguments (atleast it looks like) I have the following main code called I
2Ctest-tools.cpp:
#include <unistd.h> //Needed for I2C port
#include <fcntl.h> //Needed for I2C port
#include <sys/ioctl.h> //Needed for I2C port
#include <linux/i2c-dev.h> //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"
int main() {
int addr = 0x49;
int cmd = 2; //Write
int length = 5;
int file_i2c = 0;
I2C myI2C;
unsigned char buffer[5];
buffer[0] = 0x01;
buffer[1] = 0x02;
buffer[2] = 0x20;
buffer[3] = 0x00;
buffer[4] = 0x17;
i2c_init(&myI2C, cmd, addr, &file_i2c);
i2c_exe(&myI2C, file_i2c, buffer, length);
return 0;
}
As shown in the code, im using a object of the struct called myI2C which is passed in the two functions i2c_init, i2c_exe. The source code for functions.cpp is in the following:
#include <unistd.h> //Needed for I2C port
#include <fcntl.h> //Needed for I2C port
#include <sys/ioctl.h> //Needed for I2C port
#include <linux/i2c-dev.h> //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"
int i2c_init(I2C *cthis, int cmd, int addr, int *ptrFile_i2c ) {
char *filename = (char*)"/dev/i2c-1";
if ((*ptrFile_i2c = open(filename, O_RDWR)) < 0)
{
//ERROR HANDLING: you can check errno to see what went wrong
printf("Failed to open the i2c bus");
return 0;
}
if (ioctl(*ptrFile_i2c, I2C_SLAVE, addr) < 0)
{
printf("Failed to acquire bus access and/or talk to slave.\n");
//ERROR HANDLING; you can check errno to see what went wrong
return 0;
}
switch(cmd) {
case 1:
//cthis->WR = write;
break;
case 2:
cthis->WR = read;
break;
}
return 0;
}
int i2c_exe(I2C *cthis, int file_i2c, unsigned char *buffer, size_t length) {
cthis->WR(file_i2c, buffer, length);
return 0;
}
So the important thing to note here is that in the function i2c_init im switching on the varialbe cmd, which dictates whether the function pointer will point on the write or read function. Now the failure part comes in. The functions pointer is declared in its own .h file called i2c.h and looks like this:
struct I2C {
ssize_t (*WR)(int, const void *, size_t);
};
As you can see the function pointer has to point on a function with the parameters (int, const void*, size_t) this works like a charm when the function points on the write function BUT when it points on the read function im getting and error, the error says:
functions.cpp: In function ‘int i2c_init(I2C*, int, int, int*)’:
functions.cpp:30:14: error: invalid conversion from ‘ssize_t ()(int, void, size_t) {aka int ()(int, void, unsigned int)}’ to ‘ssize_t ()(int, const void, size_t) {aka int ()(int, const void, unsigned int)}’ [-fpermissive]
cthis->WR = read;
I have studied the error and concluded that it's because the read and write function somehow does not take the same arguments, which is weird because im passing the same arguments in them (int i2s_file, int buffer, int length) so if i change the function pointer to
ssize_t (*WR)(int, void *, size_t);
the function works with read but not with write.. So my question is: can i somehow change the write or read function to take the same argument by changing the i2c-dev library or is there anything else i could do to solve this problem?
here's a link to the i2c-dev library, which i have completely giving up to understand http://textuploader.com/5yioi
thanks in advanced
You can cast the functions explicitly to the correct type:
typedef ssize_t (*I2CCMD)(int, void *, size_t);
cthis->WR = (I2CCMD)write;
cthis->WR = (I2CCMD)read;
This should eliminate the error.
Obviously the read function cannot take a pointer to const since, unlike the write function, it has to modify that parameter.
So you cannot switch functionality with a function pointer, because the function pointers are of different types.
The best work-arounds seem to be either moving the "cmd" parameter to the i2c_exe function, or alternatively create a private variable containing cmd (inside struct I2C would be ideal). And then in i2c_exe either call read or write.
A worse solution is to change the struct to a union, like:
union I2C {
ssize_t (*WR)(int, const void *, size_t);
ssize_t (*read)(int, void*, size_t);
};
Then in case of reads, use the read member to assign to the struct. But please note that this is kind of a "dirty hack", it is poorly-specified behavior in theory. In practice, it will most likely work on any given system. (It is very unlikely that const correctness would ever affect calling convention.)
I want to call a user space program from a kernel module periodically.But the kernel program is freezing the system, while I try to load it.
following is the program,
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/delay.h>
#define TIME_PERIOD 50000
static struct hrtimer hr_timer;
static ktime_t ktime_period_ns;
static enum hrtimer_restart timer_callback(struct hrtimer *timer){
char userprog[] = "test.sh";
char *argv[] = {userprog, "2", NULL };
char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
printk("\n Timer is running");
hrtimer_forward_now(&hr_timer, ktime_period_ns);
printk("callmodule: %s\n", userprog);
call_usermodehelper(userprog, argv, envp, UMH_WAIT_PROC);
return HRTIMER_RESTART;
}
static int __init timer_init() {
ktime_period_ns= ktime_set( 0, TIME_PERIOD);
hrtimer_init ( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
hr_timer.function = timer_callback;
hrtimer_start( &hr_timer, ktime_period_ns, HRTIMER_MODE_REL );
return 0;
}
static int __exit timer_exit(){
int cancelled = hrtimer_cancel(&hr_timer);
if (cancelled)
printk(KERN_ERR "Timer is still running\n");
else
printk(KERN_ERR "Timer is cancelled\n");
}
module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");
test.sh is a script which just echoes a comment.
I have tested the call_usermodehelper part and timer part individually and it is working fine. But while I am combining the two codes, the system hangs.
Can anybody please help me to solve the problem.
Quick look around strongly suggests that hrtimer callbacks are executed from an irq context, which is expected - how else are you going to get high resoluton?
But this also means you must no block, while your callback can block due to call_usermodehelper regardless of NOWAIT passed.
So it seems you are testing your module on a kernel with debugging disabled, which is fundamentally wrong.
But this is less relevant as the thing you are trying to achieve in the first place looks fundamentally wrong.
I can only recommend you elaborate what is the actual problem. There is absolutely now way that forking + execing has anything to do with something requiring a high resolution timer.
I am currently trying to communicate with a device using CAN. To do so I am using PCAN Basic using C++.
Unfortunately, I know nothing about accessing a function inside a dll file (which is what is provided). I found this link:
Calling a dll function from C++
and am trying to use LoadLibrary via code I found here:
http://www.goffconcepts.com/techarticles/development/cpp/calldll.html
My Code:
// dll_get_func.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h> /* For sqrt() */
#include <windows.h>
#define DELCLDIR __declspec("Pcan_usb.dll")
#define PCAN_USBBUS1 0x51
#define CAN_BAUD_1M 0x0014 // 1 MBit/s
#define MSGTYPE_STANDARD 0x00
typedef struct {
DWORD ID; // 11/29 bit identifier
BYTE MSGTYPE; // Bits from MSGTYPE_*
BYTE LEN; // Data Length Code of the Msg (0..8)
BYTE DATA[8]; // Data 0 .. 7
} TPCANMsg;
int hardCodeInit(void)
{
/* get handle to dll */
HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));
/* get pointer to the function in the dll*/
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Init");
/*
Define the Function in the DLL for reuse. This is just prototyping the dll's function.
A mock of it. Use "stdcall" for maximum compatibility.
*/
typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, int CANMsgType);
pICFUNC CAN_Init;
CAN_Init = pICFUNC(lpfnGetProcessID);
//DWORD __stdcall CAN_Init(WORD wBTR0BTR1, int CANMsgType);
/* The actual call to the function contained in the dll */
int intMyReturnVal = CAN_Init(PCAN_USBBUS1,CAN_BAUD_1M);
/* Release the Dll */
FreeLibrary(hGetProcIDDLL);
/* The return val from the dll */
return intMyReturnVal;
}
int hardCodeWrite(void)
{
HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Write");
typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, TPCANMsg CANMsgType);
pICFUNC CAN_Write;
CAN_Write = pICFUNC(lpfnGetProcessID);
TPCANMsg msgOut;
msgOut.MSGTYPE = MSGTYPE_STANDARD;
msgOut.LEN = 1;
msgOut.DATA[0] = 0x03; // 0x03 = Get ID
int toReturn;
toReturn = CAN_Write(PCAN_USBBUS1,msgOut);
FreeLibrary(hGetProcIDDLL);
return toReturn;
}
int _tmain(int argc, _TCHAR* argv[])
{
int derp=hardCodeInit();
int herp=hardCodeWrite();
std::cout<<derp;
std::cout<<herp;
_getch();
return 0;
}
However, Visual Studio says that there is a:
Unhandled exception at 0x10001D95 (Pcan_usb.dll) in dll_get_func.exe: 0xC0000005:
Access violation reading location 0x00000051.
I have Pcan_usb.dll and Pcan_usb.lib in the same folder and I am using visual studio 2012.
There are several points here. Signature of the LoadLibrary:
HMODULE WINAPI LoadLibrary(_In_ LPCTSTR lpFileName);
Remove unneeded casts. This will simplify reading and understanding your code.
FARPROC lpfnGetProcessID - the name of the variable is confusing. This might be a source of confusion or misunderstanding.
Regarding the AV - the signature of the CAN_Init function as you are trying to use it is wrong. From your post it is hard to tell for sure what is should be. Look into manual (if possible), header file, etc.
Main point - you should not release the library. There are rare cases when this is needed. Most likely your case does not need this. It is very difficult to believe that you need to reload the library (and this what happens when you call FreeLibrary/LoadLibrary!) between initing it and writing.
Access violation reading location 0x00000051.
This tells me the function is treating PCAN_USBBUS1 as a pointer. Perhaps:
#define PCAN_USBBUS1 0x51
should be changed to
WORD pcan_usbbus1 = 0x51;
And the call to CAN_Init should be changed to:
int intMyReturnVal = CAN_Init(&pcan_usbbus1, CAN_BAUD_1M);
The function signature should probably be something like:
typedef int (__stdcall * pICFUNC)(WORD* wBTR0BTR1, int CANMsgType);
^ pointer here
I imagine CAN_BAUD_1M might also need to be changed in the same way but maybe not.