RS232 serial port communication in kernelspace - linux-kernel

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?

Take a look at line disciplines. You can use it to attach a tty device to some read and write routines defined in kernelspace and thus write a driver using a serial line. The line discipline gets attached to it from user space and the kernel will do all the rest.
A good example is slcan (drivers/net/can/slcan.c). Examples for the libc calls handling this can be found in can-utils (https://gitorious.org/linux-can/can-utils). If you prefer working by book chapter 18 of Linux Device Drivers will give a good first step: http://www.makelinux.net/ldd3/chp-18, though the book is not very up to date. Some details may also be found at http://www.linusakesson.net/programming/tty/.

Related

Windows Driver substitue for linux device driver sysfs interface

Let me describe what sysfs does : its a pseudo file system where files, directories are generated by the core kernel or kernel drivers. And these files have read/write access and are a mechanism to control certain kernel level parameters by user space (seperate from ioctls and file operations).
Sysfs from Kernel.org
Sysfs from Wikipedia
The following is an example of how userspace interacts with sysfs.
$ cat /sys/modules/mydriver/foo_count
1
$ echo "2" > /sys/modules/mydriver/foo_count $ cat /sys/modules/mydriver/foo_count
2
The cat command will trigger a read via the show_foo_count() kernel routine, while the echo will trigger a write via the store_foo_count() routine
The following is how the kernel driver/module might intercept the user space activity.
static ssize_t show_foo_count(struct kobject *kobj,struct kobj_attribute *attr,
char *buf)
{
/* This will perform a read operation and contents of buf will be updated*/
...
}
static ssize_t store_foo_count(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf,size_t len)
{
/* Contents are read from buf and stored within the driver's context/state */
...
}
A good example is here
How can one achieve the same sysfs usage on windows drivers ?
I see the following windows concepts, but I am unable to map them to be the equivalent of syfs :
A. Device Objects
B. File Object

Linux serial port console input, framebuffer console output

I have an embedded Linux system (i.e just Busybox) with a framebuffer (/dev/fb0) and a serial port (/dev/hvc0).
The serial port is the only method of console input currently.
My Kernel has;
CONFIG_FB=y
CONFIG_FB_SIMPLE=y
CONFIG_VGA_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
My bootargs are currently;
bootargs = "console=hvc0 earlycon=sbi debug";
What I would like to do is use the frame-buffer to display the console output (login terminal, printk output), but with input coming from the serial port (/dev/hvc0).
Can you be more specific regarding the Hw and the OS and u-boot?
You need something like this:
setenv bootargs console=ttyO2,115200n8 vram=16M root=/dev/ram0 rw ramdisk_size=16384 initrd=0x83000000,16M rootfstype=ext2
or this:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk2p1 rootwait rw video=mxcfb0:dev=hdmi,1920x1080M#60,if=RGB24'
You see, you need to specify the tty = serial port configuration (speed, parity and so on). Also the type of file system ext2, ext4, ... the above are just examples and you need to base yours according to your system.

macOS blocking serial I/O

I'm writing a tool as part of a test suite, which needs to talk over a serial port to some hardware so that the code being tested sees the environment change.
So, I do this:
open("/dev/tty.usbmodem14141", O_RDWR | O_NOCTTY);
only it hangs there. If I replace that call with
open("/dev/tty.usbmodem14141", O_RDWR | O_NOCTTY | O_NONBLOCK);
then it works -- but I would prefer not to have to fiddle with select() and friends, or write a busy-loop poll, just so I can read from the serial port; that's what blocking I/O is for.
Do I need to do anything special for this to work?
When you have opened the serial terminal in nonblocking mode, you can then clear the file status flag to perform I/O in blocking mode.
To clear the nonblocking status flag you can use fcntl(), e.g.:
int flags;
flags = fcntl(fd, F_GETFL);
flags &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
Since the Linux version of F_SETFL can change only the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags, common practice is to simplify the code down to just
fcntl(fd, F_SETFL, 0);
(Yes, the single-liner does not have the same degree of portability as advocated in Setting Terminal Modes Properly.)

Finding the address of /bin/bash for buffer overflow attack

I am trying out ret-to-libc attacks and use the following piece of code to get the address of environment variable /bin/bash
#include <unistd.h>
int main(void)
{
printf("bash address: 0x%lx\n", getenv("SHELL"));
return 0;
}
when i use gdb's x command to check if the address returned by this code is correct it shows up correctly the first time.But when some other program is executed this address changes automatically.What should i do to keep this environment variable's address constant? I am using this address for buffer overflow, but since it keeps changing with every run, the attack is never successful. Any suggestions?
You have to disable the ASLR for the address to not change.
echo 0 | tee /proc/sys/kernel/randomize_va_space

Profiling the memory used by linux kernel

I have linux kernel 2.6.30 on an ARM based embedded device.
I have to do some kernel memory usage profiling on the device.
I am thinking of monitoring the ps output on various kernel threads and modules while I carry out actions like wifi on/off etc.
Can you suggest me:
Which threads I need to monitor? How to monitor the kernel module memory usage?
sometimes it is useful to get the real info straight from the kernel, I have used this little C program I threw together to get real system info in an output format that is suited for the shell (it compiles down to a pretty small binary if that matters) --
#include <sys/sysinfo.h>
int main(int argc, char **argv){
struct sysinfo info;
sysinfo(&info);
printf( "UPTIME_SECONDS=%d\n"
"LOAD_1MIN=%d\n"
"LOAD_5MIN=%d\n"
"LOAD_15MIN=%d\n"
"RAM_TOT=%d\n"
"RAM_FREE=%d\n"
"MEMUSEDKB=%d\n"
"RAM_SHARED=%d\n"
"RAM_BUFFERS=%d\n"
"SWAP_TOT=%d\n"
"SWAP_FREE=%d\n"
"PROCESSES=%d\n",
info.uptime,
info.loads[0],
info.loads[1],
info.loads[2],
info.totalram,
info.freeram,
(info.totalram-info.freeram)*info.mem_unit/1024,
info.sharedram,
info.bufferram,
info.totalswap,
info.freeswap,
info.procs);
}
I use it in the shell like this:
eval `sysinfo`
BEFORERAM=$MEMUSEDKB
command &
sleep .1 #sleep value may need to be adjusted depending on command's run time
eval `sysinfo`
AFTERRAM=$MEMUSEDKB
echo RAMDELTA is $(($AFTERRAM - BEFORERAM ))

Resources