...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