国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

應用程序與硬件進行交互(實現硬件綁定、應用程序與硬件通信)

2019-11-17 03:19:21
字體:
來源:轉載
供稿:網友

應用程序與硬件進行交互(實現硬件綁定、應用程序與硬件通信)

一、前言 在無操作系統的裸機中,或者類似如DOS這樣操作系統中,應用程序和硬件的交互是非常簡單的。如果沒有操作系統,我們訪問硬件空間可能只需一條指令就行,甚至可以訪問任意的內存空間或者IO空間。但是在WINDOWS操作系統中,應 用程序與硬件間被完全隔離開來,應用程序與軟件的通信就必須依賴于依賴驅動程序。有點類似于現在的網上購物,賣家相當于硬件,而賣家相當于應用程序,淘寶等類似的購物網站相當于驅動程序,而賣家與買家之間的買賣就得依賴 于淘寶等類似的購物網站。至于為什么要把硬件層和應用程序隔開,答案是——安全。允許應用程序隨意訪問硬件是一件很危險的事情,除了可能會造成藍屏死機之類的問題,還會發生密碼的安全性問題。那在我們日常開發過程當中哪 些場景需要涉及到硬件與軟件的交互呢? 二、應用程序與硬件交互的場景 1.讀取硬件信息 當應用程序需要與硬件進行捆綁時,就需要獲取對應的硬件信息,例如觸摸框綁定、MCU綁定等等,需要讀取出對應硬件的信息,并與預期的信息進行比較來判斷是否進行了綁定。獲取MCU版本號等等。 2.與硬件進行通信 應用程序與硬件進行通信,比單純的讀取硬件信息稍微復雜一點。例如通過MCU來進行定時開關機,首先需要根據對應的信息查找指定的MCU設備,然后將對應的定時開關機指定發送給MCU,MCU收到信息之后,發送信息給應用程序,告之 定時開關機的指定是否設置成功。這其中包含了應用程序與硬件之間的通信。 3.硬件的管理 例如磁盤的管理,我們可以自己編寫應用程序對磁盤進行一系列的管理,磁盤分區、磁盤大小等等。移動設備管理工具等等都可以實現。 4.其他 當然還有很多很多啦.... 那么,既然我們提到了這么多得應用場景,那我們如何來實現它們呢?那接下來就不得不提SetupDi這一系列API了。 三、SetupDi API 1.HidD_GetHidGuid 函數定義 BOOL Hidd_GetHidGuid( &guidHID 指向GUID類型的指針 ); HID類設備是通過GUID類型值作標識的,調用函數HidD_GetHidGuid顆獲得HID設備的標識 2.SetupDiGetClassDevs 函數定義   HDEVINFO   SetupDiGetClassDevs(   const GUID *ClassGuid,//HID類設備是通過GUID類型值作標識的,如圖1.圖Guid示例,通過指向Guid的指針,獲取對應的設備列表。   PCTSTR Enumerator,   HWND hwndParent,   DWord Flags//Flags,當值為DIGCF_ALLCLASSES,該函數會將*ClassGuid忽略掉。   ); 獲取一個指定類別或全部類別的所有已安裝設備的信息,其中兩個參數需要注意一下。返回值,如果函數運行成功,返回設備信息結構的句柄,該結構包含與指定參數匹配的所有已安裝設備。如果失敗,則返回INVALID_HANDLE_VALUE。 3.SetupDiEnumDeviceInterfaces 函數定義 BOOL SetupDiEnumDeviceInterfaces( HDEVINFO DeviceInfoSet, //一個指向設備信息集合的句柄,包含設備接口返回信息,通常是SetupDiGetClassDevs的返回 PSP_DEVINFO_DATA DeviceInfoData, //指向特定設備的SP_DEVINFO_DATA 類型的指針, const GUID *InterfaceClassGuid, //指向制定設備接口類的GUID指針 DWORD MemberIndex, //設備信息中接口列表的索引值(初始值為0) PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData //指向調用者分配的SP_DEVICE_INTERFACE_DATA類型的內存區域的指針,調用前必須先配置DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA) ); 獲取設備列表中指定接口的信息,通過次接口只能獲取接口信息,需要取得接口的詳細信息需要調用SetupDiGetDeviceInterfaceDetail這個接口。返回值,ture則成功,false為失敗。 4.SetupDiGetDeviceInterfaceDetail BOOL SetupDiGetDeviceInterfaceDetail( IN HDEVINFO DeviceInfoSet,//指向設備信息集的指針,它包含了所要接收信息的接口。該句柄通常由SetupDiGetClassDevs函數返回。 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,//一個指向SP_DEVICE_INTERFACE_DETAIL_DATA結構的指針,該結構用于接收指定接口的信息 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData..OPTIONAL, IN DWORD DeviceInterfaceDetailDataSize,//緩沖的大小。該緩沖的大小不能小于 (offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA, DevicePath) + sizeof(TCHAR)) 字節。 OUT PDWORD RequiredSize..OPTIONAL, OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL ); 返回設備接口的詳細信息。這里需要特別提一下的是,該接口需要調用兩次,因為該接口主要是獲取設備的路徑而路徑會放到DeviceDetailData面, 然而每一個設備的路徑是不一樣的, 所以大小不一定, 所以需要調用兩次,第一次 獲取路徑的大小,第二次獲取具體的路徑信息。返回值,ture則成功,false為失敗。 5.CreateFile 函數定義 HANDLE CreateFile(   LPCTSTR lpFileName, //設備路徑   DWORD dwDesiredaccess, //訪問模式(寫/讀)   DWORD dwShareMode, //共享模式   LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全屬性的指針   DWORD dwCreationDisposition, //如何創建   DWORD dwFlagsAndAttributes, //文件屬性   HANDLE hTemplateFile //用于復制文件句柄   ); 與設備建立連接,獲取相應的屬性(設備的供應商標識與產品標識等),應用程序就能夠與對應的設備進行通信了。如果調用成功,該函數返回文件的句柄;如果調用失敗,則返回INVALID_HANDLE_VALUE,在打開通信設備時,應該以獨占方式打開。 6.HidD_GetAttributes 函數定義 HidD_GetAttributes( SafeFileHandle hidDeviceObject,//對應與選定設備的句柄 out HiddAttributes attributes,//指向HIDD_ATTRIBUTES類型的指針 ); //設備屬性結構體 struct HiddAttributes { int Size; ushort VendorId; ushort PRoductId; ushort VersionNumber; }; 獲取設備的屬性 已經介紹了這么多SetupDi API,那我們如何來利用這些API來實現我們的需求呢?下面就來介紹一下這些API一般情況下使用的步驟。 四、Setup API使用步驟 以下相關代碼片段為C#。 1.調用HidD_GetHidGuid,獲取Hid設備的Guid。當然,假如我們只需要獲取磁盤相關設備的列表,且知道磁盤的Guid為53f56307-b6bf-11d0-94f2-00a0c91efb8b。則無須調用HidD_GetHidGuid函數。 示例代碼: var hUsb = Guid.Empty; // 取得hid設備全局id HidD_GetHidGuid(ref hUsb); 2.執行第1步,或者說知道指定的Guid,調用SetupDiGetClassDevs函數,獲取Guid對應的設備集合。 示例代碼: //取得一個包含所有HID接口信息集合的句柄 var hidInfoSet = SetupDiGetClassDevs(ref hUsb, 0, IntPtr.Zero, Digcf.DIGCF_PRESENT | Digcf.DIGCF_DEVICEINTERFACE); 3.通過第2步,獲取對應的設備列表,我們就可以獲取其中某個接口的相關信息,這個時候,需要調用SetupDiEnumDeviceInterfaces來獲取接口的信息了。 4.執行完第3步之后,則需要調用SetupDiGetDeviceInterfaceDetail來獲取接口的詳細信息,主要是獲取對應設備的路徑,此函數必須連續調用兩次,詳情見接口說明。 第3、4步的示例代碼: for (index = 0; index < MaxUsbDevices; index++) { //得到第index個接口信息 if (SetupDiEnumDeviceInterfaces(hidInfoSet, IntPtr.Zero, ref hUsb, index, ref interfaceInfo)) { int buffsize = 0; // 取得接口詳細信息:第一次讀取錯誤,但可以取得信息緩沖區的大小 SetupDiGetDeviceInterfaceDetail(hidInfoSet, ref interfaceInfo, IntPtr.Zero, buffsize, ref buffsize, null); //構建接收緩沖 var pDetail = Marshal.AllocHGlobal(buffsize); var detail = new SpDeviceInterfaceDetailData { cbSize = Marshal.SizeOf(typeof(SpDeviceInterfaceDetailData)) }; Marshal.StructureToPtr(detail, pDetail, false); if (SetupDiGetDeviceInterfaceDetail(hidInfoSet, ref interfaceInfo, pDetail, buffsize, ref buffsize, null)) { deviceList.Add(Marshal.PtrToStringAuto((IntPtr)((int)pDetail + 4))); } Marshal.FreeHGlobal(pDetail); } } 5.執行完第4步后,可以獲取到設備的路徑,通過調用CreateFile與設備創建連接之后調用HidD_GetAttributes獲取設備對應的屬性,執行完這一步,我們就可以完成上述應用場景中的MCU、觸摸框等相關硬件的綁定,以及與應用程序通信 了,如圖2. PID,VID屬性。例如MCU的供應商標識為0x1ff7,產品標識為0x0f13,應用程序實現MCU綁定了。 示例代碼: //建立和設備的連接 _device = CreateFile(device, Desiredaccess.GENERIC_READ | Desiredaccess.GenericWrite, 0, 0, Creationdisposition.OPEN_EXISTING, Flagsandattributes.FILE_FLAG_OVERLAPPED, 0); if (_device.IsInvalid) continue; HiddAttributes attributes; //獲取連接屬性 HidD_GetAttributes(_device, out attributes); if (attributes.VendorId == vId && attributes.ProductId == pId) { IntPtr preparseData; HidpCaps caps; HidD_GetPreparsedData(_device, out preparseData); //獲取設備具體信息 HidP_GetCaps(preparseData, out caps); HidD_FreePreparsedData(preparseData);//?? OutputReportLength = caps.OutputReportByteLength;//獲取設備接收到字節的長度 InputReportLength = caps.InputReportByteLength;//獲取設備發送的字節的長度 //根據設備初始化FileStream實例,通過流來實現數據接收與發送 _hidDevice = new FileStream(_device, FileAccess.ReadWrite, InputReportLength, true); _deviceOpened = true; return true; } 總結:

通過調用上述API,以及執行對應的步驟,就能夠應用程序實現硬件綁定,與硬件進行交互,當然,其中可能會遇到一些問題,需要有耐心,一步一步來。關于磁盤管理、識別大容量的移動設備等,在本文中沒有講到, 由于時間關系,過幾天另起一章總結一下磁盤相關的知識。

相關圖片:

QQ2mEnZRq0XUBEWhFSEJWY5wCeQgQO7d953fH/Pu7Ox77SbZTUJ8v/DZzDvvM888M/vufN9nToQxhihg27Z3b54/H2NACDAAAsAYPnjv3fkL5kcjOx3ke8QMBEHgGfh8Pp/P5/WDXJJ4QRDYhL1dFB06dOjoBBBCCCGO4wwGA8dxsbGxBoMhJiaGfLIwMOA4DjEgesLMMSZKJcFYqD1zBgC2HFtW1Rz3q3QnABL0RjnKUGRNypcdHR0dHR2tra3t7e1tbW2UPglxUvrs7ULo0KFDRydAWTMmJiY2NnbAgAFxcXGxDHieFwRBEITY2Fg2IcdxVEOncowWcfI8jzF+97330BQEANvefW/B/O/yPK+ewm1DFicJWl3YYe563m4bsjiDdHiKs0155QAAWUXVZXYjI+wpzjblAY0NSHbXip4EdTfJp+AHZc2Ojo729vbW1tampqZmP9rb2wl36sSpQ4eOixeEOAlrxsfHJyQkDBw4MCEhIT4+Pi4uzufzDRgwgLRvbBJClsTvxBjTz3ByjB5xCiSQM/aVHATbat7DGFSJ00912CxeZhebgvmNwFOcbapYrcFnhAat1qxg7aa8TBcuMwO4bWhZcU5Atad42WbIYiSXwUaMjaImm/sioU7yldMw+e4lDwHGuKWlpbGxsb6+vr6+/syZM5s2bWI1SAI6Ig76HSm+neivLDp0dBM5OTnJyckjR44kXMP5wfN8TEwMy50kIOmkjXxX7fbt2z/77LOHHnooTHmvz4cQYDLICQAYI4R8vE9J1m2TOIhmR1kX+cpoL8N28BRnOysC6kucWUXVRKE5v6hgWanH7ncvl21esnF1halAnrExZ0nW5ioPmOX03bfBepx0XLO9vb2lpaW+vv706dONjY3PP/98bGzsr3/96x//+Me9bW9k0POs080cO5U8fOFIqY34re6ja6904acKKRmmqs7aGalX1R5+5Y2Pj7/nFvOrW9/tyUzVcNfC+S9vcb/00ktFRUVer/f2228fO3Ys6UuTdKQR35QEBEFgBzg7hbCI88MPP1y5cqXX6w1JnBUVFf/6178++OCDnTt3xsbGjho92nPgwALzAgAAwB0dXoU0LLEF4CnONm1eIvageoqzTZshq7y8HAAsyCl2uAZ6d2U9sBoor6gGMPpps8xYbVMUq64oz8y9qFhTMjOI7aptb29vamqqr69vbGxcs2bN73//+1tvvbW2tnb//v0Q/JOL1M8vIm1omEoi6MCFo6oLl/Sny/6GBUGQBNgw2/0eToDNV9G1lfTny3OUmCcxG4IfMMWsiSp5HapVkeLDJomUyyg+rtqRIQPy6SGKl2rxIcXUTFWUVLzUrge1GDki9X4wZcoUgfed+aK85egRAxL9Iw6AAwDABgAEwAEgAAQAIDDh0CDOoAAAwGEADCAAYAAeAAAJAOSRxRh4DAMvGy/wvrNnz1599dXbt28vLS1dtWrVsmXLQFZvpFeWfhLQR7pTTV9o4iSsmZmZuXv37pDCTz755NixYx966KFvvjl983dvWrPmzxcuXHjmmWdybrkVAHm9SsSpDKN9tTWvgDiHntLN5dbV2GFmu2rdNlSQUc30q6ap9KuaMrLK8wrddocZwF2YVw5WAABP8bK8zNXYCFCtlMhts+wtqnaEbW6vg23aJB5nR0dHS0tLU1NTbW2t0+n8/e9//53vfKempkY+nSxSHbbdZ83uUGY4ydUIUrvg4VMCyNhLwp0YY/LmKwiC5NerSE4agTApU0MgZFnYsQDwPx7UWiovqT2WklkBKqbIoNjfh6Z4KYmhYVaVJFIe0CiXoqQkPuSlvHIktyQFZDWoVYJi7UkqXF5XcoT5kIfTAvACCD4efF7ez5ECEgCAE5kPBACDX1ig

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄浦区| 宜兴市| 商城县| 阿尔山市| 德江县| 左贡县| 桑日县| 固阳县| 石泉县| 诸城市| 岢岚县| 武宣县| 金寨县| 平山县| 临汾市| 鹰潭市| 南皮县| 招远市| 和林格尔县| 峨边| 都江堰市| 衡东县| 普兰县| 于都县| 斗六市| 淮南市| 收藏| 绥滨县| 天水市| 岗巴县| 永春县| 韶关市| 惠安县| 抚州市| 云霄县| 澄城县| 长乐市| 洞头县| 余江县| 怀宁县| 太白县|