通訊管理機所用usb網卡、AX88772B、 smsc95xx
D:\z_linux_picohood_project\board-support\linux-4.4.x-mainline\drivers\net\usb\asix_devices.c
static const struct driver_info ax88772b_info = { .description = "ASIX AX88772B USB 2.0 Ethernet", .bind = ax88772_bind, .unbind = ax88772_unbind, .status = asix_status, .link_reset = ax88772_link_reset, .reset = ax88772_reset, .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET, .rx_fixup = asix_rx_fixup_common, .tx_fixup = asix_tx_fixup, .data = FLAG_EEPROM_MAC, };
static const struct usb_device_id products [] = { { // ASIX AX88772B 10/100 USB_DEVICE (0x0b95, 0x772b), .driver_info = (unsigned long) &ax88772b_info, },
一、網卡驅動asix注冊
static struct usb_driver asix_driver = { .name = DRIVER_NAME, .id_table = products, .probe = usbnet_probe, .suspend = usbnet_suspend, .resume = usbnet_resume, .disconnect = usbnet_disconnect, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, }; module_usb_driver(asix_driver);
二、分析 module_usb_driver(asix_driver)
#define module_usb_driver(__usb_driver) module_driver(__usb_driver, usb_register, usb_deregister)
#define usb_register(driver) usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
module_usb_driver函數,回調usb_register,usb_register最終會調用 usb_register_driver 函數來進行usb驅動注冊
三、分析 module_usb_driver(asix_driver)
int usb_register_driver(struct usb_driver *new_driver, struct module *owner, const char *mod_name) { int retval = 0; if (usb_disabled()) return -ENODEV; new_driver->drvwrap.for_devices = 0; new_driver->drvwrap.driver.name = new_driver->name; new_driver->drvwrap.driver.bus = &usb_bus_type; new_driver->drvwrap.driver.probe = usb_probe_interface; new_driver->drvwrap.driver.remove = usb_unbind_interface; new_driver->drvwrap.driver.owner = owner; new_driver->drvwrap.driver.mod_name = mod_name; spin_lock_init(&new_driver->dynids.lock); INIT_LIST_HEAD(&new_driver->dynids.list); retval = driver_register(&new_driver->drvwrap.driver); .......... .......... }
usb_register_driver是一個驅動框架函數,driver_register函數最終會調用&usb_bus_type總線里的匹配函數
struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, }; 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 if (is_usb_interface(dev)) { 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; }
如果 usb_device_match匹配成功,則會調用最頂層的
asix_driver的probe函數
int usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
struct usbnet *dev; struct net_device *net; struct usb_host_interface *interface; struct driver_info *info; struct usb_device *xdev; int status; const char *name; struct usbnet *dev11; struct usb_driver *driver = to_usb_driver(udev->dev.driver); 。。。。 。。。。 xdev = interface_to_usbdev (udev); interface = udev->cur_altsetting; status = -ENOMEM; // set up our own records net = alloc_etherdev(sizeof(*dev)); ////////////////////////////////////////////// 插入自己修改網卡比編號的代碼 ////////////////////////////////////////////// status = register_netdev (net); netif_info(dev, probe, dev->net, "register '%s' at usb-%s-%s, %s, %pM\n", udev->dev.driver->name, xdev->bus->bus_name, xdev->devpath, dev->driver_info->description, net->dev_addr); 。。。。。。。。。。。
四、修改網卡編號的代碼
if(!strcmp("musb-hdrc.0.auto",xdev->bus->bus_name)) { if(!strcmp ("1.5",xdev->devpath)) { /*eth0 */ //dev_change_name(net,"eth50"); //strcpy (net->name, "eth0"); strcpy (net->name, "eth1"); } if(!strcmp ("1.1",xdev->devpath)) { /*eth2 */ //dev_change_name(net,"eth52"); //strcpy (net->name, "eth2"); strcpy (net->name, "eth0"); } } else if(!strcmp ("musb-hdrc.1.auto",xdev->bus->bus_name)) { if(!strcmp ("1.5",xdev->devpath)) { /*eth1 */ //dev_change_name(net,"eth51"); //strcpy (net->name, "eth1"); strcpy (net->name, "eth3"); } if(!strcmp ("1.1",xdev->devpath)) { /*eth3 */ //dev_change_name(net,"eth53"); //strcpy (net->name, "eth3"); strcpy (net->name, "eth2"); } }
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)