I was looking at catching a signal using usbfs to tell when a device has been 
detached.
I used an ioctl call with USBDEVFS_DISCSIGNAL to set a signal handler, and I 
was able to detect the detachment.
>From inode.c (drivers/usb/core/inode.c) file in kernel source I concluded that 
>disc_signal.context is copied
into si_addr field of siginfo_t structure, but when signal handler was called 
(when I remove USB device)
I'm always get NULL in info->si_addr (it is not value that I put into 
disc_signal.context field).

I'm using the code below to catch the signal

static void usb_disconnect_handler(int signo, siginfo_t *info, void *ignored)
{
        if(signo == SIGRTMIN+1) {
                printf("USB device disconnected (%x)\n", info->si_addr);
        }
}

static int register_disconnect_signal_handler(void)
{
        struct sigaction new_action,old_action;

        /* Set up the structure to specify the new action. */
        new_action.sa_sigaction = usb_disconnect_handler;
        new_action.sa_flags = SA_SIGINFO;
        
        sigaction (SIGRTMIN+1, NULL, &old_action);
        if (old_action.sa_handler != SIG_IGN) {
                sigaction (SIGRTMIN+1, &new_action, NULL);
                return 0;
        }

        return -1;
}

..... and later ....

        struct usbdevfs_disconnectsignal disc_signal;

        disc_signal.signr = SIGRTMIN+1;
        disc_signal.context = (void*) a5a5a5a5a5;

        ret = ioctl(usbdev->fd, USBDEVFS_DISCSIGNAL, &disc_signal);
        if (ret < 0) {
                printf("could not register disc signal %s\n", strerror(errno));
                return ret;
        }

        ret = register_disconnect_signal_handler();
        if(ret < 0)
                return ret;


After analyzing real-time signal handling in kernel (kernel/signal.c) I 
modified function usbfs_remove_device in
drivers/usb/core/inode.c file at line 699.

static void usbfs_remove_device(struct usb_device *dev)
{
        .
        .
        .
        if (ds->discsignr) {
                sinfo.si_signo = ds->discsignr; /* SIGPIPE replaced with 
ds->discsignr */
                sinfo.si_errno = EPIPE;
                sinfo.si_code = SI_ASYNCIO;
                sinfo.si_addr = ds->disccontext;
                kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, 
ds->disc_uid, ds->disc_euid);
        }
        .
        .
}

Into field si_signo of siginfo_t structure instead of SIGPIPE I put 
ds->discsignr value.

After this change in kernel source I was able to get correct value (equal to 
disc_signal.context) in si_addr field in signal handler.
Kernel version is 2.6.16-1.2115_FC4. I check latest kernel stable version 
2.6.17.1 and it has same code in inode.c file.

Is this a bug in usb device removal signal generating or I something missed in 
signal handler registering.

Zoran Marceta

----



_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to