Android USB Tethering的实现以及代码流程

直接略过界面层,界面一系列处理后调用Tethering.java的setUsbTethering函数。

[java]  view plain copy
  1. public int setUsbTethering(boolean enable) {  
  2.     if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");  
  3.         UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);  
  4.    
  5.     synchronized (mPublicSync) {  
  6.         if (enable) {  
  7.             if (mRndisEnabled) {  
  8.                 tetherUsb(true);  
  9.             } else {  
  10.                 mUsbTetherRequested = true;  
  11.                 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);//一开始因为rndis还没有enable,所以会先设置function  
  12.             }  
  13.         } else {  
  14.             tetherUsb(false);  
  15.             if (mRndisEnabled) {  
  16.                 usbManager.setCurrentFunction(nullfalse);  
  17.             }  
  18.             mUsbTetherRequested = false;  
  19.         }  
  20.     }  
  21.         return ConnectivityManager.TETHER_ERROR_NO_ERROR;  
  22. }  


Java层改变usbfunction,其实就是设置内核提供的接口文件进行操作的

具体可以在init.usbmode.sh里面看到

[ruby]  view plain copy
  1. echo 0 > /sys/class/android_usb/android0/enable  
  2. echo ${VENDOR_ID} > /sys/class/android_usb/android0/idVendor  
  3.    
  4. if [ ${ENG_PROP} -eq 1 ] ; then  
  5.   set_engpid ${USB_FUNCTION}  
  6. fi  
  7.    
  8. echo ${PID} > /sys/class/android_usb/android0/idProduct  
  9. /system/bin/log -t ${TAG} -p i "usb product id: ${PID}"  
  10.    
  11. echo 0 > /sys/class/android_usb/android0/bDeviceClass  
  12. echo 0 > /sys/class/android_usb/android0/bDeviceSubClass  
  13. echo 0 > /sys/class/android_usb/android0/bDeviceProtocol  
  14.    
  15. echo ${USB_FUNCTION} > /sys/class/android_usb/android0/functions  
  16. /system/bin/log -t ${TAG} -p i "enabled usb functions: ${USB_FUNCTION}"  
  17.    
  18. echo 1 > /sys/class/android_usb/android0/enable  


首先设置enable0,即断开,然后设置functions等,最后再 将enable设为1,也就是代表连接上了USB。设置enable会调用android.c的enable_store函数,设置fucntions会调用functions_store函数。

android.c里面的代码:

[cpp]  view plain copy
  1. static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store);  
  2. static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);  

functions_store只是把enablefunction存储到一个enabled_list里面。

重点是enable_store函数

[cpp]  view plain copy
  1. static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,  
  2.     const char *buff, size_t size)  
  3. {  
  4. struct android_dev *dev = dev_get_drvdata(pdev);  
  5. struct usb_composite_dev *cdev = dev->cdev;  
  6. struct android_usb_function *f;  
  7. struct android_configuration *conf;  
  8. int enabled = 0;  
  9. static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);  
  10.    
  11. if (!cdev)  
  12. return -ENODEV;  
  13.    
  14. mutex_lock(&dev->mutex);  
  15.    
  16. sscanf(buff, "%d", &enabled);  
  17. if (enabled && !dev->enabled) {  //enable从0设置为1时进入这个分支  
  18. /* 
  19.  * Update values in composite driver's copy of 
  20.  * device descriptor. 
  21.  */  
  22. cdev->desc.idVendor = device_desc.idVendor;  
  23. cdev->desc.idProduct = device_desc.idProduct;  
  24. cdev->desc.bcdDevice = device_desc.bcdDevice;  
  25. cdev->desc.bDeviceClass = device_desc.bDeviceClass;  
  26. cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;  
  27. cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;  
  28. list_for_each_entry(conf, &dev->configs, list_item)  
  29. list_for_each_entry(f, &conf->enabled_functions,  
  30. enabled_list) {  
  31. if (f->enable)  
  32. f->enable(f);  
  33. }  
  34. android_enable(dev);  
  35. dev->enabled = true;  
  36. else if (!enabled && dev->enabled) {  
  37. android_disable(dev);  
  38. list_for_each_entry(conf, &dev->configs, list_item)  
  39. list_for_each_entry(f, &conf->enabled_functions,  
  40. enabled_list) {  
  41. if (f->disable)  
  42. f->disable(f);  
  43. }  
  44. dev->enabled = false;  
  45. else if (__ratelimit(&rl)) {  
  46. pr_err("android_usb: already %s\n",  
  47. dev->enabled ? "enabled" : "disabled");  
  48. }  
  49.    
  50. mutex_unlock(&dev->mutex);  
  51.    
  52. return size;  
  53. }  

因为rndis_function没有定义enable函数,所以直接执行android_enable(dev)Rndis_function的定义

[cpp]  view plain copy
  1. static struct android_usb_function rndis_function = {  
  2. .name = "rndis",  
  3. .init = rndis_function_init,  
  4. .cleanup = rndis_function_cleanup,  
  5. <span style="color:#cc0000;">.bind_config = rndis_function_bind_config,</span>  
  6. .unbind_config = rndis_function_unbind_config,  
  7. .attributes = rndis_function_attributes,  
  8. };  

接着看android_enable这个函数

[cpp]  view plain copy
  1. static void android_enable(struct android_dev *dev)  
  2. {  
  3. struct usb_composite_dev *cdev = dev->cdev;  
  4. struct android_configuration *conf;  
  5.    
  6. if (WARN_ON(!dev->disable_depth))  
  7. return;  
  8.    
  9. if (--dev->disable_depth == 0) {  
  10.    
  11. list_for_each_entry(conf, &dev->configs, list_item)  
  12. usb_add_config(cdev, &conf->usb_config,  
  13. android_bind_config);  
  14.    
  15. usb_gadget_connect(cdev->gadget);//Enables the D+ (or potentially D-) pullup  
  16. }  
  17. }  


主要是执行了usb_add_config函数,并且将android_bind_config传给了一个函数指针。

Usb_add_configcomposite.c里面的函数

[cpp]  view plain copy
  1. int usb_add_config(struct usb_composite_dev *cdev,  
  2. struct usb_configuration *config,  
  3. int (*bind)(struct usb_configuration *))  
  4. {  
  5. 。。。。。。  
  6. status = bind(config);  
  7. 。。。。。。  
  8. }  

这里又回到android.c的android_bind_config函数

android_bind_config调用android_bind_enabled_functions,继续调用每个function自己注册的bind_config函数。这里调用的就是rndis的了。看看该函数rndis_function_bind_config。

[cpp]  view plain copy
  1. static int  
  2. rndis_function_bind_config(struct android_usb_function *f,  
  3. struct usb_configuration *c)  
  4. {  
  5. int ret;  
  6. struct rndis_function_config *rndis = f->config;  
  7.    
  8. if (!rndis) {  
  9. pr_err("%s: rndis_pdata\n", __func__);  
  10. return -1;  
  11. }  
  12.    
  13. pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,  
  14. rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],  
  15. rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);  
  16.    
  17.     //初始化一个ethernet-over-usb link  
  18. ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "usb");  
  19. if (ret) {  
  20. pr_err("%s: gether_setup failed\n", __func__);  
  21. return ret;  
  22. }  
  23.    
  24. if (rndis->wceis) {  
  25. /* "Wireless" RNDIS; auto-detected by Windows */  
  26. rndis_iad_descriptor.bFunctionClass =  
  27. USB_CLASS_WIRELESS_CONTROLLER;  
  28. rndis_iad_descriptor.bFunctionSubClass = 0x01;  
  29. rndis_iad_descriptor.bFunctionProtocol = 0x03;  
  30. rndis_control_intf.bInterfaceClass =  
  31. USB_CLASS_WIRELESS_CONTROLLER;  
  32. rndis_control_intf.bInterfaceSubClass =  0x01;  
  33. rndis_control_intf.bInterfaceProtocol =  0x03;  
  34. }  
  35.    
  36. return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,  
  37.    rndis->manufacturer);  
  38. }  
  39.    


继续回到kernel来,现在走到了U_ether的gether_setup_name函数 这里有个rndis_function_config,他是在UsbDeviceManager初始化的时候通过sysfs赋值的。UsbDeviceManager的构造函数调用了一个叫initRndisAddress的函数。

[cpp]  view plain copy
  1. int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],  
  2. const char *netname)  
  3. {  
  4. struct eth_dev *dev;  
  5. struct net_device *net;  
  6. int status;  
  7.    
  8. if (the_dev)  
  9. return -EBUSY;  
  10.    
  11. net = alloc_etherdev(sizeof *dev);  
  12. if (!net)  
  13. return -ENOMEM;  
  14.    
  15. dev = netdev_priv(net);  
  16. spin_lock_init(&dev->lock);  
  17. spin_lock_init(&dev->req_lock);  
  18. INIT_WORK(&dev->work, eth_work);  
  19. INIT_WORK(&dev->rx_work, process_rx_w);  
  20. INIT_LIST_HEAD(&dev->tx_reqs);  
  21. INIT_LIST_HEAD(&dev->rx_reqs);  
  22.    
  23. skb_queue_head_init(&dev->rx_frames);  
  24.    
  25. /* network device setup */  
  26. dev->net = net;  
  27. snprintf(net->name, sizeof(net->name), "%s%%d", netname);  
  28.    
  29. if (get_ether_addr(dev_addr, net->dev_addr))  
  30. dev_warn(&g->dev,  
  31. "using random %s ethernet address\n""self");  
  32.    
  33. if (get_host_ether_addr(host_ethaddr, dev->host_mac))  
  34. dev_warn(&g->dev, "using random %s ethernet address\n""host");  
  35. else  
  36. dev_warn(&g->dev, "using previous %s ethernet address\n""host");  
  37.    
  38. if (ethaddr)  
  39. memcpy(ethaddr, dev->host_mac, ETH_ALEN);  
  40.    
  41. net->netdev_ops = ð_netdev_ops;  
  42.    
  43. SET_ETHTOOL_OPS(net, &ops);  
  44.    
  45. dev->gadget = g;  
  46. SET_NETDEV_DEV(net, &g->dev);  
  47. SET_NETDEV_DEVTYPE(net, &gadget_type);  
  48.    
  49. status = register_netdev(net); //注册网络设备  
  50. if (status < 0) {  
  51. dev_dbg(&g->dev, "register_netdev failed, %d\n", status);  
  52. free_netdev(net);  
  53. else {  
  54. INFO(dev, "MAC %pM\n", net->dev_addr);  
  55. INFO(dev, "HOST MAC %pM\n", dev->host_mac);  
  56.    
  57. the_dev = dev;  
  58.    
  59. /* two kinds of host-initiated state changes: 
  60.  *  - iff DATA transfer is active, carrier is "on" 
  61.  *  - tx queueing enabled if open *and* carrier is "on" 
  62.  */  
  63. netif_carrier_off(net);  
  64. }  
  65.    
  66. return status;  
  67. }  



Eth_dev结构体包含了一个usb_gadget结构体和net_device结构体 

 

 

 

 

[cpp]  view plain copy
  1. 等待补充更新  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

完成后,kernel会发送一个uevent

Netd接收到并处理

[java]  view plain copy
  1. void NetlinkHandler::onEvent(NetlinkEvent *evt) {  
  2.     const char *subsys = evt->getSubsystem();  
  3.    
  4.     if (!strcmp(subsys, "net")) {  
  5.         int action = evt->getAction();  
  6.         const char *iface = evt->findParam("INTERFACE");  
  7.    
  8.         if (action == evt->NlActionAdd) {  
  9.             notifyInterfaceAdded(iface);  
  10.         } else if (action == evt->NlActionRemove) {  
  11.             notifyInterfaceRemoved(iface);  
  12.         } else if (action == evt->NlActionChange) {  
  13.             evt->dump();  
  14.             notifyInterfaceChanged("nana"true);  
  15.         } else if (action == evt->NlActionLinkUp) {  
  16.             notifyInterfaceLinkChanged(iface, true);  
  17.         } else if (action == evt->NlActionLinkDown) {  
  18.             notifyInterfaceLinkChanged(iface, false);  
  19.         }  

[java]  view plain copy
  1. void NetlinkHandler::notifyInterfaceAdded(const char *name) {  
  2.     char msg[255];  
  3.     snprintf(msg, sizeof(msg), "Iface added %s", name);  
  4.    
  5.     mNm->getBroadcaster()->sendBroadcast(ResponseCode::InterfaceChange,  
  6.             msg, false);  
  7. }  


接着就调用interfaceAdded

这里是通过socketclients发送消息,NetworkManagementService.java的NetdCallbackReceiver会收到消息,在onEvent中进行处理

[java]  view plain copy
  1. public boolean onEvent(int code, String raw, String[] cooked) {  
  2.     switch (code) {  
  3.         case NetdResponseCode.InterfaceChange:  
  4.              /* 
  5.               * a network interface change occured 
  6.               * Format: "NNN Iface added <name>" 
  7.               *         "NNN Iface removed <name>" 
  8.               *         "NNN Iface changed <name> <up/down>" 
  9.               *         "NNN Iface linkstatus <name> <up/down>" 
  10.               */  
  11.              if (cooked.length < 4 || !cooked[1].equals("Iface")) {  
  12.                  throw new IllegalStateException(  
  13.                      String.format("Invalid event from daemon (%s)", raw));  
  14.                  }  
  15.                  if (cooked[2].equals("added")) {  
  16.                      notifyInterfaceAdded(cooked[3]);  
  17.                      return true;  
  18.                  } else if (cooked[2].equals("removed")) {  
  19.                      notifyInterfaceRemoved(cooked[3]);  
  20.                      return true;  
  21.                  } else if (cooked[2].equals("changed") && cooked.length == 5) {  
  22.                      notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));  
  23.                      return true;  
  24.                  } else if (cooked[2].equals("linkstate") && cooked.length == 5) {  
  25.                      notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));  
  26.                      return true;  
  27.                  }  
  28.                  throw new IllegalStateException(  
  29.                      String.format("Invalid event from daemon (%s)", raw));  
  30.                  // break;  

[java]  view plain copy
  1. private void notifyInterfaceAdded(String iface) {  
  2.     final int length = mObservers.beginBroadcast();  
  3.     for (int i = 0; i < length; i++) {  
  4.         try {  
  5.             mObservers.getBroadcastItem(i).interfaceAdded(iface);  
  6.         } catch (RemoteException e) {  
  7.         }  
  8.     }  
  9.     mObservers.finishBroadcast();  
  10. }  


notifyInterfaceAdded会调用到Tethering.java里面的interfaceAdded函数

具体为什么会调用到tethering.java里的函数,是因为ConnectivityService在初始化的时候将Tethering的对象mTethering register到了INetworkManagementService的实例mNetd

ConnectivityService.java

[java]  view plain copy
  1. public ConnectivityService(Context context, INetworkManagementService netManager,  
  2.         INetworkStatsService statsService, INetworkPolicyManager policyManager,  
  3.         NetworkFactory netFactory) {  
  4. 。。。。。。。。。。  
  5. try {  
  6.     mNetd.registerObserver(mTethering);  
  7.     mNetd.registerObserver(mDataActivityObserver);  
  8. catch (RemoteException e) {  
  9.     loge("Error registering observer :" + e);  
  10. }  


 registerObserver其实是把mTethering放到一个callbacklist里面,调用的时候会从这个list’里面取出来

 

继续看Tethering.java的interfaceAdded

[java]  view plain copy
  1. public void interfaceAdded(String iface) {                                                                                           
  2.     boolean found = false;                                                                     
  3.     boolean usb = false;                                                                       
  4.     synchronized (mPublicSync) {                                                               
  5.         if (isWifi(iface)) {                                                                   
  6.             found = true;                                                                      
  7.         }                                                                                      
  8.         if (isUsb(iface)) {                                                                    
  9.             found = true;                                                                      
  10.             usb = true;                                                                        
  11.         }                                                                                      
  12.         if (isBluetooth(iface)) {                                                              
  13.             found = true;                                                                      
  14.         }                                                                                      
  15.         if (found == false) {                                                                  
  16.             if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");              
  17.             return;                                                                            
  18.         }                                                                                      
  19.                                                                                                
  20.         TetherInterfaceSM sm = mIfaces.get(iface);                                             
  21.         if (sm != null) {                                                                      
  22.             if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");  
  23.             return;                                                                            
  24.         }                                                                                      
  25.         sm = new TetherInterfaceSM(iface, mLooper, usb);                                       
  26.         mIfaces.put(iface, sm);                                                                
  27.         sm.start();                                                                 
  28.     }                                                                                          
  29. }                                                                                              
  1.    
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Android 10.0系统中,可以通过以下步骤实现USB转网口默认固定IP地址的设置: 1. 连接USB转网口设备到Android设备。 2. 在Android设备中打开“设置”应用程序,点击“网络和互联网”选项。 3. 在“网络和互联网”选项中,选择“热点与共享”选项。 4. 在“热点与共享”选项中,选择“USB网络共享”选项。 5. 在“USB网络共享”选项中,开启“USB Tethering”选项,然后点击“USB网口设置”选项。 6. 在“USB网口设置”选项中,选择“静态IP”选项。 7. 在“静态IP”选项中,输入所需的IP地址、子网掩码和网关信息。 8. 点击“保存”按钮完成设置。 经过以上步骤后,Android设备就会将USB转网口设备连接到静态IP地址,并且该设置将在以后的使用中保持不变。需要注意的是,确保所设置的固定IP地址与其他设备使用的IP地址不冲突,以免出现网络连接问题。 ### 回答2: Android 10.0系统的USB转网口默认情况下是动态获取IP地址的,如果需要设置固定IP地址,可以按照以下步骤进行: 1. 连接设备并打开USB调试模式,可以在设置->开发者选项中找到该选项。 2. 打开电脑的命令提示符或终端工具,输入“adb devices”命令,确认设备连接成功。 3. 在终端中输入“adb shell”,进入设备的shell模式。 4. 输入“su”命令,获取root权限。 5. 输入“netcfg”,查看当前所有网络接口及其状态。 6. 根据需要的网络接口,确定其接口名称。一般为“rndis0”或“rmnet0”。 7. 输入“ifconfig [接口名称] [IP地址] netmask [子网掩码] up”命令,设置IP地址与子网掩码。例如:ifconfig rndis0 192.168.1.100 netmask 255.255.255.0 up。 8. 输入“route add default gw [网关地址] [接口名称]”命令,设置默认网关。例如:route add default gw 192.168.1.1 rndis0。 9. 输入“setprop net.dns1 [首选DNS服务器地址]”命令,设置DNS服务器地址。例如:setprop net.dns1 8.8.8.8。 10. 使用ping命令测试网络连接是否正常,例如:ping baidu.com。 以上是Android 10.0系统USB转网口设置固定IP地址的步骤,需要注意的是,该设置仅在当前USB网络连接下有效,并且用户需要具备一定的命令行操作经验。在进行设置时,应根据实际情况进行调整。 ### 回答3: Android 10.0系统的USB转网口功能可以把手机当成一个有线网络适配器使用,将手机通过USB接口与电脑相连,从而实现电脑通过手机进行有线网络访问的功能。要设置USB转网口默认的固定IP地址,可以按照以下步骤进行操作: 1. 打开设置菜单,在“网络和互联网”选项下找到“热点和网络共享”设置,打开该设置。 2. 在热点和网络共享页面中找到“USB网络共享”选项,开启USB网络共享功能。 3. 在“USB网络共享”选项的设置页面中,找到“USB Tethering设置”选项,点击进入。 4. 在“USB Tethering设置”页面中,可以看到“USB网络共享配置”设置项,点击该设置项。 5. 在“USB网络共享配置”设置页面中,可以设置USB网络共享的IP地址、子网掩码、网关、DNS等参数。在IP地址设置中选择“静态”方式,手动设置需要设置的固定IP地址。 6. 完成上述设置后,重新连接电脑和手机的USB接口,电脑会自动获取到设置的固定IP地址,实现USB转网口的固定IP地址功能。 需要注意的是,如果设置的固定IP地址与网络中其他设备的IP地址冲突,就可能会导致无法连接网络或无法正常访问网络。因此,在设置固定IP地址时,需要确保设置的IP地址在网络中是唯一的,避免冲突。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值