Summary:
Kernel panic using usbdevfs for interrupt transfers (OHCI hcd)
Hi all,
I am currently trying to use usb interrupt transfers from the usb file system.
I am trying to speak to an HID device by submiting interrupt URBs at ep 1.
The less i can saw is that it does not work well...
The not-working program is the following :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <bits/signum.h> /* SIGRTMAX */
#include <signal.h>
#include <linux/usbdevice_fs.h>
unsigned char bytes[64];
typedef void (*usb_interrupt_handler) (int signum, siginfo_t * si, void* data);
static void incoming_intr(int signum, siginfo_t * si, void* data)
{
struct usbdevfs_urb *purb = (struct usbdevfs_urb *) si->si_addr;
int err = si->si_errno;
printf("Received Interrupt with ERRCODE %u, ERRCOUNT %u and POINTER %p\n",
err, purb->error_count, purb);
printf("Value %llx%llx%llx%llx%llx%llx%llx%llx\n", *(unsigned long long *) data
, *(unsigned long long *) (data + 8)
, *(unsigned long long *) (data + 16)
, *(unsigned long long *) (data + 24)
, *(unsigned long long *) (data + 32)
, *(unsigned long long *) (data + 40)
, *(unsigned long long *) (data + 48)
, *(unsigned long long *) (data + 56));
fflush(stdout);
}
struct usbdevfs_urb *pcururb;
int usb_interrupt_enable(int fd, unsigned char ep, usb_interrupt_handler h)
{
struct usbdevfs_urb *purb = malloc(sizeof(struct usbdevfs_urb));
struct sigaction act;
sigset_t sigset;
int ret;
/* zeroing buffer*/
memset(purb, 0, sizeof(struct usbdevfs_urb));
printf("urb pointer : %p\n", purb);
/*sigaction */
sigemptyset(&sigset);
act.sa_sigaction = incoming_intr;
act.sa_mask = sigset; /* null mask */
act.sa_flags = SA_SIGINFO;
sigaction(SIGRTMAX, &act, 0);
/* Ensure the endpoint address is correct */
ep |= 0x80;
/* preparing the urb */
purb->type = USBDEVFS_URB_TYPE_INTERRUPT;
purb->endpoint = ep;
purb->buffer_length = 64;
purb->buffer = (unsigned char *)bytes;
purb->flags = 0;
purb->start_frame = -1;
purb->signr = SIGRTMAX;
pcururb = purb;
ret = ioctl(fd, USBDEVFS_SUBMITURB, purb);
if (ret != 0)
fprintf(stderr, "error submitting interrupt URB at endpoint 0x%x: %s",
ep, strerror(errno));
return ret == 0;
}
int usb_interrupt_disable(int fd, unsigned char ep)
{
int ret;
ret = ioctl(fd, USBDEVFS_DISCARDURB, pcururb);
if (ret != 0)
fprintf(stderr, "error discarding interrupt URB at endpoint 0x%x: %s",
ep, strerror(errno));
return ret == 0;
}
int main(int argc, char *argv[])
{
if(argc == 2) {
int fd = open(argv[1], O_RDWR);
if(fd > 0) {
int ret;
ret = ioctl(USBDEVFS_CLAIMINTERFACE, 0);
if(ret != 0) {
long long i = 0;
usb_interrupt_enable(fd, 1, incoming_intr);
for(; i != 1; i--);
usb_interrupt_disable(fd, 1);;
ret = ioctl(USBDEVFS_RELEASEINTERFACE, 0);
}
close(fd);
return 0;
}
return 1;
} else
return 1;
}
I don't know if i am misusing the usbdevfs, but even this leads to strange behaviour:
-With an uhci host controller uhci_submit_urb() fails with EINVAL. [Tested on x86
computer ]
-With an ohci host controller i have a kernel panic with i run this program at least
2 times. [Tested on 2 x86 computers]
ksymoops 2.4.5 on i686 2.4.19-24mdkcustom. Options used
-V (default)
-k /proc/ksyms (default)
-l /proc/modules (default)
-o /lib/modules/2.4.19-24mdkcustom/ (default)
-m /boot/System.map-2.4.19-24mdkcustom (default)
Warning: You did not tell me where to find symbol information. I will
assume that the log matches the kernel and modules that are running
right now and I'll use the default options above for symbol resolution.
If the current kernel and/or modules do not match the log, you can get
more accurate output by telling me the kernel version and where to find
map, modules, ksyms etc. ksymoops -h explains the options.
Warning (find_objects): no *.o files in /lib/modules/2.4.19-24mdkcustom/kernel/. Is
/lib/modules/2.4.19-24mdkcustom/kernel/ a valid module directory?
Warning (compare_ksyms_lsmod): module ext3 is in lsmod but not in ksyms, probably no
symbols exported
Warning (map_ksym_to_module): cannot match loaded module jbd to a unique module
object. Trace may not be reliable.
*pde = 00000000
Oops: 0000
CPU: 0
EIP: 0010:[<d892ee04>] Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010246
eax: ffffffff ebx: 00000000 ecx: cea2e55c edx: 00000000
esi: cea2e55c edx: 20687469 ebp: cd2edf58 esp: cd2edf40
ds: 0018 es: 0018 ss: 0018
d257b800 d2489000 00000002 d3e35380 04000001 cd2edfc4 cd2edf98 c010a207
0000000b d257b800 cd2edfc4 c0382a60 0000000b cd2edfc4 cd2edfbc c010a39b
Call Trace: [<d892fbcd>][<c010a207>][<c010a39b>][<c010c888>]
Code: 66 8b 47 06 40 66 89 47 06 66 3b 47 04 74 40 9c 5b fa 8b 45
>>EIP; d892ee04 <[usb-ohci]dl_done_list+54/110> <=====
>>eax; ffffffff <END_OF_CODE+23087b3c/????>
>>ecx; cea2e55c <_end+e66bcd0/1844d7d4>
>>esi; cea2e55c <_end+e66bcd0/1844d7d4>
>>edx; 20687469 Before first symbol
>>ebp; cd2edf58 <_end+cf2b6cc/1844d7d4>
>>esp; cd2edf40 <_end+cf2b6b4/1844d7d4>
Trace; d892fbcd <[usb-ohci]hc_interrupt+11d/170>
Trace; c010a207 <handle_IRQ_event+37/70>
Trace; c010a39b <do_IRQ+7b/c0>
Trace; c010c888 <call_do_IRQ+5/d>
Code; d892ee04 <[usb-ohci]dl_done_list+54/110>
00000000 <_EIP>:
Code; d892ee04 <[usb-ohci]dl_done_list+54/110> <=====
0: 66 8b 47 06 mov 0x6(%edi),%ax <=====
Code; d892ee08 <[usb-ohci]dl_done_list+58/110>
4: 40 inc %eax
Code; d892ee09 <[usb-ohci]dl_done_list+59/110>
5: 66 89 47 06 mov %ax,0x6(%edi)
Code; d892ee0d <[usb-ohci]dl_done_list+5d/110>
9: 66 3b 47 04 cmp 0x4(%edi),%ax
Code; d892ee11 <[usb-ohci]dl_done_list+61/110>
d: 74 40 je 4f <_EIP+0x4f> d892ee53
<[usb-ohci]dl_done_list+a3/110>
Code; d892ee13 <[usb-ohci]dl_done_list+63/110>
f: 9c pushf
Code; d892ee14 <[usb-ohci]dl_done_list+64/110>
10: 5b pop %ebx
Code; d892ee15 <[usb-ohci]dl_done_list+65/110>
11: fa cli
Code; d892ee16 <[usb-ohci]dl_done_list+66/110>
12: 8b 45 00 mov 0x0(%ebp),%eax
<0>Kernel panic: Aiee, Killing interrupt handlers!
3 warnings issued. Results may not be reliable.
Kernels tested: (both with same Kernel Panic) :
-2.4.19-24mdk
-2.4.21-pre5
HID peripherals tested:
- Microsoft Corp. SideWinder PnP GamePad
- USB mouse
- Home made HID device (based on Microchip PIC16C765)
Computers:
- 1 AMD K6-2, 1 Athlon XP, 1 Athlon, 3 different USB Chipsets
- All of them running Mandrake Linux 9.0
I think this bug is perfectly reproductible by running the previous test program and
plugging an HID device.
To reproduce it:
-Build the kernel with input subsystem disabled
-rmmod hid
-run crashme /proc/bus/usb/xxx/xxx at least twice
So my questions are:
-Am i using usbdevfs the wrong way?
*or* -Is this a kernel bug?
*or* - anything else?
Fabien Chevalier
French Supelec Student
-------------------------------------------------------
This SF.net email is sponsored by: Etnus, makers of TotalView, The debugger
for complex code. Debugging C/C++ programs can leave you feeling lost and
disoriented. TotalView can help you find your way. Available on major UNIX
and Linux platforms. Try it free. www.etnus.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-users