10. scan the video device chain and register the video device 10.1 uvc video chain [cpp] struct uvc_video_chain {// uvc video chain struct uvc_device * dev; // uvc device struct list_head list; // uvc video chain linked list header struct list_head entities; // uvc object linked list header struct uvc_entity * processing; // process Unit entity struct uvc_entity * selector; // selector Unit entity struct mutex ctrl_mutex;/* Protects ctrl.info */}; 10.2 uvc scan device [cpp] static int uvc_scan_device (struct uvc_device * dev) {struct uvc_video_chai N * chain; // uvc video chain struct uvc_entity * term; // uvc entity list_for_each_entry (term, & dev-> entities, list) {// traverse global entity linked list if (! UVC_ENTITY_IS_OTERM (term) // obtain the Output Terminal object continue in the object linked list; if (term-> chain. next | term-> chain. prev) // The video chain has been added to the uvc video chain. chain = kzarloc (sizeof (* chain), GFP_KERNEL ); // allocate the uvc video chain memory. (if (chain = NULL) return-ENOMEM; INIT_LIST_HEAD (& chain-> entities ); // initialize the video chain entities linked list mutex_init (& chain-> ctrl_mutex); chain-> dev = dev; // bind the uvc video chain and the uvc device if (uvc_scan_chain (c Hain, term) <0) {// scan uvc video chains (process all related input pins) kfree (chain); continue;} uvc_trace (UVC_TRACE_PROBE, "Found a valid video chain (% s ). \ n ", uvc_print_chain (chain); list_add_tail (& chain-> list, & dev-> chains ); // uvc video chain linked list added to uvc device} if (list_empty (& dev-> chains) {uvc_printk (KERN_INFO, "No valid video chain found. \ n "); return-1;} return 0;} 10.3 uvc scan video chain [cpp] static int uvc_scan_chain (struct uvc_video_ch Ain * chain, struct uvc_entity * term) {struct uvc_entity * entity, * prev; uvc_trace (UVC_TRACE_PROBE, "Scanning UVC chain:"); entity = term; // obtain the object prev = NULL; // The previous object while (entity! = NULL) {/* Entity must not be part of an existing chain */if (entity-> chain. next | entity-> chain. prev) {// you have added uvc_trace (UVC_TRACE_DESCR, "Found reference to entity % d already in chain to the uvc video chain. \ n ", entity-> id); return-EINVAL;}/* Process entity */if (uvc_scan_chain_entity (chain, entity) <0) // scan the current object return-EINVAL;/* Forward scan */if (uvc_scan_chain_forward (chain, entity, prev) <0 )// Return-EINVAL;/* Backward scan */prev = entity; // The current object is the first entity in the next while loop if (uvc_scan_chain_backward (chain, & entity) <0) // scan the object return-EINVAL;} return 0 ;} add the input entity of the uvc video chain to the entities linked list of the uvc video chain to add the uvc video chain to the chains linked list of the uvc device 10.3.1 scan the current object [cpp] static int uvc_scan_chain_entity (struct uvc_video_chain * chain, struct uvc_entity * entity) {switch (UVC_ENTITY_TYPE (entity) {case UVC_VC_EXTENSION_UNI T: // extended Unit if (uvc_trace_param & UVC_TRACE_PROBE) printk ("<-XU % d", entity-> id); if (entity-> bNrInPins! = 1) {uvc_trace (UVC_TRACE_DESCR, "Extension unit % d has more than 1 input pin. \ n ", entity-> id); return-1;} break; case UVC_VC_PROCESSING_UNIT: // process Unit if (uvc_trace_param & UVC_TRACE_PROBE) printk (" <-PU % d ", entity-> id); if (chain-> processing! = NULL) {uvc_trace (UVC_TRACE_DESCR, "Found multiple Processing Units in chain. \ n "); return-1;} chain-> processing = entity; // if it is a processing Unit, set it as the break object of the uvc video chain; case UVC_VC_SELECTOR_UNIT: // selector Unit if (uvc_trace_param & UVC_TRACE_PROBE) printk ("<-SU % d", entity-> id);/* Single-input selector units are ignored. */if (entity-> bNrInPins = 1) break; if (chain-> selector! = NULL) {uvc_trace (UVC_TRACE_DESCR, "Found multiple Selector Units in chain. \ n "); return-1;} chain-> selector = entity; // if it is a selector Unit, set it as the selector object break of the uvc video chain; case UVC_ITT_VENDOR_SPECIFIC: // Special case UVC_ITT_CAMERA: // enter Terminal camera case UVC_ITT_MEDIA_TRANSPORT_INPUT: // enter Terminal Media transport if (uvc_trace_param & UVC_TRACE_PROBE) printk ("<-IT % d \ n ", entity-> id); break; case UVC_TT_S TREAMING: // enter Terminal stream if (UVC_ENTITY_IS_ITERM (entity) {if (uvc_trace_param & UVC_TRACE_PROBE) printk ("<-IT % d \ n", entity-> id );} else {if (uvc_trace_param & UVC_TRACE_PROBE) printk ("OT % d", entity-> id);} break; default: uvc_trace (UVC_TRACE_DESCR, "Unsupported entity type 0x % 04x found in chain. \ n ", UVC_ENTITY_TYPE (entity); return-1;} list_add_tail (& entity-> chain, & chain-> entities); // Return 0;} 10.3.2 scan forward object [cpp] static int uvc_scan_chain_forward (struct uvc_video_chain * chain, struct uvc_entity * entity, struct uvc_entity * prev) {struct uvc_entity * forward; int found;/* Forward scan */forward = NULL; found = 0; while (1) {// obtain the object before it. Therefore, the object is processed until the previous object forward = NULL jumps out of the endless loop forward = uvc_entity_by_reference (chain-> dev, entity-> id, forward ); // obtain the previous object if (forward = N ULL) break; if (forward = prev) continue; switch (UVC_ENTITY_TYPE (forward) {case UVC_VC_EXTENSION_UNIT: // extended Unit if (forward-> bNrInPins! = 1) {uvc_trace (UVC_TRACE_DESCR, "Extension unit % d has more than 1 input pin. \ n ", entity-> id); return-EINVAL;} list_add_tail (& forward-> chain, & chain-> entities ); // Add the uvc entity to the entities of the uvc video chain if (uvc_trace_param & UVC_TRACE_PROBE) {if (! Found) printk ("(->"); printk ("XU % d", forward-> id); found = 1 ;}break; case UVC_OTT_VENDOR_SPECIFIC: // vendor Special case UVC_OTT_DISPLAY: // output Termianl display case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: // Output Terminal media transport case UVC_TT_STREAMING: // Output Terminal stream if (UVC_ENTITY_IS_ITERM (forward )) {uvc_trace (UVC_TRACE_DESCR, "Unsupported input terminal % u. \ n ", forward-> id); return-EINVAL;} list_ad D_tail (& forward-> chain, & chain-> entities); // Add the uvc entity to the entities of the uvc video chain if (uvc_trace_param & UVC_TRACE_PROBE) {if (! Found) printk ("(->"); printk ("OT % d", forward-> id); found = 1 ;}break ;}} if (found) printk (")"); return 0;} 10.3.3 backward scan the entity [cpp] static int uvc_scan_chain_backward (struct uvc_video_chain * chain, struct uvc_entity ** _ entity) {struct uvc_entity * entity = * _ entity; struct uvc_entity * term; int id =-EINVAL, I; switch (UVC_ENTITY_TYPE (entity) {case UVC_VC_EXTENSION_UNIT: // extended Unit case UVC_VC_PROC ESSING_UNIT: // The number of Terminal inputs processed by the processing Unit can only be 1 id = entity-> baSourceID [0]; // obtain the ID break of the Input pin (Unit/Terminal; case UVC_VC_SELECTOR_UNIT: // selector object/* Single-input selector units are ignored. */if (entity-> bNrInPins = 1) {// if the number of input pin is 1 id = entity-> baSourceID [0]; // obtain the ID break of the input in (Unit/Terminal);} if (uvc_trace_param & UVC_TRACE_PROBE) printk ("<-IT"); chain-> selector = entity; // The selector object of the uvc video chain refers To uvc entity for (I = 0; I <entity-> bNrInPins; ++ I) {// total number of input pin id = entity-> baSourceID [I]; // obtain the ID term = uvc_entity_by_id (chain-> dev, id) of the input in (Unit/Terminal ); // obtain the corresponding Input pin object if (term = NULL |! UVC_ENTITY_IS_ITERM (term) {uvc_trace (UVC_TRACE_DESCR, "Selector unit % d input % d isn't connected to an input terminal \ n", entity-> id, I ); return-1;} if (uvc_trace_param & UVC_TRACE_PROBE) printk ("% d", term-> id); list_add_tail (& term-> chain, & chain-> entities ); // Add the uvc object to the uvc video chain entities linked list uvc_scan_chain_forward (chain, term, entity); // scan the object forward} if (uvc_trace_param & UVC_TRACE_PROBE) printk ("\ n "); Id = 0; break; case when: case UVC_ITT_CAMERA: case when: case UVC_OTT_DISPLAY: case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: case UVC_TT_STREAMING: id = UVC_ENTITY_IS_OTERM (entity )? Entity-> baSourceID [0]: 0; break;} if (id <= 0) {* _ entity = NULL; return id;} entity = uvc_entity_by_id (chain-> dev, id); if (entity = NULL) {uvc_trace (UVC_TRACE_DESCR, "Found reference to unknown entity % d. \ n ", id); return-EINVAL;} * _ entity = entity; return 0;} notice that a [cpp] uvcvideo: Scanning UVC chain is displayed in the trace printed statement: OT 2 <-XU 5 <-XU 4 <-PU 3 <-IT 1 shows how these units and Terminal are built.