Re: [linux-uvc-devel] Acer Usb Camera 5986:055a recognized but no /dev/video0 entry
Linux UVC driver and tools
Brought to you by:
pinchartl
From: Henrik I. <hen...@av...> - 2015-12-09 13:07:06
|
Hi again Inspired by Arno's tracing activities, I decided to look deeper into this device as well. Below is my understanding of what's wrong. Attached is a diff with a lot of new uvc_trace() added, just to print out as much info I could get my hands on. Functionally it's the same that I posted previously. Command to get below results: sudo modprobe quirks=4096 trace=0xffff Note: Until a few days ago I knew nothing about linux kernel code or device drivers. If you're in the same position, take the below with caution. If you're capable of contradicting or adding to the below, I very much welcome that. *Basics* Linux has a standard way of doing doubly linked lists called `struct list_head`. You can read about it here: http://www.makelinux.net/ldd3/chp-11-sect-5 *Relevant uvcvideo driver basics* A UVC device will internally consist of multiple "entities". The entities form a "chain", through which (video) data flows. And endpoint in the chain is a "terminal": input terminal, output terminal or streaming terminal. (The Acer camera is a streaming terminal.) Non-enpoint entities are called "units". Code comment explains this in more detail as: /* ------------------------------------------------------------------------ * UVC device scan */ /* * Scan the UVC descriptors to locate a chain starting at an Output Terminal * and containing the following units: * * - one or more Output Terminals (USB Streaming or Display) * - zero or one Processing Unit * - zero, one or more single-input Selector Units * - zero or one multiple-input Selector Units, provided all inputs are * connected to input terminals * - zero, one or mode single-input Extension Units * - one or more Input Terminals (Camera, External or USB Streaming) * * The terminal and units must match on of the following structures: * * ITT_*(0) -> +---------+ +---------+ +---------+ -> TT_STREAMING(0) * ... | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} | ... * ITT_*(n) -> +---------+ +---------+ +---------+ -> TT_STREAMING(n) * * +---------+ +---------+ -> OTT_*(0) * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} | ... * +---------+ +---------+ -> OTT_*(n) * * The Processing Unit and Extension Units can be in any order. Additional * Extension Units connected to the main chain as single-unit branches are * also supported. Single-input Selector Units are ignored. */ The latter structure is the one this Acer camera is trying to provide. The call stack for the code we're looking into is below. uvc_probe() is the first function to create a UVC-specific data structure (struct uvc_device) out of the general usb_* arguments given to it: uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) uvc_scan_device(struct uvc_device) for each(dev->entities) if (output terminal) uvc_scan_chain() while ( entity != NULL ) uvc_scan_chain_entity() uvc_scan_chain_forward() uvc_scan_chain_backward() The struct uvc_device contains a struct list_head called entities (dev->entities). This contains a list of uvc_entity structs, which are the entities of the UVC device. The purpose of the above code path is to discover these entities, their types (and functionality related to each type) and to store them in another list_head in the order that they from a chain (entity->chain, if there are many chains, they are found under dev->chains). *Observations* At the start of uvc_scan_device(), the list dev->entities contains 4 entities: [ 108.931880] uvcvideo: Just to see what's there, scan the list backward (prev) first. [ 108.931882] uvcvideo: id=4 type=6 (0x0006) name=Extension 4 prev=ffff8800a971b800 this=ffff8800a971e800 next=ffff88006f7f7508. [ 108.931884] uvcvideo: id=3 type=33025 (0x8101) name=Output 3 prev=ffff8800a971bc00 this=ffff8800a971b800 next=ffff8800a971e800. [ 108.931886] uvcvideo: id=2 type=5 (0x0005) name=Processing 2 prev=ffff8800a971a800 this=ffff8800a971bc00 next=ffff8800a971b800. [ 108.931888] uvcvideo: id=1 type=513 (0x0201) name=Camera 1 prev=ffff88006f7f7508 this=ffff8800a971a800 next=ffff8800a971bc00. [ 108.931889] uvcvideo: Backward scan completed, now start again and go forward (next): [ 108.931891] uvcvideo: id=1 type=513 (0x0201) name=Camera 1 prev=ffff88006f7f7508 this=ffff8800a971a800 next=ffff8800a971bc00. [ 108.931893] uvcvideo: id=2 type=5 (0x0005) name=Processing 2 prev=ffff8800a971a800 this=ffff8800a971bc00 next=ffff8800a971b800. [ 108.931894] uvcvideo: id=3 type=33025 (0x8101) name=Output 3 prev=ffff8800a971bc00 this=ffff8800a971b800 next=ffff8800a971e800. [ 108.931896] uvcvideo: id=4 type=6 (0x0006) name=Extension 4 prev=ffff8800a971b800 this=ffff8800a971e800 next=ffff88006f7f7508. [ 108.931897] uvcvideo: End of informational scan, we now return to our normal programming... (Sorry, I had to scan list_head both directions to confirm it's really circular. I'm new to this :-) The code then proceeds to find an output terminal and trying to scan backwards from that. Each uvc_entity contains the field entity->baSourceID, which is a pointer to the previous entity in the uvc chain. The code tries to follow this until it finds the other end of a complete chain. From traces that also contain baSourceID, it's easy to see what chain structure we should end up with here: [ 108.931899] uvcvideo: uvc_scan_device() loop: id=1, type=513 (0x0201) name=Camera 1, baSourceID=0 [ 108.931901] uvcvideo: uvc_scan_device() loop: id=2, type=5 (0x0005) name=Processing 2, baSourceID=1 [ 108.931902] uvcvideo: uvc_scan_device() loop: id=3, type=257 (0x0101) name=Output 3, baSourceID=6 [ 108.931903] uvcvideo: Found OUTPUT_TERMINAL type, check if it's already part of a chain... [ 108.931904] uvcvideo: Terminal is not part of a chain, so allocate memory and init+scan a new chain... [ 108.931905] uvcvideo: Scanning UVC chain: [ 108.931909] uvcvideo: uvc_scan_chain_entity() new entity: id=3, type=257 (0x0101), name=Output 3, baSourceID=6. [ 108.931910] OT 3 [ 108.931911] uvcvideo: uvc_scan_chain_entity(): ...list_add_tail() [ 108.931913] uvcvideo: uvc_scan_chain_backward(): id=3, type=257 (0x0101), name=Output 3, baSourceID=6. [ 108.931914] uvcvideo: Found reference to unknown entity 6, but ignoring as UVC_QUIRK_IGNORE_CHAIN_ERR is set. In other words, the chain clearly is: +--------------+ | Camera 1 | | id=1 | | type=0x201 | +--------------+ | v +--------------+ | Processing 2 | | id=2 | | type=0x5 | +--------------+ | v +--------------+ | Extension 4 | | id=4 | | type=0x6 | +--------------+ +--------------+ | ??? | | id=6 | | | +--------------+ | v +--------------+ | Output 3 | | id=3 | | type=0x101 | +--------------+ We know that there should be an entity id=6, since "Output 3" is connected to it in the chain. In addition, we can speculate that there probably is an entity id=5 that we haven't seen yet, but that would be located between id=4 and id=6. The problem is that entities 5 and 6 are not present in dev->entities, so the code doesn't find them and aborts with an error. With the attached patch, the error is ignored and uvc_scan_chain() is left holding entity 3. Luckily this happens to be an output terminal, so we actually have a "working" UVC chain consisting solely of the entity "Output 3", which is returned as success to the calling code. *Next steps* My main question now is, who is populating dev->entities, and why is it incomplete? The correct fix would be to change that code so that entities 5 and 6 are correctly discovered and added to the list, before we enter the code path discussed above. Alternatively, as already has been suggested in this thread, since we seem to end up with a working device (there's an output terminal, and video comes out of it), a fix that would be welcomed by those of us stuck with this device, would be to simply ignore this error and return ok with the incomplete chain. Note also that prior to uvc_scan_chain(), we have successfully found controls in entities 1 and 2, so it seems probably that applications can successfully set things like white balance, sharpness, etc... A variation of the second alternative would be to simply connect entities 3 and 4, to get the chain 1 -> 2 -> 4 -> 3. Based on the code comment cited above, this is actually a valid chain, since we have a streaming terminal, a processing unit, an extension unit and an output unit. In other words, if we set baSourceID=4 (instead of 6) on entity 3, everything would work fine. It's just a single bit that's wrong! henrik -- hen...@av... +358-40-5697354 skype: henrik.ingo irc: hingo www.openlife.cc My LinkedIn profile: http://fi.linkedin.com/pub/henrik-ingo/3/232/8a7 |