

...making Linux just a little more fun!
Deepti R [deepti.rajappan at gmail.com]
Hello,
I have read the article of yours from http://linuxgazette.net/136/anonymous.html. I am trying to write a small driver program, i have written it, but little bit of redesigning is needed. So it would be great anyone of you can help me.. i am posting my question below ..
I wrote a simple keyboard driver program, which detects the control k (CTRL + K) sequence [I have written the code to manipulate only ctrl + k]. I also have a simple application program which does a normal multiplication function.
I need to invoke that application program from my driver when I press ctrl + k in my keyboard [once I press the ctrl + k, driver will send a SIGUSR1 signal to my application program. That will accept the signal and perform multiplication]. I could do that if I hardcode the pid of application progam [pid of a.out fille] in driver. Ie, inside the function kill_proc(5385, SIGUSR1, 0), the first parameter is the pid of application program. But this is not a correct method, every time I need to compile the application program open the driver add the pid to it, compile it using Makefile then insert the .ko file, it doesn't look good. I tried using -1 as the first parameter for kill_proc () [to send the SIGNAL to all the process that are listening], since my application program is also listening to the SIGNAL, ideally it should catch the SIGUSR1 signal and execute It, but it's not working* 1/4.
Can you suggest any method to send the SIGUSR1 signal from my driver [which is in kernal spcae] to application program [which is in userspace]?
Having an entry of pid to /proc also i can achieve this, but that is not a
good design.
, Can it be implemented through ioctl?
I am pasting my codes below...
Driver code
-------- --------- --------
#define KERNEL SYSCALLS
#include <linux/ctype.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <asm/system.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/consolemap.h>
#include <linux/vt_kern.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/version.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <asm/signal.h>
#include <linux/file.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#define LCTRL 0x04
#define RCTRL 0x08
#define CAPS 0x40
#define CAPSDOWN 0x80
#define SCRLED 0x01
#define NUMLED 0x02
#define CAPSLED 0x04
#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos));
#define WRITABLE(f) (f->f_op && f->f_op->write)
ssize_t proc_write( struct file *filp, const char __user *buffer, unsigned
long len, void * data );
int proc_read( char *page, char **start, off_t off, int count, int *eof,
void *data );
unsigned char kmode = 0;
static void do_self(int);
static unsigned char key_map[] = {
0, 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', 127, 9,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13, 0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
''', '`', 0, '', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
0, 0, 0, 0, 0, 0, '<', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
static unsigned char shift_map[] = {
0, 27, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
'"', '~', '0', '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
0, 0, 0, 0, 0, 0, '>', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
void do_keyboard(void)
{
unsigned char scancode,x;
scancode=inb_p(0x60);
x=inb_p(0x61);
outb_p(x|0x80, 0x61);
outb_p(x&0x7f, 0x61);
outb(0x20, 0x20);
if(scancode == 0x3A)
{
kmode|=CAPS;
}
if(scancode == 0xBA)
{
kmode&=(~CAPS);
}
if(scancode == 0x1D)
{
kmode |= RCTRL;
kmode |= LCTRL;
}
if(scancode == 0x9D)
{
kmode&=(~RCTRL);
kmode&=(~LCTRL);
}
do_self(scancode);
}
static void do_self(int sc)
{
unsigned char ch;
int res;
if (kmode & (LCTRL | RCTRL))
{
ch = shift_map[sc];
}
else
ch = key_map[sc];
if (ch == 0)
return;
if (kmode & (LCTRL | RCTRL | CAPS)) /* ctrl or caps */
if ((ch >= 'a' && ch <= 'z') || (ch >= 224 && ch <= 254))
{
ch -= 32;
}
if (kmode & (LCTRL | RCTRL))
{
if (ch == 0x4b)
{
printk(KERN_INFO"detected ctrl+k n");
res = kill_proc(5853, SIGUSR1, 0);
}
}
}
static void my_irq_handler()
{
do_keyboard();
}
int init_module()
{
int result;
result = request_irq(1,(void *)my_irq_handler, IRQF_SHARED,
"L1S keyboard",(void *)(my_irq_handler));
if(result !=0)
{
printk(KERN_ALERT"Not able to allocate IRQ");
return -1;
}
else
{
printk(KERN_ALERT"Success");
return 0;
}
}
void cleanup_module()
{
free_irq(1,(void *)(my_irq_handler));
printk(KERN_ALERT"Freed IRQ");
}
Application Program
--------------- --------
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
volatile sig_atomic_t child_alive = 1;
void mysignal_handler(int signum);
void multiply (int a,int b);
int x,y;
int main (void)
{
switch (fork ())
{
case -1:
exit (3);
case 0:
if (setsid () == -1)
{
exit (4);
}
break;
default:
return 0;
}
if (signal (SIGUSR1, mysignal_handler) == SIG_IGN)
{
signal (SIGUSR1,mysignal_handler);
}
if (signal (SIGINT, mysignal_handler) == SIG_IGN)
{
signal (SIGINT,mysignal_handler);
}
while (child_alive)
{
pause();
}
return 0;
}
void multiply (int a, int b)
{
int f1=a;
int f2=b;
int r=f1*f2;
printf("\nResult of 5 * 10 = %d", r);
}
void mysignal_handler (int signum)
{
switch(signum)
{
case SIGUSR1:
multiply(5,10);
signal (signum, mysignal_handler);
break;
case SIGINT:
printf("Captured SIGINT in mysignal_handler \n");
child_alive = 0;
return;
break;
default:
return;
}
}
Makefile
------ ----
obj-m += kboard.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Thanks, Deepti