Hi, two basic questions: -- how can one test a usb port to find what bandwidth is available before opening a webcam stream? -- how to clean up when a usb v4l1 webcam device is disconnected while open for streaming video? Thanks for any pointers to the answers.. Duncan On 23-Nov-2002 Mark McClelland wrote: > Duncan Haldane wrote: > >>On 18-Nov-2002 Mark McClelland wrote: >> >> >>>Duncan Haldane wrote: >>> >>> >If two cameras are registered, one on /dev/video0 and one on /dev/video1, >>> >and I use e.g. xawtv or gqcam to monitor them, I cannot open /dev/video1 >>> >when /dev/video0 is open and vice-versa. This happens for two cpia >>> >devices and one cpia + one ov511 device. >>> >>>That's because both cameras are trying to use nearly all of the USB's >>>bandwidth. Or, more precisely, each is trying to schedule an ISO packet >>> I've now consulted the available CPiA developer's guide and see that the CPiA chip allows 4 alt settings of the USB interface with MaxPacketSizes= {0,448,704,960} for alt={0,1,2,3}. The current cpia_usb driver only allowed alt=0 (non-streaming) and alt=3 (streaming) states. I verified that two cameras on the same usb hub can work together if both use alt=2, at about 8fps. On different hubs, both work with alt=3 with a larger fps. I've added an alt setting to the device structure so it can be set on a per-camera basis. The packetsize is only set by v4l function cpia_usb_open() Ideally the driver would find out from the usb port what bandwidth was available so it could choose an appropriate alt setting 1,2,3 (or even 0) when starting. I guess I would like to make the alt setting user-switchable though the /proc/cpia/video<n> interface that can control the cpia driver so the camera would start in some safe alt setting, and this could then be increased by the user if the bandwidth became available. (e.g. by disconnecting or reducing the bandwidth use of other cameras) Clearly this needs some way for the driver to test what alt setiing is currently safe. Any suggestion? >> >>Yes, this seems correct: I have now traced the problem to disruption of >>communication of commands to/from the cpia cam (ReadPacket() in cpia_usb.c/ >>cpia_usb_transferCmd()). This eventually causes de/re-registration of >>the camera, leaving a frozen viewer window that needs a reboot to clear >>it.... (incomplete cleanup ?) -- nasty. >> >>At the very least I would hope to prevent hanging that requires a reboot!. >> >> > > Agreed. I'm not sure why that happens, but I suspect the cpia driver is > at fault since lots of drivers have no problem with random disconnects. Hmmm. this seems to occur because the usb hub.c decided /dev/video<n> is dead: this bit of code in hub.c issues a warning message about "EMI" (possible electromagnetic interference) when it tries to renable the port: --------------snipped from usb/hub.c----------------------------- else if (portchange & USB_PORT_STAT_C_ENABLE) { dbg("port %d enable change, status %x", i + 1,portstatus); usb_clear_port_feature(dev, i + 1,USB_PORT_FEAT_C_ENABLE); /* * EM interference sometimes causes bad shielded USB devices to * be shutdown by the hub, this hack enables them again. * Works at least with mouse driver. */ if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { err("already running port %i disabled by hub(EMI?),re-enabling...", i +1); usb_hub_port_connect_change(hub, i,portstatus, portchange); } } ------------------------------------------------------------- but the hanging problem also occurs if I simply yank the usb cable out of the port when the camera is running. The v4l application is gqcam-0.9 with a small patch. but i guess xawtv would also do it. (BTW, the v4l app "camstream" stopped working with ov511 webcams with its last release, and the author couldnt track this down. Has Mark looked at this?) The cpia driver skips some cleanups if it detects that the disconnected camera has an open_count > 0. But if I try running an **ov511** camera and again disconnect the usb cable while it's running I also get a similar frozen gqcam which can't be killed and doesnt let the module be rmmod'ed. (this was ov511 v1.50 for Linux 2.4.18) AARGH: need to reboot from a console to clear it (X hangs if I just logout with the hung gqcam) , and various file systems are unmounted while busy, so lots of fscking at reboot.... So this doesnt seem to be cpia-specific... Is this a problem of the v4l app (e.g. gqcam) or the camera driver? Do _any_ v4l1 apps behave correctly (i.e. close down gracefully if the usb /dev/video<n> to which they are attached gets shut down?) Or should the v4l usb driver be doing something more to shut down an open camera that has been disconnected? This is what the cpia driver does: ----------------cpia.c------------------------- void cpia_unregister_camera(struct cam_data *cam) { if (!cam->open_count) { DBG("unregistering video\n"); video_unregister_device(&cam->vdev); } else { LOG("/dev/video%d removed while open, " "deferring video_unregister_device\n", cam->vdev.minor); DBG("camera open -- setting ops to NULL\n"); cam->ops = NULL; } #ifdef CONFIG_PROC_FS DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor); destroy_proc_cpia_cam(cam); #endif if (!cam->open_count) { DBG("freeing camera\n"); kfree(cam); } } --------------------------------------------------- > It's possibly something to do with the synchronous calls (eg. > usb_control_msg()) being active when disconnect() gets called. There's > no solution to that currently, other than to use the async calls (ie. > usb_submit_urb()) and implement the necessary locking yourself. I'd also > check all of the codepaths that handle signals (eg. interrupted > syscalls), and check for function returns that don't drop all held > locks. I looked it over briefly, and nothing jumps out at me. > > If you can't find anything, put a ton of printks in disconnect() and > close() and see where it hangs :) > > <snip> > >>>Check the descriptors. As long as there's an alternate setting where >>>MxPS <= 1023 / 2 then you should be in business. You can either have the Hmm.alt=2, MxPS=704 = 1408/2 > 512 works! >>>packet size or alternate number be a module param, or you can do a >>>"cams" thing like ov511. Or, you can allow the frame rate to be set >>>somewhere, and have the driver automatically choose the minimum possible >>>packet size that can still sustain that frame rate. >>> >>> > My idea about auto-adjusting the alternate setting based on the > framerate is probably too difficult for a driver this complex, since > features like compression make it difficult to know the minimum > necessary bandwidth. I recommend doing what ov511 does instead (allow > user to input the number of cameras in /proc or as a module param, > determine a packet size based on that, and set the corresponding > alternate setting in cpia_usb_open()). I'll try to go with /proc input. But I want to get the camera to determine the maximum safe alt MaxPacketSize setting to start with when it first is opened. How can I do this? I also have to work out how to close the camera and reopen it with a different alt setting, but I guess this should be relatively obvious using cpia_usb_close() (change alt setting for camera) cpia_usb_open()? The disconnect-while-camera-is-open=>needs-reboot problem seems the most disturbing one, though.... Duncan