物联网之魂:物联网协议与物联网操作系统.html.pdf

上传人:紫竹语嫣 文档编号:5518800 上传时间:2020-05-28 格式:PDF 页数:331 大小:30.05MB
返回 下载 相关 举报
物联网之魂:物联网协议与物联网操作系统.html.pdf_第1页
第1页 / 共331页
物联网之魂:物联网协议与物联网操作系统.html.pdf_第2页
第2页 / 共331页
物联网之魂:物联网协议与物联网操作系统.html.pdf_第3页
第3页 / 共331页
物联网之魂:物联网协议与物联网操作系统.html.pdf_第4页
第4页 / 共331页
物联网之魂:物联网协议与物联网操作系统.html.pdf_第5页
第5页 / 共331页
点击查看更多>>
资源描述

《物联网之魂:物联网协议与物联网操作系统.html.pdf》由会员分享,可在线阅读,更多相关《物联网之魂:物联网协议与物联网操作系统.html.pdf(331页珍藏版)》请在三一文库上搜索。

1、丛书序 信息物理学是物联网工程的理论基础 物联网是近年发展起来的一种网络通信方式。它来源于互联网,但又不同于互联网。它不仅和软件相关,还涉及硬件。互联网在网络上创造一个全新世界时所遇到的“摩擦系数”很小,因为互联网主 要和软件打交道。而物联网却涉及很多硬件,硬件研发又有其物理客体所必须要遵循的自然规律。 物联网和互联网是能够连接的。它能将物品的信息通过各种传感器采集过来,并汇集到网络上。因此,物联网本质上是物和物之间或物和人之间的一种交互。如何揭示物联网的信息获取、信息传输和 信息处理的特殊规律,如何深入探讨信息物理学的前沿课题,以及如何系统、完整地建立物联网学科的知识体系和学科结构,这些问题

2、无论是对高校物联网相关专业的开设,还是对物联网在实际工程领域 中的应用,都是亟待解决的。 物联网领域千帆竞渡,百舸争流 物联网工程在专家、学者和政府官员提出的“感知地球,万物互联”口号的推动下,呈现出空前繁荣的景象。物联网企业的新产品和新技术层出不穷。大大小小的物联网公司纷纷推出了众多连接物联 网的设备,包括智能门锁、牙刷、腕表、健身记录仪、烟雾探测器、监控摄像头、炉具、玩具和机器人等。 1行业巨头跑马圈地,产业资本强势加入 物联网时代,大型公共科技和电信公司已遍布物联网,它们无处不在,几乎已经活跃于物联网的每个细分类别中。这意味着一个物联网生态系统正在形成。 芯片制造商(英特尔、高通和ARM

3、等)都在竞相争夺物联网的芯片市场;思科也直言不讳地宣扬自己的“万物互联”概念,并在不久前以14亿美元的价格收购了Jasper;IBM则宣布在物联网业务中投 资30亿美元;AT Wi-FiStateTrackerwst = new Wi-FiStateTracker(context,mHandler); /创建Wi-FiStateTracker实例 Wi-FiService Wi-FiService = newWi-FiService(context,wst); /创建Wi-FiService实例 ServiceManager.addService(Context.WI-FI_SERVICE,W

4、i-FiService); /向服务管理系统添加Wi-Fi服务 Wi-FiService.startWi-Fi(); /启动Wi-Fi mNetTrackersConnectivityManager.TYPE_WI-FI= wst; wst.startMonitoring(); /启动Wi-FiMonitor中的Wi-FiThread线程 Wi-FiService的主要工作是:Wi-FiMonitor与Wpa_supplicant的启动和关闭,向Wpa_supplicant发送命令。 Wi-FiMonitor的主要工作是:阻塞监听并接收来自Wpa_supplicant的消息,然后发送给Wi-F

5、iStateTracker。 上面两个线程通过AF_UNIX套接字和Wpa_supplicant通信,在通信过程中有两种连接方式:控制连接和监听连接。它们的代码如下: ctrl_conn =wpa_ctrl_open(ifname); http:/ http:/ http:/ monitor_conn = wpa_ctrl_open(ifname); 3.5.2 Wi-Fi启动流程 1使能Wi-Fi 要想使用Wi-Fi模块,必须首先使能Wi-Fi,当第一次按下Wi-Fi使能按钮时,Wireless Settings会实例化一个Wi-FiEnabler对象,实例化代码如下: packages/a

6、pps/settings/src/com/android/settings/WirelessSettings.java protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); CheckBoxPreferenceWi-Fi = (CheckBoxPreference) findPreference(KEY_TOGGLE_ WI-FI); mWi-FiEnabler=new Wi-FiEnabler(this, Wi-Fi); Wi-FiEnabler类的定义大致如下,它实现了一

7、个监听接口,当Wi-FiEnabler对象被初始化后,它监听到用户按键的动作,调用响应函数onPreferenceChange,该函数会调用Wi-FiManager的setWi- FiEnabled函数。 public class Wi-FiEnabler implementsPreference.OnPreferenceChangeListener public boolean onPreferenceChange(Preference preference,Objectvalue) booleanenable = (Boolean)value; if (mWi-FiManager.setW

8、i-FiEnabled(enable) mCheckBox.setEnabled(false); 我们都知道,Wi-Fimanager只是一个服务代理,所以它会调用Wi-FiService的setWi-FiEnabled函数,而这个函数会调用sendEnableMessage函数,了解Android消息处理机制的读者都知道,这个 函数最终会给自己发送一个MESSAGE_ENABLE_WI-FI的消息,被Wi-FiService里面定义的handlermessage函数处理,会调用setWi-FiEnabledBlocking函数。下面是调用流程: mWi-FiEnabler.onprefere

9、ncechange函数mWi-FiManage.setWi-Fienabled函数mWi-FiService.setWi-FiEnabled函数mWi-FiService.sendEnableMessage函数mWi- FiService.handleMessage函数mWi-FiService.setWi-FiEnabledBlocking函数。 在setWi-FiEnabledBlocking函数中主要做如下工作:加载Wi-Fi驱动,启动wpa_supplicant,注册广播接收器,启动Wi-FiThread监听线程。代码如下: if (enable) if(!mWi-FiStateTra

10、cker.loadDriver() Slog.e(TAG,“Failed toload Wi-Fi driver.“); setWi-FiEnabledState(WI-FI_STATE_UNKNOWN,uid); return false; if(!mWi-FiStateTracker.startSupplicant() mWi-FiStateTracker.unloadDriver(); Slog.e(TAG, “Failed tostart supplicant daemon.“); setWi-FiEnabledState(WI-FI_STATE_UNKNOWN, uid); retu

11、rn false; registerForBroadcasts(); mWi-FiStateTracker.startEventLoop(); 至此,Wi-Fi使能结束,自动进入扫描阶段。 2扫描AP 扫描AP是Wi-Fi的一项重要工作,分为自动扫描和手动扫描两种方式。 当驱动加载成功后,如果配置文件的AP_SCAN=1,扫描会自动开始,Wi-FiMonitor将会从supplicant收到一个消息EVENT_DRIVER_STATE_CHANGED,调用handleDriver Event,然后调用mWi- FiStateTracker.notifyDriverStarted函数。该函数向消

12、息队列添加EVENT_DRIVER_STATE_CHANGED,handlermessage函数处理消息时调用scan函数,并通过Wi-FiNative将扫描命令发送到 wpa_supplicant。代码如下: Frameworks/base/Wi-Fi/java/android/net/Wi-Fi/Wi-FiMonitor.java private void handleDriverEvent(Stringstate) if(state = null) return; if(state.equals(“STOPPED“) mWi-FiStateTracker.notifyDriverStop

13、ped(); else if (state.equals(“STARTED“) mWi-FiStateTracker.notifyDriverStarted(); else if (state.equals(“HANGED“) mWi-FiStateTracker.notifyDriverHung(); Frameworks/base/Wi-Fi/java/android/net/Wi-Fi/Wi-FiStateTracker.java case EVENT_DRIVER_STATE_CHANGED: switch(msg.arg1) case DRIVER_STARTED: /* *Set

14、the number of allowed radio channels according *to the system setting, since it gets reset by the *driver upon changing to the STARTED state. */ setNumAllowedChannels(); synchronized(this) if(mRunState = RUN_STATE_STARTING) mRunState= RUN_STATE_RUNNING; if(!mIsScanOnly) reconnectCommand(); else /在某些

15、情况下,需要运行请求程序来启动背景扫描 scan(true); break; 上面是启动Wi-Fi时自动进行的AP扫描,用户当然也可以手动扫描AP,这部分实现在Wi-FiService里面,Wi-FiService通过startScan接口函数发送扫描命令到supplicant。代码如下: Frameworks/base/Wi-Fi/java/android/net/Wi-Fi/Wi-FiStateTracker.java public boolean startScan(booleanforceActive) enforceChangePermission(); switch(mWi-FiS

16、tateTracker.getSupplicantState() caseDISCONNECTED: caseINACTIVE: caseSCANNING: caseDORMANT: break; default: mWi-FiStateTracker.setScanResultHandling( Wi-FiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); break; return mWi-FiStateTracker.scan(forceActive); 后面的流程与自动扫描的流程相似,我们来分析一下手动扫描从哪里开始的。我们知道,手动扫描是通过菜单

17、扫描命令来响应的,而响应该动作的应该是Wi-FiSettings类中Scanner类的 handlerMessage函数,它调用Wi-FiManager的startScanActive函数,从而调用Wi-FiService的startScan函数。代码如下: packages/apps/Settings/src/com/android/settings/Wi-FiWi-Fisettings.java public boolean onCreateOptionsMenu(Menu menu) menu.add(Menu.NONE,MENU_ID_SCAN, 0, R.string.Wi-Fi_m

18、enu_scan) .setIcon(R.drawable.ic_menu_scan_network); menu.add(Menu.NONE,MENU_ID_ADVANCED,0,R.string.Wi-Fi_menu_advanced) .setIcon(android.R.drawable.ic_menu_manage); returnsuper.onCreateOptionsMenu(menu); 当选择菜单命令时,Wi-FiSettings就会调用这个函数绘制菜单。如果单击扫描按钮,Wi-FiSettings会调用onOptionsItemSelected函数。代码如下: packa

19、ges/apps/Settings/src/com/android/settings/Wi-FiWi-Fisettings.java public booleanonOptionsItemSelected(MenuItem item) switch (item.getItemId() caseMENU_ID_SCAN: if(mWi-FiManager.isWi-FiEnabled() mScanner.resume(); return true; caseMENU_ID_ADVANCED: startActivity(new Intent(this,AdvancedSettings.clas

20、s); return true; returnsuper.onOptionsItemSelected(item); private class Scanner extends Handler private int mRetry = 0; void resume() if (!hasMessages(0) sendEmptyMessage(0); void pause() mRetry= 0; mAccessPoints.setProgress(false); removeMessages(0); Override public voidhandleMessage(Message messag

21、e) if(mWi-FiManager.startScanActive() mRetry = 0; else if (+mRetry = 3) mRetry = 0; Toast.makeText(Wi-FiSettings.this,R.string.Wi-Fi_fail_ to_scan, Toast.LENGTH_LONG).show(); return; mAccessPoints.setProgress(mRetry!= 0); sendEmptyMessageDelayed(0, 6000); 这里的mWi-FiManager.startScanActive函数就会调用Wi-FiS

22、ervice里的startScan函数,后面的流程和上面的一样,不再赘述。 当supplicant完成了这个扫描命令后,它会发送一个消息给上层,提醒它们扫描已经完成,Wi-FiMonitor会接收到这消息,然后再发送给Wi-FiStateTracker。代码如下: Frameworks/base/Wi-Fi/java/android/net/Wi-Fi/Wi-FiMonitor.java void handleEvent(int event, String remainder) switch (event) caseDISCONNECTED: handleNetworkStateChange(

23、NetworkInfo.DetailedState. DISCONNECTED,remainder); break; case CONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState. CONNECTED,remainder); break; case SCAN_RESULTS: mWi-FiStateTracker.notifyScanResultsAvailable(); break; case UNKNOWN: break; Wi-FiStateTracker将会广播SCAN_RESULTS_AVAILABLE_ACTI

24、ON消息: Frameworks/base/Wi-Fi/java/android/net/Wi-Fi/Wi-FiStateTracker.java public voidhandleMessage(Message msg) Intent intent; case EVENT_SCAN_RESULTS_AVAILABLE: if(ActivityManagerNative.isSystemReady() mContext.sendBroadcast(newIntent(Wi-FiManager.SCAN_ RESULTS_AVAILABLE_ACTION); sendScanResultsAva

25、ilable(); /* * On receiving the first scanresults after connecting to * the supplicant, switch scanmode over to passive. */ setScanMode(false); break; 由于Wi-FiSettings类注册了Intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用handleEvent函数,调用流程如下: Wi-FiSettings.handleEvent函数Wi-FiSettings.updateAccessPoints函数

26、mWi-FiManager.Get ScanResults函数mService.getScanResults函数mWi-FiStateTracker.scan Results函数 Wi-FiNative.scan ResultsCommand函数 将获取AP列表的命令发送到supplicant,然后supplicant通过socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本相同。 3配置连接AP 当用户选择一个活跃的AP时,Wi-FiSettings响应打开一个对话框来配置AP,比如加密方法和连接AP的验证模式。配置好AP后,Wi-FiService添加或更新网络连接到特定的

27、AP。代码如下: packages/apps/settings/src/com/android/settings/Wi-Fi/Wi-FiSetttings.java public booleanonPreferenceTreeClick(PreferenceScreen screen,Preference preference) if (preference instanceofAccessPoint) mSelected= (AccessPoint) preference; showDialog(mSelected, false); else if (preference =mAddNetw

28、ork) mSelected= null; showDialog(null,true); else if (preference =mNotifyOpenNetworks) Secure.putInt(getContentResolver(), Secure.WI-FI_NETWORKS_AVAILABLE_NOTIFICATION_ON, mNotifyOpenNetworks.isChecked()? 1 : 0); else returnsuper.onPreferenceTreeClick(screen, preference); return true; 配置好以后,当按Connec

29、t Press时,Wi-FiSettings通过发送LIST_NETWORK命令到supplicant来检查该网络是否配置。如果没有该网络或没有配置它,Wi-FiService将调用addorUpdateNetwork函 数来添加或更新网络,然后发送命令给supplicant,连接到这个网络。下面是从响应连接按钮到Wi-FiService发送连接命令的代码: packages/apps/settings/src/com/android/settings/Wi-Fi/Wi-FiSetttings.java public void onClick(DialogInterfacedialogInte

30、rface, int button) if (button =Wi-FiDialog.BUTTON_FORGET else if (button =Wi-FiDialog.BUTTON_SUBMIT if(config = null) if(mSelected != null else if (workId != -1) if (mSelected != null) mWi-FiManager.updateNetwork(config); saveNetworks(); else intnetworkId =mWi-FiManager.addNetwork(config); if (netwo

31、rkId != -1) mWi-FiManager.enableNetwork(networkId,false); workId =networkId; if (mDialog.edit | requireKeyStore(config) saveNetworks(); else connect(networkId); FrameworksbaseWi-FijavaandroidnetWi-FiWi-FiManager.java public intupdateNetwork(Wi-FiConfiguration config) if(config = null |workId dev.pla

32、tform_data); DHD_ERROR(“# %sn“,_FUNCTION_); Wi-Fi_irqres = platform_get_resource_byname(pdev,IORESOURCE_IRQ, “bcmdhd_wlan_irq“); if (Wi-Fi_irqres = NULL) Wi-Fi_irqres =platform_get_resource_byname(pdev, IORESOURCE_IRQ,“bcm4329_wlan_irq“); Wi-Fi_control_data = Wi-Fi_ctrl; Wi-Fi_set_power(1,0); /* Pow

33、er On */ Wi-Fi_set_carddetect(1); /* CardDetect (0-1) */ up( return 0; 这是Wi-Fi平台设备驱动注册时成功匹配Wi-Fi设备后调用的Wi-Fi_probe函数,它的主要工作就是从Wi-Fi设备中获取终端资源,并获取Wi-Fi_platform_data类型结构赋予Wi-Fi_control_data变量, 这一步很重要,下面就可以看出它的重要性了。然后调用Wi-Fi_set_power函数和Wi-Fi_set_carddetect函数给Wi-Fi芯片上电并检测。代码如下: int Wi-Fi_set_power(int o

34、n, unsignedlong msec) DHD_ERROR(“%s = %dn“,_FUNCTION_, on); if (Wi-Fi_control_data if (msec) msleep(msec); return 0; Wi-Fi_set_power函数中调用Wi-Fi_control_data-set_power(on)函数,Wi-Fi_control_data就是前面说的那个重要变量,注意它是从Wi-Fi_device平台设备的Wi-Fi_platform_data类型结构中获取 的。现在来看看上面的Wi-Fi_device平台初始化的代码: static struct pl

35、atform_device mahimahi_Wi-Fi_device = .name = “bcm4329_wlan“, .id = 1, .num_resources = ARRAY_SIZE(mahimahi_Wi-Fi_resources), .resource = mahimahi_Wi-Fi_resources, .dev = .platform_data = static struct Wi-Fi_platform_datamahimahi_Wi-Fi_control= .set_power = mahimahi_Wi-Fi_power, .set_reset = mahimah

36、i_Wi-Fi_reset, .set_carddetect = mahimahi_Wi-Fi_set_carddetect, .mem_prealloc = mahimahi_Wi-Fi_mem_prealloc, ; 所以它实际调用的是mahimahi_Wi-Fi_power函数,该函数的定义在kernel/arch/arm/mach-msm/board-mahimahi-mmc.c中。代码如下: int mahimahi_Wi-Fi_power(int on) printk(“%s: %dn“, _func_, on); if (on) config_gpio_table(Wi-Fi_o

37、n_gpio_table, ARRAY_SIZE(Wi-Fi_on_gpio_table); mdelay(50); else config_gpio_table(Wi-Fi_off_gpio_table, ARRAY_SIZE(Wi-Fi_off_gpio_table); mdelay(100); gpio_set_value(MAHIMAHI_GPIO_WI-FI_SHUTDOWN_N,on);/*WI-FI_SHUTDOWN */ mdelay(200); mahimahi_Wi-Fi_power_state = on; return 0; 调用gpio_set_value函数操作Wi-

38、Fi芯片,给Wi-Fi芯片上电。现在来看看Wi-Fi_set_carddetect函数究竟做了什么事: Path:wl/sys/wl_android.c static int Wi-Fi_set_carddetect(int on) DHD_ERROR(“%s = %dn“, _FUNCTION_, on); if(Wi-Fi_control_data return 0; 同样会调用Wi-Fi_device平台的mahimahi_Wi-Fi_set_carddetect函数。代码如下: Path:kernel/arch/arm/mach-msm/board-mahimahi-mmc.c int

39、 mahimahi_Wi-Fi_set_carddetect(int val) pr_info(“%s: %dn“, _func_, val); mahimahi_Wi-Fi_cd = val; if(Wi-Fi_status_cb) Wi-Fi_status_cb(val,Wi-Fi_status_cb_devid); else pr_warning(“%s: Nobody to notifyn“, _func_); return 0; Wi-Fi_status_cb代码如下: static int mahimahi_Wi-Fi_status_register( void (*callbac

40、k)(intcard_present, void *dev_id), void *dev_id) if (Wi-Fi_status_cb) return -EAGAIN; Wi-Fi_status_cb = callback; Wi-Fi_status_cb_devid = dev_id; return 0; static unsigned intmahimahi_Wi-Fi_status(struct device *dev) return mahimahi_Wi-Fi_cd; static structmmc_platform_data mahimahi_Wi-Fi_data = .ocr

41、_mask = MMC_VDD_28_29, .built_in = 1, .status = mahimahi_Wi-Fi_status, .register_status_notify= mahimahi_Wi-Fi_status_register, .embedded_sdio = 由上面的代码不难看出会有个地方调用了mahimahi_Wi-Fi_status_register函数来设置Wi-Fi_status_cb回调函数,可以跟踪这个mahimahi_Wi-Fi_data结构体,看它被传递给了谁: int msm_add_sdcc(unsigned intcontroller, st

42、ruct mmc_platform_data *plat, unsigned int stat_irq,unsigned long stat_irq_flags); int _initmahimahi_init_mmc(unsigned int sys_rev, unsigned debug_uart) msm_add_sdcc(1, if (system_rev 0) msm_add_sdcc(2, else mahimahi_sdslot_data.status =mahimahi_sdslot_status_rev0; mahimahi_sdslot_data.register_stat

43、us_notify = NULL; set_irq_wake(MSM_GPIO_TO_INT(MAHIMAHI_GPIO_SDMC_CD_REV0_N),1); msm_add_sdcc(2, struct platform_device msm_device_sdc2 = .name = “msm_sdcc“, .id = 2, .num_resources = ARRAY_SIZE(resources_sdc2), .resource = resources_sdc2, .dev = .coherent_dma_mask =0xffffffff, , ; struct platform_d

44、evicemsm_device_sdc3 = .name = “msm_sdcc“, .id = 3, .num_resources = ARRAY_SIZE(resources_sdc3), .resource = resources_sdc3, .dev = .coherent_dma_mask = 0xffffffff, , ; struct platform_device msm_device_sdc4= .name = “msm_sdcc“, .id = 4, .num_resources = ARRAY_SIZE(resources_sdc4), .resource = resou

45、rces_sdc4, .dev = 439,2-16 62% .coherent_dma_mask = 0xffffffff, , ; static struct platform_device *msm_sdcc_devices _initdata = int_initmsm_add_sdcc(unsigned int controller,struct mmc_platform_data *plat, unsigned int stat_irq,unsigned long stat_irq_flags) pdev =msm_sdcc_devicescontroller-1; /因为传过来c

46、ontroller是1,所以下面注册的是第1个平台设备 pdev-dev.platform_data= plat; /被传递给平台设备的platform_data res =platform_get_resource_byname(pdev, IORESOURCE_IRQ, “status_irq“); if (!res) return -EINVAL; else if (stat_irq) res-start = res-end =stat_irq; res-flags res-flags |=stat_irq_flags; return platform_device_register(pdev); 这个平台设备就是SD卡控制器,也就是前面说的host驱动所驱动的主机控制设备。 Path: drivers/mmc/host/msm_sdcc.c static struct platform_drivermsmsdcc_driver = .probe = msmsdcc_probe, .suspend = msmsdcc_suspend, .resume =

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/环境 > 建筑资料


经营许可证编号:宁ICP备18001539号-1