This is the first post in a series about TP-link TL-WN722N wifi adapter. it’s a cool little gadget that provides wifi over USB. This post is about usb registration from the linux driver.
Let’s dive into the deep end which is the USB driver.The usb interface would eventually register network device and cfg80211 devices for ioctl
starting with entry point in the driver
module_init(rtw_drv_entry);
module_exit(rtw_drv_halt);
rtw_drv_entry
calls usb_register
to register this driver (short and sweet).
static int __init rtw_drv_entry(void)
{
ret = usb_register(&usb_drv.usbdrv);
Note that usb_drv
is global inside that file and defined as follows:
struct rtw_usb_drv {
struct usb_driver usbdrv;
int drv_registered;
u8 hw_type;
};
struct rtw_usb_drv usb_drv = {
.usbdrv.name = (char *)DRV_NAME,
.usbdrv.probe = rtw_drv_init,
.usbdrv.disconnect = rtw_dev_remove,
.usbdrv.id_table = rtw_usb_id_tbl,
.usbdrv.suspend = rtw_suspend,
.usbdrv.resume = rtw_resume,
Well, that was easy! not so fast. This is just the registration the usb ops that USB core will call to probe the devices.
in rtw_drv_init
if (rtw_os_ndevs_init(dvobj) != _SUCCESS)
goto free_if_vir;
rtw_os_ndevs_init
is important beause it has import init methods rtw_os_ndevs_register
and rtw_os_ndevs_alloc
if (rtw_os_ndevs_alloc(dvobj) != _SUCCESS)
goto exit;
if (rtw_os_ndevs_register(dvobj) != _SUCCESS)
goto os_ndevs_free;
in rtw_os_ndevs_alloc
, there is rtw_os_ndev_alloc
called
status = rtw_os_ndev_alloc(adapter);
in rtw_os_ndev_alloc
ndev = rtw_init_netdev(adapter);
in rtw_init_netdev
, rtw_hook_if_ops
is called.
rtw_hook_if_ops(pnetdev);
in rtw_hook_if_ops
the device ops are assigned.
void rtw_hook_if_ops(struct net_device *ndev)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
ndev->netdev_ops = &rtw_netdev_ops;
#else
ndev->init = rtw_ndev_init;
ndev->uninit = rtw_ndev_uninit;
ndev->open = netdev_open;
ndev->stop = netdev_close;
ndev->hard_start_xmit = rtw_xmit_entry;
ndev->set_mac_address = rtw_net_set_mac_address;
ndev->get_stats = rtw_net_get_stats;
ndev->do_ioctl = rtw_ioctl;
#endif
}
and rtw_netdev_ops
defines the net device ops for rtw device
static const struct net_device_ops rtw_netdev_ops = {
.ndo_init = rtw_ndev_init,
.ndo_uninit = rtw_ndev_uninit,
.ndo_open = netdev_open,
.ndo_stop = netdev_close,
.ndo_start_xmit = rtw_xmit_entry,
in the second important call is rtw_os_ndevs_register
, there is rtw_os_ndev_register
called
if (rtw_os_ndev_register(adapter, name) != _SUCCESS)
in rtw_os_ndev_register
if (rtnl_lock_needed)
ret = (register_netdev(ndev) == 0) ? _SUCCESS : _FAIL;
else
ret = (register_netdevice(ndev) == 0) ? _SUCCESS : _FAIL;