I want to use serial port in kernel space, I have found some code which was in user space, I tried to convert the codes to work in kernel space...
This is my code
#include <linux/termios.h>
#include <linux/unistd.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
struct file * fp;
...
struct termios termAttr;
struct sigaction saio;
oldfs = get_fs();
set_fs(KERNEL_DS);
fp = filp_open("/dev/ttymxc0", O_RDWR | O_NOCTTY | O_NDELAY,0);
if(fp == NULL)
printk(KERN_ALERT "Serial openning error!!.\n");
else{
saio.sa_handler = signal_handler_IO;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fp, F_SETFL, O_NDELAY|FASYNC);
fcntl(fp, F_SETOWN, THIS_MODULE);
tcgetattr(fp,&termAttr);
cfsetispeed(&termAttr,B115200);
cfsetospeed(&termAttr,B115200);
termAttr.c_cflag &= ~PARENB;
termAttr.c_cflag &= ~CSTOPB;
termAttr.c_cflag &= ~CSIZE;
termAttr.c_cflag |= CS8;
termAttr.c_cflag |= (CLOCAL | CREAD);
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST;
tcsetattr(fp,TCSANOW,&termAttr);
printk(KERN_ALERT "Serial configured....\n");
vfs_write(fp, "HI",2, NULL);
filp_close(fp, NULL);
set_fs(oldfs);
}
while compiling, I got following errors:
note: each undeclared identifier is reported only once for each function it appears in
error: implicit declaration of function 'sigaction' [-Werror=implicit-function-declaration]
sigaction(SIGIO,&saio,NULL);
^
error: implicit declaration of function 'fcntl' [-Werror=implicit-function-declaration]
fcntl(fp, F_SETFL, O_NDELAY|FASYNC);
^
error: implicit declaration of function 'tcgetattr' [-Werror=implicit-function-declaration]
tcgetattr(fp,&termAttr);
^
error: implicit declaration of function 'cfsetispeed' [-Werror=implicit-function-declaration]
cfsetispeed(&termAttr,B115200);
^
error: implicit declaration of function 'cfsetospeed' [-Werror=implicit-function-declaration]
cfsetospeed(&termAttr,B115200);
^
error: implicit declaration of function 'tcsetattr' [-Werror=implicit-function-declaration]
I am cross compiling this driver and I already compiled Linux source, I have searched for this functions in my Linux source code but I did not find any of this functions! what should I use instead of this functions?
Edit 1:
I have changed my code into this:
//serial
struct ktermios termAttr;
struct sigaction saio;
loff_t pos =0;
struct tty_struct *tty;
serialfp = file_open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY,0);
if(serialfp == NULL)
printk(KERN_ALERT "ARIO RMG Serial openning error!!.\n");
else{
tty = (struct tty_struct *)serialfp->private_data;
tty_termios_encode_baud_rate(&tty->termios,B115200,B115200 );
printk(KERN_ALERT "ARIO RMG Serial configured....\n");
pos = serialfp->f_pos;
file_write(serialfp, "\n\n\n\n\nThis is first test of sending serial data from kernel module\n\n\n\n\n",70,&pos);
serialfp->f_pos=pos;
serial_thread_condition = 1;
mutex_init(&serial_mutex);
task1 = kthread_create(&thread_function, (void *)&pid1, "pradeep");
wake_up_process(task1);
printk(KERN_ALERT "data received:%s\n\n\n\n\n\n\n\n",rmg_drvstruct[0].RxSerial);
}
I am able to send data into serial port now, I also created a thread to read data from serial port. with following code:
static int thread_function(void *data){
loff_t pos;
while(serial_thread_condition){
mutex_lock(&serial_mutex);
if (IS_ERR(serialfp)) {
mutex_unlock(&serial_mutex);
serial_thread_condition=0;
return 0;
}
pos = serialfp->f_pos;
printk(KERN_INFO "try to read from serial\r\n");
if(file_read(serialfp, rmg_drvstruct[0].RxSerial, 100, &pos)>0)
{
printk(KERN_INFO "Data: %s\r\n", rmg_drvstruct[0].RxSerial);
serialfp->f_pos = pos;
serial_thread_condition = 0;
mutex_unlock(&serial_mutex);
break;
}
mutex_unlock(&serial_mutex);
}
}
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
But I got nothing in serial port in my thread, I wanted to use interrupts for new received bytes, but irq_request()
function makes kernel panic and computer freezes out, so what should I do to properly receive data with interrupt or a thread?