usbnet驱动深入分析-usb虚拟网卡host端

来源:互联网 发布:刻录软件nero免费下载 编辑:程序博客网 时间:2024/05/22 13:27

1、驱动流程:

 

2、明确probe函数的功能:

probe有usb core 经枚举过程,匹配 id_table ,识别到驱动,并调用probe来初始化一些信息。

如 dev->driver_info = info 只是取得注册时的一些信息,用于一些比较特殊的设备,如bind 与收发与普通的网卡不同时,增加或减少一些配置。

主要做了:

 skb_queue_head_init (&dev->rxq);
 skb_queue_head_init (&dev->txq);
 skb_queue_head_init (&dev->done);

/*tasklet 软中断初始化,数据接收发送关键函数*/

 dev->bh.func = usbnet_bh;
 dev->bh.data = (unsigned long) dev;

/*初始化关键队列,通过usbnet_defer_kevent 设置USB数据传输过程错误,并设置标志,调用schedule_work,提交到工作队列来处理错误事件*/
 INIT_WORK (&dev->kevent, kevent);

/*内核定时器初始化,用来处理USB传输过程的一些错误,如一些CRC错误,调用mod_timer启动内核定时器*/
 dev->delay.function = usbnet_bh;
 dev->delay.data = (unsigned long) dev;
 init_timer (&dev->delay);

初始化了三个队列,分别是发送 接收 处理;

1)数据发送完成后通过 defer_bh 函数移动到 done队列,触发软中断tasklet,来处理tx_done;

2)数据接收完成后 与发送数一样 通过 defer_bh 来处理rx_done,其中调用了netif_rx来提交数据到网络层。

 net->change_mtu = usbnet_change_mtu;
 net->get_stats = usbnet_get_stats;
 net->hard_start_xmit = usbnet_start_xmit;
 net->open = usbnet_open;
 net->stop = usbnet_stop; SET_NETDEV_DEV(net, &udev->dev);/*net关联usb接口*/
 status = register_netdev (net);/*注册网络设备*/

需要注意的函数为 usbnet_start_xmit 与 usbnet_open 。

 

获取usb端点地址,有当前的配置获取bulk in out 的地址,用来收发数据,这部分过程可以参考usb-skeleton.c程序,不做详细介绍。

 

3、数据发送

其中 usbnet_start_xmit 为网卡发送函数,有上层调用send函数时,传下skb数据包。

在 usbnet_start_xmit 中,usb_alloc_urb (0, GFP_ATOMIC)分配内存---->usb_fill_bulk_urb (urb, dev->udev, dev->out,  skb->data, skb->len, tx_complete, skb) 填充urb----->usb_submit_urb (urb, GFP_ATOMIC)提交urb。

成功时__skb_queue_tail (&dev->txq, skb),在完成函数 tx_complete 函数中 会设置tx_done标志等,然后调用defer_bh来处理。

 

4、数据的接收

 

第一种可能:

这是这部分驱动中最难的一部分。接收数据关键起始点为 usbnet_open 函数,上层 通过 ifconfig usb0 up 时,open函数被调用了,open函数中 触发了软中断 tasklet_schedule();

static void usbnet_bh (unsigned long param)
{
 struct usbnet  *dev = (struct usbnet *) param;
 struct sk_buff  *skb;
 struct skb_data  *entry;

 while ((skb = skb_dequeue (&dev->done))) {
  entry = (struct skb_data *) skb->cb;
  switch (entry->state) {
  case rx_done:
   entry->state = rx_cleanup;
   rx_process (dev, skb);
   continue;
  case tx_done:
  case rx_cleanup:
   usb_free_urb (entry->urb);
   dev_kfree_skb (skb);
   continue;
  default:
   devdbg (dev, "bogus skb state %d", entry->state);
  }
 }

···

 if (netif_running (dev->net)
   && netif_device_present (dev->net)
   && !timer_pending (&dev->delay)
   && !test_bit (EVENT_RX_HALT, &dev->flags)) {
  int temp = dev->rxq.qlen;
  int qlen = RX_QLEN (dev);

  if (temp < qlen) {
   struct urb *urb;
   int  i;

   for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
    urb = usb_alloc_urb (0, GFP_ATOMIC);
    if (urb != NULL)
     rx_submit (dev, urb, GFP_ATOMIC);
   }
   if (temp != dev->rxq.qlen && netif_msg_link (dev))
    devdbg (dev, "rxqlen %d --> %d",
      temp, dev->rxq.qlen);
   if (dev->rxq.qlen < qlen)
    tasklet_schedule (&dev->bh);
  }
···

}

个人认为蓝色部分为接收提供了4个urb来接收数据(full speed),从rx_complete 中可以看出,urb 没有数据时阻塞 ,该函数未被调用,然后数据进来时,urb又有数据,又调用了rx_submit来提交数据,

 

rx_complete 函数部分代码:

···

 defer_bh(dev, skb, &dev->rxq);  /*在complete函数完成时调用tasklet_bh*/

 

if (urb) {
  if (netif_running (dev->net)
    && !test_bit (EVENT_RX_HALT, &dev->flags)) {
   rx_submit (dev, urb, GFP_ATOMIC);      /*接收数据*/        
   return;
  }
 ···

第二种可能:

 

由第一种中 tasklet_bh  蓝色部分开始接收数,由于没有数据进来提交urb时,进入default 又开始调用tasklet,形成循环。

rx_submit部分代码:

···

 switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
  case -EPIPE:
   usbnet_defer_kevent (dev, EVENT_RX_HALT);
   break;
  case -ENOMEM:
   usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
   break;
  case -ENODEV:
   if (netif_msg_ifdown (dev))
    devdbg (dev, "device gone");
   netif_device_detach (dev->net);
   break;
  default:
   if (netif_msg_rx_err (dev))
    devdbg (dev, "rx submit, %d", retval);
   tasklet_schedule (&dev->bh);
   break;
  case 0:
   __skb_queue_tail (&dev->rxq, skb);
  }

···

 

个人总结:

啃了一个礼拜终于啃完了,只是对urb的整体机制不够深入了解呀,但还是把usbnet给裁了,只支持bulk。欢迎技术交流呀!

奶奶的第一次写技术博客。不容易,希望对大家有帮助。USB驱动是个不错的东西。QQ:497067994

 

哥的处女请尊重原创!!!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 一年级小孩不听老师话怎么办 大班幼儿规则意识差怎么办 幼儿大班《打雷了怎么办》的教案 小孩上课不听讲到处乱跑怎么办 小孩子经常咬人好动怎么办 6个月宝宝好动怎么办 新生调皮被幼儿园退学怎么办 孩子在幼儿园太调皮怎么办 幼儿上课注意力不集中怎么办 幼儿上课一半要离开怎么办 八个月宝宝消化不良拉肚子怎么办 8个月的宝宝拉肚子怎么办 孕8个月拉稀怎么办 孩子调皮好动爱说话怎么办 宝宝8个月不会爬怎么办 怀孕8个月不想要了怎么办 8个月宝宝发烧怎么办 八个月的小孩发烧怎么办 孩子8个月发烧38怎么办 8个宝宝发烧38度怎么办 怀孕八个月不想要怎么办 怀孕八个月不想要了怎么办 八个月宝宝拉肚子拉水怎么办 八个月的宝宝拉肚子怎么办 八个月发烧38度怎么办 孩子特别调皮好动该怎么办 孩子有好动症该怎么办 在幼儿园好动的孩子该怎么办 18个月宝宝上火怎么办 打孩子越打上瘾怎么办 八个月不想要了怎么办 胎儿心脏畸形肺动脉瓣闭锁怎么办 小孩爱动怎么办补什么 初中孩子下午上课总犯困怎么办 孩子上课精神不集中怎么办 孩子玩兴奋了就打人怎么办 婴儿兴奋白天不睡觉怎么办 小孩读书精神不集中怎么办 小孩上课精神不集中怎么办 小孩学习精神不集中怎么办 孩子暑假天天看电视不出门怎么办