usb转百兆修改usb0为eth1

usb转百兆网模块一般采用ax88772

在内核中配置添加该模块:

make menuconfig

使用/搜索

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmPzsvqf-1662347013762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220829094952473.png)]
回车之后,按5选择8817

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhEjPZ8p-1662347013763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220829095026775.png)]
输入?可以看到该驱动支持88系列的usb转百兆芯片,然后将其使能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOF0DAFb-1662347013763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220829095136933.png)]
我们还需要将Simple USB Network Links 使能,该驱动为通用usb转网口驱动
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4EEGYeIF-1662347013763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220829095309872.png)]
然后保存,编译内核烧写到板子里面

正常插入模块打印信息:

usb 1-1.1: new high-speed USB device number 4 using ci_hdrc ,
asix 1-1.1:1.0 eth1: register 'asix' at usb-ci_hdrc.1-1.1, 
ASIX AX88772B USB 2.0 Ethernet, 00:0e:c6:87:72:01,IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready

使用的是AX88772的驱动,识别到了eth1,但是还有一种情况,使用cdc驱动,识别成了usb0
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZakPIuxx-1662347013764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220829095719900.png)]
那么,如果我们还是想用eth1这个名字的话,可以从驱动里面做一些修改

进入对应目录搜索用到的驱动

zero@ubuntu:~/linux-4.1.15/drivers/net/usb$ ls -l *.o

用到了cdc_ether.c驱动,可以看里面的driver结构体,里面用到了usbnet_probe,该函数在usbnet.c里面

static struct usb_driver cdc_driver = {

  .name =   "cdc_ether",
  .id_table = products,
  .probe =   usbnet_probe,
  .disconnect =  usbnet_disconnect,
  .suspend =  usbnet_suspend,
  .resume =  usbnet_resume,
  .reset_resume = usbnet_resume,
  .supports_autosuspend = 1,
  .disable_hub_initiated_lpm = 1,

};

可以到probe函数里面有很多代码,我们不做详细解读,只关注名字相关代码,往下看

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 usb_driver  *driver = to_usb_driver(udev->dev.driver);


  /* usbnet already took usb runtime pm, so have to enable the feature
   \* for usb interface, otherwise usb_autopm_get_interface may return
   \* failure if RUNTIME_PM is enabled.
   */

  if (!driver->supports_autosuspend) {
   	 driver->supports_autosuspend = 1;
 	 pm_runtime_enable(&udev->dev);
  }

  name = udev->dev.driver->name;
  info = (struct driver_info *) prod->driver_info;
  if (!info) {
    dev_dbg (&udev->dev, "blacklisted by %s\n", name);
    return -ENODEV;
  }

  xdev = interface_to_usbdev (udev);
  interface = udev->cur_altsetting;

  status = -ENOMEM;

  // set up our own records
  net = alloc_etherdev(sizeof(*dev));
  if (!net)
  goto out;

  /* netdev_printk() needs this so do it as early as possible */
  SET_NETDEV_DEV(net, &udev->dev);

  dev = netdev_priv(net);
  dev->udev = xdev;
  dev->intf = udev;
  dev->driver_info = info;
  dev->driver_name = name;
  dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
  | NETIF_MSG_PROBE | NETIF_MSG_LINK);
  init_waitqueue_head(&dev->wait);
  skb_queue_head_init (&dev->rxq);
  skb_queue_head_init (&dev->txq);
  skb_queue_head_init (&dev->done);
  skb_queue_head_init(&dev->rxq_pause);

  dev->bh.func = usbnet_bh;
  dev->bh.data = (unsigned long) dev;
  INIT_WORK (&dev->kevent, usbnet_deferred_kevent);
  init_usb_anchor(&dev->deferred);
  dev->delay.function = usbnet_bh;
  dev->delay.data = (unsigned long) dev;
  init_timer (&dev->delay);
  mutex_init (&dev->phy_mutex);
  mutex_init(&dev->interrupt_mutex);
  dev->interrupt_count = 0;

  dev->net = net;
  strcpy (net->name, "usb%d");
  memcpy (net->dev_addr, node_id, sizeof node_id);

  /* rx and tx sides can use different message sizes;
   \* bind() should set rx_urb_size in that case.
   */
  dev->hard_mtu = net->mtu + net->hard_header_len;
\#if 0

// dma_supported() is deeply broken on almost all architectures
  // possible with some EHCI controllers
  if (dma_supported (&udev->dev, DMA_BIT_MASK(64)))
    net->features |= NETIF_F_HIGHDMA;
\#endif

  net->netdev_ops = &usbnet_netdev_ops;
  net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
  net->ethtool_ops = &usbnet_ethtool_ops;

  // allow device-specific bind/init procedures
  // NOTE net->name still not usable ...
  if (info->bind) {
    status = info->bind (dev, udev);
    if (status < 0)

      goto out1;
    
    // heuristic:  "usb%d" for links we know are two-host,
    // else "eth%d" when there's reasonable doubt.  userspace
    // can rename the link if it knows better.
    if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
      ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
       (net->dev_addr [0] & 0x02) == 0))
      strcpy (net->name, "eth%d");

   /* WLAN devices should always be named "wlan%d" */
    if ((dev->driver_info->flags & FLAG_WLAN) != 0)
      strcpy(net->name, "wlan%d");
   /* WWAN devices should always be named "wwan%d" */
    if ((dev->driver_info->flags & FLAG_WWAN) != 0)
      strcpy(net->name, "wwan%d");

    /* devices that cannot do ARP */
    if ((dev->driver_info->flags & FLAG_NOARP) != 0)
      net->flags |= IFF_NOARP;


    /* maybe the remote can't receive an Ethernet MTU */
    if (net->mtu > (dev->hard_mtu - net->hard_header_len))
      net->mtu = dev->hard_mtu - net->hard_header_len;

  } else if (!info->in || !info->out)
    status = usbnet_get_endpoints (dev, udev);
  else {
    dev->in = usb_rcvbulkpipe (xdev, info->in);
    dev->out = usb_sndbulkpipe (xdev, info->out);
    if (!(info->flags & FLAG_NO_SETINT))
      status = usb_set_interface (xdev,
        interface->desc.bInterfaceNumber,
        interface->desc.bAlternateSetting);
    else
      status = 0;

  }

  if (status >= 0 && dev->status)
    status = init_status (dev, udev);
  if (status < 0)
    goto out3;

  if (!dev->rx_urb_size)
    dev->rx_urb_size = dev->hard_mtu;
  dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);

  /* let userspace know we have a random address */
  if (ether_addr_equal(net->dev_addr, node_id))
   net->addr_assign_type = NET_ADDR_RANDOM;

  if ((dev->driver_info->flags & FLAG_WLAN) != 0)
    SET_NETDEV_DEVTYPE(net, &wlan_type);
  if ((dev->driver_info->flags & FLAG_WWAN) != 0)
   SET_NETDEV_DEVTYPE(net, &wwan_type);

  /* initialize max rx_qlen and tx_qlen */
  usbnet_update_max_qlen(dev);

  if (dev->can_dma_sg && !(info->flags & FLAG_SEND_ZLP) &&
    !(info->flags & FLAG_MULTI_PACKET)) {
    dev->padding_pkt = kzalloc(1, GFP_KERNEL);
    if (!dev->padding_pkt) {
      status = -ENOMEM;
     goto out4;
    }
  }


  status = register_netdev (net);
  if (status)
   goto out5;
  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);


  // ok, it's ready to go.
  usb_set_intfdata (udev, dev);

  netif_device_attach (net);

  if (dev->driver_info->flags & FLAG_LINK_INTR)

    usbnet_link_change(dev, 0, 0);

  return 0;

out5:

  kfree(dev->padding_pkt);

out4:

  usb_free_urb(dev->interrupt);

out3:

  if (info->unbind)

    info->unbind (dev, udev);

out1:

  free_netdev(net);

out:

  return status;

}

下面代码是有关名字的设置,

	if (info->bind) {
		status = info->bind (dev, udev);
		if (status < 0)
			goto out1;
	// heuristic:  "usb%d" for links we know are two-host,
	// else "eth%d" when there's reasonable doubt.  userspace
	// can rename the link if it knows better.
        dev->driver_info->flags=FLAG_ETHER;                //加上这一行
	if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
	    ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
	     (net->dev_addr [0] & 0x02) == 0))
		strcpy (net->name, "eth%d");
	/* WLAN devices should always be named "wlan%d" */
	if ((dev->driver_info->flags & FLAG_WLAN) != 0)
		strcpy(net->name, "wlan%d");
	/* WWAN devices should always be named "wwan%d" */
	if ((dev->driver_info->flags & FLAG_WWAN) != 0)
		strcpy(net->name, "wwan%d");

	/* devices that cannot do ARP */
	if ((dev->driver_info->flags & FLAG_NOARP) != 0)
		net->flags |= IFF_NOARP;

	/* maybe the remote can't receive an Ethernet MTU */
	if (net->mtu > (dev->hard_mtu - net->hard_header_len))
		net->mtu = dev->hard_mtu - net->hard_header_len;
}

所以需要修改net->dev_addr [0],使它不等于0x02,并且FLAG_ETHER和dev->driver_info->flags做位与运算不等于0

FLAG_ETHER=0x20

添加一些打印信息后[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oxZG13yE-1662347013764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220830161213766.png)]

发现net->dev_addr [0]是9a,2进制展开10011010,2展开是10,

10011010

00000010

=2 !=0

所以需要修改第二位为0,如:0x08,那么需要在哪里改呢?

usb转百兆网口被识别的时候会执行bind初始化函数

int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)

{

  int       status;
  struct cdc_state     *info = (void *) &dev->data;

  BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
      < sizeof(struct cdc_state)));

  status = usbnet_generic_cdc_bind(dev, intf);
  if (status < 0)
    return status;

  status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress);
  if (status < 0) {
    usb_set_intfdata(info->data, NULL);
    usb_driver_release_interface(driver_of(intf), info->data);
    return status;
  }
  dev->net->dev_addr [0] = 0x08;                  //加上这一行
  return 0;
    
}

然后会执行usbnet_get_ethernet_addr()

int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress)
{
	int 		tmp = -1, ret;
	unsigned char	buf [13];

	ret = usb_string(dev->udev, iMACAddress, buf, sizeof buf);           //将地址转换为16进制
	if (ret == 12)
		tmp = hex2bin(dev->net->dev_addr, buf, 6);            //转化为2进制
	if (tmp < 0) {
		dev_dbg(&dev->udev->dev,
			"bad MAC string %d fetch, %d\n", iMACAddress, tmp);
		if (ret >= 0)
			ret = -EINVAL;
		return ret;
	}
    
	return 0;
}

usb_string()函数

/**
 * usb_string - returns UTF-8 version of a string descriptor
 * @dev: the device whose string descriptor is being retrieved
 * @index: the number of the descriptor
 * @buf: where to put the string
 * @size: how big is "buf"?
 * Context: !in_interrupt ()
 *
 * This converts the UTF-16LE encoded strings returned by devices, from
 * usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones
 * that are more usable in most kernel contexts.  Note that this function
 * chooses strings in the first language supported by the device.
 *
 * This call is synchronous, and may not be used in an interrupt context.
 *
 * Return: length of the string (>= 0) or usb_control_msg status (< 0).
 */
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
	unsigned char *tbuf;
	int err;

	if (dev->state == USB_STATE_SUSPENDED)
		return -EHOSTUNREACH;
	if (size <= 0 || !buf || !index)
		return -EINVAL;
	buf[0] = 0;
	tbuf = kmalloc(256, GFP_NOIO);
	if (!tbuf)
		return -ENOMEM;

	err = usb_get_langid(dev, tbuf);
	if (err < 0)
		goto errout;

	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
	if (err < 0)
		goto errout;

	size--;		/* leave room for trailing NULL char in output buffer */
	err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
			UTF16_LITTLE_ENDIAN, buf, size);
	buf[err] = 0;

	if (tbuf[1] != USB_DT_STRING)
		dev_dbg(&dev->dev,
			"wrong descriptor type %02x for string %d (\"%s\")\n",
			tbuf[1], index, buf);

 errout:
	kfree(tbuf);
	return err;
}
EXPORT_SYMBOL_GPL(usb_string);

hex2bin()函数

/**
 * hex2bin - convert an ascii hexadecimal string to its binary representation
 * @dst: binary result
 * @src: ascii hexadecimal string
 * @count: result length
 *
 * Return 0 on success, -1 in case of bad input.
 */
int hex2bin(u8 *dst, const char *src, size_t count)
{
	while (count--) {
		int hi = hex_to_bin(*src++);
		int lo = hex_to_bin(*src++);

		if ((hi < 0) || (lo < 0))
			return -1;

		*dst++ = (hi << 4) | lo;
	}
	return 0;
}
EXPORT_SYMBOL(hex2bin);

修改内容见上面代码中的加上这一行

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极……星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值