SPOT the Geek and Windows CE Drivers_第1頁
SPOT the Geek and Windows CE Drivers_第2頁
SPOT the Geek and Windows CE Drivers_第3頁
SPOT the Geek and Windows CE Drivers_第4頁
SPOT the Geek and Windows CE Drivers_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

1、SPOT the Geek and Windows CE Drivers  Microsoft Windows ChallengE2Understanding the Purpose of a Device Driver3Example APIs3Dynamic-Link Library3Creating a Stream Driver4Functions5Figure 1: The Remote Registry Editor6Write Function8Read Function9Void Functions10IO Control Function11Testing the

2、Functions17Registry Entries18Order18Index19Testing the Driver19Figure 3: Windows CE Remote System Information window20Figure 4: List of loaded modules20Watches running Smart Personal Object Technologies (SPOT) became publicly available at this year's Consumer Electronics Show (CES). Fossil and S

3、uunto are the first companies shipping products (a list of watches can be found on the MSN Direct Web site). You might be asking what this has to do with Microsoft® Windows® CE, and that's an excellent question to which I don't have a good answer. This is a cool (read geeky) watch.

4、 I have an Abacus SPOT watch and am impressed with the watch and the MSN® Direct service. I'm currently signed up to receive weather (which for some reason always shows rain in Seattle!), stock quotes, news alerts, instant messages, and my calendar. Interestingly, the SPOT watch automatical

5、ly adjusts for new time zoneshow useful is that! I've been presenting at the Windows® Embedded Essentials events in Korea and Taiwan, so my SPOT watch was still set for Korea time. While I was waiting to clear customs at the Seattle airport, I noticed that the watch had adjusted to Redmond

6、time and within minutes I started to receive news and calendar items.You are probably wondering how to configure the serviceit's actually extremely simple. Each watch contains a unique ID (think GUID). When you power up the watch for the first time the GUID is displayed on the screen. After you

7、power up, you need to go to and complete a registration form, which links your watch GUID to your passport account. Then you sign up for whichever services you are interested in. Right now news, weather, stock, calendar, new watch faces, and instant messages are supported. There are plans to expand

8、on this lineup in the near future with additional channels.OK, that's enough of SPOT, now let's take a look at device drivers on Windows CE.Microsoft Windows ChallengEThe Microsoft Embedded Devices Group, in collaboration with the Institute of Electrical and Electronics Engineers, Inc. (IEEE

9、) Computer Society International Design Competition (CSIDC) have invited student teams to participate in the first official Microsoft Windows ChallengE ("ChallengE"). The theme of the 2004 competition is "Making the World a Safer Place." Right now teams are building devices based

10、 on Windows CE .NET 4.2. Each team is responsible for building a custom operating system image and any required applications or drivers. Since many teams are new to Windows CE, we've been receiving a number of questions about how to customize the operating system. Most teams are adding additiona

11、l peripherals to their base hardware platform and have been asking about device drivers. Therefore, this month's article is going to take you through the process of creating, building, and testing a stream driver on Windows CE. One of the common ways of interfacing with a driver is through IO Co

12、ntrol, or IOCTL, so we will also implement this functionality in the driver.Understanding the Purpose of a Device DriverBefore we dig into the process of writing drivers, it may be good to understand the purpose of a device driver: Drivers abstract the underlying hardware from the operating system a

13、nd better still from an application developer. An application developer shouldn't need to know the specifics of your display hardware, or your serial hardware. Windows exposes application programming interfaces (API) for a developer to call into the hardware but the developer does not need to kn

14、ow what the physical hardware is (that's the beauty of APIs). Example APIsFor example, take writing to a serial portan application developer simply: 1. Calls CreateFile( ) on COMx 2. Calls WriteFile( ) to write some bytes of data to the serial port 3. Calls CloseHandle( ) to close the serial por

15、t The same sequence of APIs works no matter what the underlying serial hardware is (or which Windows operating system you are running on). The same is also true of other APIs. If we want to output a line to the display surface we would simply call PolyLine( ), or MoveToEx( ), LineTo( ). For the most

16、 part, as an application developer you don't need to know what display hardware is, there are APIs to call, which return the dimensions of the display surface, the color depth, and so on. The good news is that developers have a consistent, well known set of APIs to call, which abstract their app

17、lication from the underlying hardware. For computer application developers, this is crucial, because the application developer has no way of knowing whether the application will run on a laptop, Tablet PC, or desktop computer; or whether the computer is running at 1024x768 or 1600x1200. The applicat

18、ion developer can query the screen resolution and color depth at runtime and therefore doesn't need to build an application that only runs on specific hardware.Dynamic-Link LibraryA driver is simply a dynamic-link library (DLL), which is loaded into a parent process address space. The parent pro

19、cess can then call any of the interfaces exposed from the DLL. The driver is typically loaded by its parent process through a call to LoadLibrary( ) or LoadDriver( ). LoadDriver not only loads the DLL into the parent process address space but also makes sure the DLL isn't paged out.How does a ca

20、lling process know which APIs or functions are exposed from our DLL or driver? Easy, the parent process calls GetProcAddress( ), which takes the name of a function and the hInstance of the loaded DLL. The call returns a pointer to the function, if it exists, or NULL if the function is not exposed fr

21、om the DLL. Stream drivers expose a well known set of functions. Let's take the serial port example we used earlier. Since this is a stream driver we want to be able to write a stream of bytes to the device or read a stream of bytes from the device. Therefore we would expect the following set of

22、 functions to be exposed from our driver: Open, Close, Read, and Write. Stream drivers also expose some additional functions: PowerUp, PowerDown, IO Control, Init, and DeInit.Creating a Stream DriverLet's use Platform Builder to create a base operating system image for the Emulator platform. We

23、can then add our DLL/driver project to the platform. I've created a platform called "DrvDemo," which is based on the "Internet Appliance" configuration, and we will set this to be a debug image so that we can trace the debug output from the functions in our driver.Once the pl

24、atform is built and downloaded (this shows the operating system boots and runs OK), we then need to create our skeleton driver. We will use the Platform Builder New Project or File menu item to create a WCE Dynamic Link Library. There is no difference in creating a DLL to expose functions or resourc

25、es and a DLL to be used as a driverthe only difference is which functions the DLL exposes and how the DLL is registered and used on the platform. (As an aside, one way to create internationalized applications is to create a base application that contains one set of core language strings, dialogs, an

26、d resources; then create a number of external DLLs, each of which contain the dialogs, strings, and resources for a specific locale. The application can then load the appropriate language resources on the fly. Additional languages can easily be added to the application by simply adding additional DL

27、L files. This and other interesting topics are described in the book Developing International Software, by Microsoft Press, originally written by Nadine Kano (the second edition was updated by Dr. International, I guess a relative of the good Dr. GUI from MSDN.) Here's a link to the book on the

28、Microsoft Press Web site. This title should be available at all good bookstores, and online through A or Barnes & Noble.)Right, back to the driverI'm going to name the DLL project "MyDriver," a simple Windows CE DLL Project. This generates a "bare bones" DLL. Here's t

29、he code that's generated for us.Copy Code/ MyDriver.cpp : Defines the entry point for the DLL application./#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) return TRUE; Cool, eh? All that code written for us; what is left for us to

30、 do ? The DLL exposes one function, DllMain, which is the entry point to our DLL. The entry point for our DLL can be called in four situations: Process Attach, Process Detach, Thread Attach, and Thread Detach. The reason for calling the DLL entry point is passed into DllMain through the DWORD ul_rea

31、son_for_call parameter. We can switch on this to determine why the entry point has been called, like so:Copy CodeBOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) switch ( ul_reason_for_call ) case DLL_PROCESS_ATTACH: OutputDebugString(L"MyDriver - DLL_PROCESS

32、_ATTACHn"); break; case DLL_PROCESS_DETACH: OutputDebugString(L"MyDriver - DLL_PROCESS_DETACHn"); break; case DLL_THREAD_ATTACH: OutputDebugString(L"MyDriver - DLL_THREAD_ATTACHn"); break; case DLL_THREAD_DETACH: OutputDebugString(L"MyDriver - DLL_THREAD_DETACHn");

33、 break; return TRUE; FunctionsHere's the list of functions we need to expose for our driver, where XXX_ denotes the name of the driver as exposed to the operating system. For a serial driver this would be COM, where serial port 1 would be exposed as COM1. Our driver will expose its name to the o

34、perating system as DEM (for DEMo driver).FunctionDescriptionXXX_CloseCloses the device context identified by hOpenContext.XXX_DeinitCalled by the Device Manager to de-initialize a device.XXX_InitCalled by the Device Manager to initialize a device.XXX_IOControlSends a command to a device.XXX_OpenOpen

35、s a device for reading, writing, or both. An application indirectly invokes this function when it calls CreateFile to open special device file names.XXX_PowerDownEnds power to the device. It is useful only with devices that can be shut off under software control.XXX_PowerUpRestores power to a device

36、.XXX_ReadReads data from the device identified by the open context.XXX_SeekMoves the data pointer in the device.XXX_WriteWrites data to the device.So our functions are:DEM_Close, DEM_Deinit, DEM_Init, DEM_IOControl, DEM_Open, DEM_PowerDown, DEM_PowerUp, DEM_Read, DEM_Seek, and DEM_Write.Our driver i

37、s exposed as DEM1: to the operating system. OK, let's implement some functionality for the driver:First DEM_Init( )the function definition for this function is as follows:Copy CodeDWORD DEM_Init( LPCTSTR pContext, LPCVOID lpvBusContext); This takes as its first parameter, a pointer to a string c

38、ontaining the registry path to the active key for the stream interface driver. With our driver being loaded by the operating system, we get passed the following string (HKLM) DriversActive02. We can use the Remote Registry Editor to view the contents of this key.Figure 1: The Remote Registry EditorT

39、he "Key" item in the registry points to the location of the registry information for this driver: HKLMDriversBuiltInSample. We can use this information to load any registry specific information for this driver. For example, if this were a display driver we would use this information to det

40、ermine screen refresh rate or screen resolution. Since this is a simple driver, we don't have any configuration information to load from the registry.We need to return a DWORD handle to a device context if our driver initializes correctly. In our case the function will return the value of Hex 12

41、34 - 0x1234. The function would return NULL if the driver failed to initialize.Copy CodeDWORD DEM_Init( LPCTSTR pContext, LPCVOID lpvBusContext)OutputDebugString(L"MyDriver - DEM_Init - Context: ");OutputDebugString(pContext);OutputDebugString(L"n");OutputDebugString(L"MyDri

42、ver - DEM_Initn");return 0x1234; Next the DEM_Open functionthe function definition is as follows:Copy CodeDWORD DEM_Open(DWORD hDeviceContext,DWORD AccessCode,DWORD ShareMode ) The Open function is passed to the DeviceContext that we returned from the Init function, along with the access code,

43、and the share mode. These functions map directly to the parameters from the CreateFile Win32® API. In our case the driver will always open, so we simply return a valid OpenContext, in this case the value Hex 5678 0x5678.Copy CodeDWORD DEM_Open( DWORD hDeviceContext, DWORD AccessCode, DWORD Shar

44、eMode )OutputDebugString(L"MyDriver - DEM_Openn");OutputDebugString(L"hDeviceContext - ");DBGOut(hDeviceContext);OutputDebugString(L"n");OutputDebugString(L"MyDriver - DEM_Openn");return 0x5678; Now DEM_Closehere's the function definition:Copy CodeBOOL DEM

45、_Close( DWORD hOpenContext ) The Close function simply gets the OpenContext. In our case we're simply returning TRUE, which indicates the driver closed correctly.Copy CodeBOOL DEM_Close( DWORD hOpenContext )OutputDebugString(L"MyDriver - DEM_Closen");OutputDebugString(L"hOpenConte

46、xt - ");DBGOut(hOpenContext);OutputDebugString(L"n");OutputDebugString(L"MyDriver - DEM_Closen");return TRUE; Now we get to the interesting functions: Read, Write, Seek, and IOCTL. Let's start with Writehow's this going to work? For our demo driver we want an applica

47、tion to write some data (perhaps a string) to the driver. We will cache the data and then return this to the application when we call the Read interface. This is interesting because the data is cached across application runtimes; so we could run our application, call the Write function on our driver

48、, close the application, and some time later reload the application, call the Read function that then returns the data to the application. Of course a "real" stream driver would be interfacing with hardware to read and write data.Write FunctionDEM_Writehere's the function definition:Co

49、py CodeDWORD DEM_Write( DWORD hOpenContext, LPCVOID pBuffer, DWORD Count ) The Write function is passed our OpenContext handle, a pointer to a buffer, and a count of the number of bytes to be written. Remember this is bytes, not characters. Even though we might be passing a Unicode string, let's

50、 say "HELLO," this is five unicode characters or 10 bytes. When living in the Unicode world, we need to be careful of the difference between bytes and characters. It's not enough to call lstrlen( ) to get the string length. For our sample string above, this would write five bytes or &q

51、uot;Hel," which is not the desired result. (Perhaps it's time to order a copy of Developing International Software, which describes single byte character sets, double byte character sets, and Unicode in detail.)OK, so here's our Write function code. Let's walk through the codewe use

52、 OutputDebugString to write some useful entry point information to the debug window in Platform Builder. We then stumble across a variable that's not been seen before. Let me introduce you to hMem. hMem is a driver global of type HANDLE, which is defined as HANDLE hMem=NULL;.When we call the Wri

53、te routine we check to see if hMem has been allocated. If it has, we call LocalFree to free up the existing content, then allocate enough memory to store the incoming data, and memcpy to copy the inbound buffer to the memory allocated in the function. The Write function is expected to return the num

54、ber of bytes written. So, in this case we return the number of bytes we've been passed by the application.Copy CodeDWORD DEM_Write( DWORD hOpenContext, LPCVOID pBuffer, DWORD Count )OutputDebugString(L"MyDriver - DEM_Writen");OutputDebugString(L"hOpenContext - ");DBGOut(hOpen

55、Context);OutputDebugString(L"n");if (NULL != hMem) LocalFree(hMem);hMem=LocalAlloc(LPTR,Count);memcpy(hMem,pBuffer,Count);dwCount=Count;OutputDebugString(L"MyDriver - DEM_Writen");return Count; Read FunctionThat's Write function completed. We would expect the Read function to

56、 be very similarhere's the function definition:Copy CodeDWORD DEM_Read( DWORD hOpenContext, LPVOID pBuffer, DWORD Count ) The Read function returns the number of bytes written, or if we fail to read any bytes, it returns -1 (0xffff). Since an application developer may try to read bytes from our

57、driver before calling the Write function, we need to return 0xffff if we don't have any data stored. In our demo driver we output some debug information and check our hMem. If this is NULL, we simply return 0xffff. If this is not NULL, then we obviously have some data to return. We set our retur

58、n value to be the number of bytes to return to the application, copy our stored data into the buffer passed into the Read function, and then return. Note  The Read function is passed a pointer to a buffer and a count that defines the size of the buffer. In our Read function, we really should ch

59、eck to make sure the buffer is big enough to return the stored data.Copy CodeDWORD DEM_Read( DWORD hOpenContext, LPVOID pBuffer, DWORD Count )DWORD dwRetCount=0xffff; / default to errorOutputDebugString(L"MyDriver - DEM_Readn");OutputDebugString(L"hOpenContext - ");DBGOut(hOpenContext);OutputDebugString(L"n");if (NULL != hMem) dwRetCount=dwCount; memcpy(pBuffer

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論