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