I'm writing a kernel module for Linux v3.2 to control an external laser, but I'm having trouble communicating signals through the RS232 serial port on the machine.
There seems to be a serial driver already compiled in my kernel holding ownership to the ioport addresses I want to access:
# cat /proc/ioports | grep serial
02e8-02ef : serial
02f8-02ff : serial
03f8-03ff : serial
This makes sense since Linux allows userspace programs to use the /dev/ttyS*
device nodes to communicate via the serial ports. For example, here's how I setup the device for an LCD panel:
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
...
/* Initialization and configuration */
const char *const lcd_dev = "/dev/ttyS1";
int lcd_dev_fd = open(lcd_dev, O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(lcd_dev_fd, F_SETFL, 0);
struct termios options;
tcgetattr(lcd_dev_fd, &options);
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
options.c_oflag &= ~OPOST;
tcsetattr(lcd_dev_fd, TCSANOW, &options);
...
/* sending bytes */
const unsigned char scls[] = {0xFE, 'X', 0xFE, 75, 0xFE, 84, 0xFE, 'H'};
write(lcd_dev_fd, scls, sizeof(scls);
However, this is a userspace interface and thus incompatible with my kernelspace module. I need a way to produce the same effect (RS232 serial I/O) but from within kernelspace.
Although I can unload the default Linux serial driver and replace it with my own custom RS232 driver, I don't want to reinvent the wheel here -- the default Linux serial driver appears to support the functionality I require.
Is there a simple way to communicate via the RS232 serial ports in kernelspace (perhaps through this default Linux serial driver), or do I just have to program my own custom RS232 driver?
ioctl()
, then the rest can live in userland. – Peter