zoukankan      html  css  js  c++  java
  • 分析USB平台设备模型框架(1)

    start_kernel
        	rest_init();
    		kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
    			do_basic_setup();
    				driver_init();
    					void __init driver_init(void)
    						void __init driver_init(void)
    						{
    							/* These are the core pieces */                
    							devices_init();					 表示在/sys/devices /sys/dev  /sys/block /sys/char 文件夹
    							buses_init();                                          /sys/bus
    							classes_init();                                        /sys/class
    							firmware_init();                                       /sys/firmware
    							hypervisor_init(); 
    						
    							/* These are also core pieces, but must come after the
    							 * core core pieces.
    							 */
    							platform_bus_init();
    							system_bus_init();
    							cpu_dev_init();
    							memory_dev_init();
    						}
    
    
    
    平台总线设备驱动:
    struct bus_type platform_bus_type = {
    	.name		= "platform",
    	.dev_attrs	= platform_dev_attrs,
    	.match		= platform_match,
    	.uevent		= platform_uevent,
    	.pm		= PLATFORM_PM_OPS_PTR,
    };
    int __init platform_bus_init(void)
    {
    	int error;
    
    	early_platform_cleanup();
    
    	error = device_register(&platform_bus);
    	if (error)
    		return error;
    	error =  bus_register(&platform_bus_type);      //平台总线注冊          
    	if (error)
    		device_unregister(&platform_bus);
    	return error;
    }
    
    
    USB总线设备驱动:
    
    USB总线匹配函数
    static int usb_device_match(struct device *dev, struct device_driver *drv)
    {
    	/* devices and interfaces are handled separately */
    	if (is_usb_device(dev)) {
    
    		/* interface drivers never match devices */
    		if (!is_usb_device_driver(drv))
    			return 0;
    
    		/* TODO: Add real matching code */
    		return 1;
    
    	} else {
    		struct usb_interface *intf;
    		struct usb_driver *usb_drv;
    		const struct usb_device_id *id;
    
    		/* device drivers never match interfaces */
    		if (is_usb_device_driver(drv))
    			return 0;
    
    		intf = to_usb_interface(dev);
    		usb_drv = to_usb_driver(drv);
    
    		id = usb_match_id(intf, usb_drv->id_table);
    		if (id)
    			return 1;
    
    		id = usb_match_dynamic_id(intf, usb_drv);
    		if (id)
    			return 1;
    	}
    
    	return 0;
    }
    
    struct bus_type usb_bus_type = {
    	.name =		"usb",
    	.match =	usb_device_match,
    	.uevent =	usb_uevent,
    };
    
    static const struct file_operations usb_fops = {
    	.owner =	THIS_MODULE,
    	.open =		usb_open,
    };
    
    USB HUB驱动,因此大多数情况下,能够直接使用USB HUB设备,系统已经完毕device和driver
    static struct usb_driver hub_driver = {
    	.name =		"hub",
    	.probe =	hub_probe,
    	.disconnect =	hub_disconnect,
    	.suspend =	hub_suspend,
    	.resume =	hub_resume,
    	.reset_resume =	hub_reset_resume,
    	.pre_reset =	hub_pre_reset,
    	.post_reset =	hub_post_reset,
    	.ioctl =	hub_ioctl,
    	.id_table =	hub_id_table,
    	.supports_autosuspend =	1,
    };
    
    
    subsys_initcall(usb_init);
    	retval = bus_register(&usb_bus_type);           //USB总线注冊
    				priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);  //在/sys/bus/usb下创建devices
    				priv->drivers_kset = kset_create_and_add("drivers", NULL,&priv->subsys.kobj);  //在/sys/bus/usb下创建drivers
    				klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);        初始化devices链表
    				klist_init(&priv->klist_drivers, NULL, NULL);                                  初始化driver链表
    	retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
    	retval = usb_host_init();
    	retval = usb_major_init();                    //注冊字符设备
    				error = register_chrdev(USB_MAJOR, "usb", &usb_fops);    //cat /proc/devices 下查看  180 usb,主设备号180
    	retval = usb_register(&usbfs_driver);
    	retval = usb_devio_init();
    	retval = usbfs_init();
    	retval = usb_hub_init();   
    		usb_register(&hub_driver)   ///将hub.c里面的hub_driver增加到usb总线下的驱动链表里
    			new_driver->drvwrap.driver.bus = &usb_bus_type;    //指定增加的驱动的类型: &usb_bus_type;
    			retval = driver_register(&new_driver->drvwrap.driver);
    				ret = bus_add_driver(drv);
    					 driver_find(drv->name, drv->bus);
    					 ret = bus_add_driver(drv);
    					 	error = driver_attach(drv);
    					 		bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
    }								driver_match_device(drv, dev)   //调用总线上的match,检測驱动与设备是否匹配 	
    								driver_probe_device(drv, dev);
    									really_probe(dev, drv);
    											if (dev->bus->probe) {
    											ret = dev->bus->probe(dev);    //先使用总显得Probe
    											if (ret)
    												goto probe_failed;
    											} else if (drv->probe) {
    											ret = drv->probe(dev);         //再使用调用hub.c里面的驱动的probe函数
    											if (ret)
    												goto probe_failed;
    											}
    											
    											static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
    												hub_configure(hub, endpoint)
    														pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
    														maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
    														hub->urb = usb_alloc_urb(0, GFP_KERNEL);
    														usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
    															hub, endpoint->bInterval);
    														hub->urb->transfer_dma = hub->buffer_dma;
    														hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    														hub_activate(hub, HUB_INIT);					
    	static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);   //定义等待队列	
    																
    		khubd_task = kthread_run(hub_thread, NULL, "khubd");  //开启Hub_thread线程	
    			wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop());	 //将当前进程增加到等待队列中,进程在这里停下来了,我们须要看看那里唤醒进程					        
            
            void usb_kick_khubd(struct usb_device *hdev)
                      static void kick_khubd(struct usb_hub *hub)
                      		wake_up(&khubd_wait);	//唤醒等待进程Hub_thread
                      			hub_events();
                      				hub_port_connect_change(hub, i,portstatus, portchange);
                      					udev = usb_alloc_dev(hdev, hdev->bus, port1);   //分配一个struct usb_device
                      						choose_address(udev);  //选择usb设备地址
                      						hub_port_init	
    							                  dev_info (&udev->dev,
    									  "%s %s speed %sUSB device using %s and address %d
    ",
    									  (udev->config) ? "reset" : "new", speed, type,
    									  udev->bus->controller->driver->name, devnum);
    									  
    									  hub_set_address //将选择的地址告诉usb设备
    									  retval = usb_get_device_descriptor(udev, 8); //获得设备描写叙述符
    									  retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);  ;//再次获得设备描写叙述符
    									  
    								status = usb_new_device(udev);
    									announce_device(udev);
    										show_string(udev, "Product", udev->product);
    										show_string(udev, "Manufacturer", udev->manufacturer);
    										show_string(udev, "SerialNumber", udev->serial);
    									err = device_add(&udev->dev);
    										error = bus_add_device(dev);;//将usb设备增加到usb总线旗下的设备列表里面
    										bus_attach_device(dev);
    											ret = device_attach(dev);
    												ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);    //对全部的驱动,调用__device_attach推断设备与驱动是否匹配
    													driver_match_device(drv, dev)
    														return drv->bus->match ? drv->bus->match(dev, drv) : 1;
    													 driver_probe_device(drv, dev);
    													 	ret = really_probe(dev, drv);									
    															  drv->probe(dev);//一旦匹配的话就会调用驱动的probe函数
                      							
                      						
    	
    					
    描写叙述USB HUB 的结构体				
    struct usb_hub {
    	struct device		*intfdev;	/* the "interface" device */
    	struct usb_device	*hdev;
    	struct kref		kref;
    	struct urb		*urb;		/* for interrupt polling pipe */
    
    	/* buffer for urb ... with extra space in case of babble */
    	char			(*buffer)[8];
    	dma_addr_t		buffer_dma;	/* DMA address for buffer */
    	union {
    		struct usb_hub_status	hub;
    		struct usb_port_status	port;
    	}			*status;	/* buffer for status reports */
    	struct mutex		status_mutex;	/* for the status buffer */
    
    	int			error;		/* last reported error */
    	int			nerrors;	/* track consecutive errors */
    
    	struct list_head	event_list;	/* hubs w/data or errs ready */
    	unsigned long		event_bits[1];	/* status change bitmask */
    	unsigned long		change_bits[1];	/* ports with logical connect
    							status change */
    	unsigned long		busy_bits[1];	/* ports being reset or
    							resumed */
    #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
    #error event_bits[] is too short!
    #endif
    
    	struct usb_hub_descriptor *descriptor;	/* class descriptor */
    	struct usb_tt		tt;		/* Transaction Translator */
    
    	unsigned		mA_per_port;	/* current for each child */
    
    	unsigned		limited_power:1;
    	unsigned		quiescing:1;
    	unsigned		disconnected:1;
    
    	unsigned		has_indicators:1;
    	u8			indicator[USB_MAXCHILDREN];
    	struct delayed_work	leds;
    	struct delayed_work	init_work;
    };			
    		
    	

  • 相关阅读:
    CSP2019-S2总结
    #期望dp#洛谷 6835 [Cnoi2020]线形生物
    #树状数组,概率,离散,双指针#洛谷 6834 [Cnoi2020]梦原
    #容斥,倍数,排列组合#洛谷 2714 四元组统计
    #莫队,bitset#洛谷 3674 小清新人渣的本愿
    #贪心#洛谷 3173 [HAOI2009]巧克力
    #树链剖分,LCA#洛谷 3398 仓鼠找sugar
    #树状数组,哈希#洛谷 6687 论如何玩转 Excel 表格
    小甲鱼Python第八讲课后习题
    小甲鱼Python第七讲课后习题
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6740089.html
Copyright © 2011-2022 走看看