Android Qcom USB Driver Learning (14)

Links to the general catalog of this series of articles and introductions to each part: Android Qcom USB Driver Learning (Zero)

Knowing what dwc3 udc gadget hcd xhci is, I was almost stunned by Chatgpt, it seems to know what these functions are.

The UDC Gadget

UDC: (USB Device Controller) is used to manage and control the communication between the USB device and the host.
Gadget: Android implements adb, mtp (Media Transfer Protocol media transfer protocol), mass_storage, etc. at this layer.

The early USB only supported a single gadget device, and the usage scenario was relatively simple. Later, the composite framework was added to support gadget devices with multiple functions. The binding of multiple functions is completed in the kernel. If you need to modify it, you need to modify the kernel. , inflexible and inconvenient. The Linux3.11 version introduces usb gadget configfs based on configfs.
usb gadget configfs re-implements the composite device layer, which can configure and combine kernel functions in user space, and flexibly form USB composite devices, which greatly improves work efficiency.
system/core/rootdir/init.usb.configfs.rc

[persist.sys.usb.config]: [diag,adb]
[sys.usb.config]: [mtp,adb] 

on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb"
     write /config/usb_gadget/g1/idVendor 0x0c2e
     write /config/usb_gadget/g1/idProduct 0x0ba3
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
     write /config/usb_gadget/g1/UDC ${
    
    sys.usb.controller}
     setprop sys.usb.state ${
    
    sys.usb.config}

drivers/usb/gadget/configfs.c
drivers\usb\gadget\composite.c
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/function/f_mtp.c
USB bus-Linux kernel USB3.0 device control USB gadget configfs analysis of device composite device

gadget -> composite -> function

make_group -> function_make -> usb_get_function_instance -> alloc_inst -> mtp_alloc_inst
每个function driver创建的时候会分配一个usb_function_instance

echo  4e00000.dwc3 >  configs/usb_gadget/g1/UDC 
usb_udc_attch_driver-> udc_bind_to_driver-> configfs_composite_bind 
                                         -> usb_add_function -> function->bind -> mtp_function_bind
		

HCD-XHCI

HCD: (Host Controller Driver) is the host controller driver, which is an abstraction of the host controller hardware.
XHCI: (eXtensible Host Controller Interface) is also a host controller driver. XHIC is based on USB3.0 and is backward compatible. It integrates two roothubs, one corresponding to usb2.0 (main_hcd) and one corresponding to usb3.0 (shared_hcd )

struct xhci_hcd {
    
    
			   /* usb_hcd结构体:用于描述USB主机控制器驱动*/
				struct usb_hcd *main_hcd;
				struct usb_hcd *shared_hcd;
				/* glue to PCI and HCD framework */
				struct xhci_cap_regs __iomem *cap_regs;
				struct xhci_op_regs __iomem *op_regs;
				struct xhci_run_regs __iomem *run_regs;
				struct xhci_doorbell_array __iomem *dba;
				/* Our HCD's current interrupter register set */
				struct	xhci_intr_reg __iomem *ir_set;
		
				/* Cached register copies of read-only HC data */
				__u32		hcs_params1;
				...
		
				spinlock_t	lock;
		
				/* packed release number */
				u8		sbrn;
				u16		hci_version;
				...
				...
				...
			};

Root hub device registration (3)
drivers/usb/host/xhci-plat.c
drivers/usb/core/hcd.c
drivers/usb/host/xhci.c
drivers/usb/core/hub.c


dwc3_otg_start_host ->   dwc3_host_init -> platform_device_add(xhci) -> xhci_plat_probe

xhci->main_hcd = hcd;  
usb_add_hcd(hcd, irq, IRQF_SHARED); //roothub对应usb0
usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
	hcd->driver->start(hcd)  //hc_driver
		xhci_run(hcd)
			xhci_try_enable_msi(hcd)
				hci_setup_msix(xhci)
					xhci_irq(hcd)
					---------------------------------------------------------------------------------
				   |	xhci_handle_event(xhci)														|
				   |	case: TRB_PORT_STATUS                                                       |
				   |		handle_port_status(xhci, event);                                        |
				   |	case: TRB_TRANSFER                                                          |
				   |		handle_tx_event(xhci, &event->trans_event);                             |
				   |			usb_hcd_giveback_urb                                                |
				   |				tasklet_schedule(&bh->bh);                                      |
				   |					kick_hub_wq(hub);                                           |
				   |						queue_work(hub_wq, &hub->events)                        |
				   |							hub_event->port_event->hub_port_connect_change      |
				   |								->hub_port_connect -> usb_new_device(udev);     |
				    ----------------------------------------------------------------------------------		
	register_root_hub(hcd)
		usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE)
			usb_new_device (usb_dev)
				usb_enumerate_device(udev)
				announce_device(udev)/* 打印New USB device found*/
				device_add(&udev->dev)

DWC3

DWC3: (DesignWare USB 3.0 Controller) In the Android system, dwc3 is usually used as a USB3.0 host controller to work with the XHCI driver to control the communication between the USB3.0 device and the host. At the same time, dwc3 can also be used in conjunction with the Gadget driver to convert the linux device into a USB device and realize the communication between the device and the host.
When the dwc3 controller is initialized, the controller will be set to USB_DR_MODE_OTG mode, and the dwc3_host_init and dwc3_gadget_init functions will be called to initialize the resources required for the host mode and device mode. The controller can then dynamically switch to the host mode and device mode.

                  ->   host mode    xhci   dwc3_host_init()
dwc3 controller -
                  ->   device mode  udc    dwc3_gadget_init()

dual-role device (DRD) OTG State
enum dwc3_drd_state {
    
    
  	DRD_STATE_UNDEFINED = 0, //put controller and phy in suspend if no cable connected
							 //pm_runtime_putsync decrease usage_count
  	DRD_STATE_IDLE,	         
  	DRD_STATE_PERIPHERAL,
  	DRD_STATE_PERIPHERAL_SUSPEND,
  	DRD_STATE_HOST_IDLE,
  	DRD_STATE_HOST,
  };
dual-role usb control(DR) works on a particular mode
enum usb_dr_mode {
    
    
  	USB_DR_MODE_UNKNOWN,
  	USB_DR_MODE_HOST,
  	USB_DR_MODE_PERIPHERAL,
  	USB_DR_MODE_OTG,
  };

状态的切换通过dwc3_otg_sm_work -> dwc3_otg_start_host/dwc3_otg_start_peripheral

power/supply/qcom/qpnp-smb5.c devm_extcon_dev_register Send broadcast

static const unsigned int smblib_extcon_cable[] = {
    
    
  	EXTCON_USB,
  	EXTCON_USB_HOST,
  	EXTCON_NONE,
};

smblib_notify_device_mode
	extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
smblib_notify_usb_host
	extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);

usb/dwc3/dwc3-msm.c devm_extcon_register_notifier registers to monitor usb status changes and accept broadcasts

mdwc->extcon[idx].vbus_nb.notifier_call = dwc3_msm_vbus_notifier;
extcon_register_notifier(edev, EXTCON_USB, &mdwc->extcon[idx].vbus_nb);
extcon_register_notifier(edev, EXTCON_USB_HOST,&mdwc->extcon[idx].id_nb);
dwc3_msm_vbus_notifier(&mdwc->extcon[idx].vbus_nb,true, edev);
dwc3_msm_id_notifier(&mdwc->extcon[idx].id_nb,true, edev);

Guess you like

Origin blog.csdn.net/qq_40405527/article/details/131197540