对于wince 驱动或者linux驱动,或者其他操作系统驱动。基本上就是两个部分,1,访问硬件寄存器。2,编写操作系统接口。从访问硬件上来说,可以有总线驱动,一般的I/O驱动等。从操作系统来说,就wince而言,可以分为,built-driver和stream driver,也可以从另外的一个角度,分为 Layered Device Driver 和 Monolithic driver。总之,驱动的叫法和种类很多,一般都要根据具体开发的驱动再仔细研究。其实大多数工作都是要看E文的datasheet,了解硬件的工作原理,对CPU工作方式有一定的理解,问题就不大了。这里简单介绍一下如何编写wince下的stream driver。
首先讲一下框架,很简单,按照wince的联机帮助文档,完成下面的接口函数就好了。
XXX_IOControl (Device Manager)
。。。。
无非就是一些读写,IOCTL,POWER管理的接口而已。下面就是写的一个FOO driver,从它慢慢谈起。FOO取代了上面函数中的XXX,FOO就是说不明白的意思。呵呵。
实际上,不需要实现上面的所有函数。
FOO.h
#pragma once
#define SETFNAME(n) LPCWSTR pszFname = L##n
#define FOO_DEBUG
#ifdef FOO_DEBUG
#define DEBUG_OUT(x,y) RETAILMSG(x,y)
#elif
#define DEBUG_OUT(x,y)
#endif
#define FOO_DEV_NAME L"Foo1:"
typedef struct {
char* pBuffer1;
char* pBuffer2;
int nLen;
}COPY_STRUCT;
// {1F9A46C2-F419-4285-A78D-2553023C3C35}
DEFINE_GUID(DEVICE_IFC_FOO_GUID,
0x1f9a46c2, 0xf419, 0x4285, 0xa7, 0x8d, 0x25, 0x53, 0x2, 0x3c, 0x3c, 0x35);
//define IOCTL code
#define IOCTL_FOO_COPYCMD "
CTL_CODE(FILE_DEVICE_UNKNOWN ,0x350,METHOD_BUFFERED ,FILE_ANY_ACCESS)
#define IOCTL_FOO_LOCKBUS "
CTL_CODE(FILE_DEVICE_UNKNOWN,0x351,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_FOO_UNLOCKBUS "
CTL_CODE(FILE_DEVICE_UNKNOWN,0x352,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_FOO_XER "
CTL_CODE(FILE_DEVICE_UNKNOWN,0X353,METHOD_BUFFERED,FILE_ANY_ACCESS)
这里面定义了一个GUID,暂时驱动没有使用。还定义了IOCTL的code,代表具体的功能。
FOO.C
#include <windows.h>
#include <ddkreg.h>
#include <ceddk.h>
#include <nkintr.h>
#include <pm.h>
#include <Mmsystem.h>
#include "foo.h"
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("FOO"),
{
TEXT("Error"),TEXT("Warning"),TEXT("Init"),TEXT("IST"),
TEXT("Foo1"),TEXT("Foo2"),TEXT("Fooxx"),TEXT("Fooyy"),
TEXT(""),TEXT("Resume"),TEXT(""),TEXT(""),
TEXT(""),TEXT(""),TEXT(""),TEXT(""),
},
0x0007 // ZONE_ERROR | ZONE_WARN | ZONE_INIT
};
#endif // DEBUG
#define FOO_DEV_COOKIE 'FooD'
#define FOO_INS_COOKIE 'FooI'
#define LOCK() EnterCriticalSection(cs)
#define UNLOCK() LeaveCriticalSection(cs)
typedef struct foo_dev
{
DWORD foo_val;
DWORD dwCookie;
long instance;
//Critical section
// CRITICAL_SECTION cs;
}FOO_DEV;
typedef struct foo_instance
{
FOO_DEV *pDev;
DWORD dwCookie;
}FOO_INSTANCE;
static CRITICAL_SECTION cs;
BOOL FOO_Deinit(DWORD dwContext);
/**
* Function FOO_Init
*
* Description
* brief handles initialization of the matrix keypad driver.
*/
DWORD
FOO_Init(DWORD dwContext)
{
SETFNAME("FOO::Init");
DWORD rc = (DWORD)NULL;
FOO_DEV* pFoo;
pFoo = LocalAlloc(LPTR,sizeof(struct foo_dev));
if(pFoo==NULL)
{
DEBUG_OUT(1,(TEXT("Foo_init error,not enough mem!"r"n")));
goto cleanUp;
}
//initialize
pFoo->dwCookie = FOO_DEV_COOKIE;
//initialize the critcal section
InitializeCriticalSection(&cs);
rc = (DWORD)pFoo;
cleanUp:
if(rc==0)
{
FOO_Deinit((DWORD)pFoo);
DEBUG_OUT(1,(TEXT("Foo_Init error"r"n")));
}
return rc;
}
/**
* Function: FOO_Deinit
*
* Description
* brief handles deinitialization of the remote driver.
*/
BOOL
FOO_Deinit(DWORD dwContext)
{
SETFNAME("FOO::Deinit");
FOO_DEV *pDevice = (FOO_DEV*)dwContext;
// Delete critical section
DeleteCriticalSection(&cs);
if(pDevice!=NULL)
LocalFree(pDevice);
DEBUG_OUT(1,(TEXT("FOO_Deinit"r"n")));
return TRUE;
}
/**
* Function: FOO_Open
*
* Description
*
* Note
* This call must succeed for FOO1: to open an IOCTL channel
*/
DWORD
FOO_Open(DWORD dwContext, DWORD AccessCode, DWORD ShareMode)
{
SETFNAME("FOO::Open");
DWORD rc = (DWORD)NULL;
FOO_DEV *pFoo = (FOO_DEV *)dwContext;
FOO_INSTANCE *pIns=NULL;
DEBUG_OUT(1, (TEXT("%s"r"n"), pszFname));
if(pFoo==NULL)
{
DEBUG_OUT(1,(TEXT("Open error:error parameter"r"n")));
goto cleanUp;
}
pIns = LocalAlloc(LPTR,sizeof(struct foo_instance));
if(pIns==NULL)
{
DEBUG_OUT(1,(TEXT("Open error:error parameter"r"n")));
goto cleanUp;
}
pIns->dwCookie = FOO_INS_COOKIE;
pIns->pDev = pFoo;
// Increment number of open instances
InterlockedIncrement(&pFoo->instance);
rc = (DWORD)pIns;
cleanUp:
if(rc==0)
{
DEBUG_OUT(1,(TEXT("Open Failed"r"n")));
}
return rc;
}
/**
* Function FOO_Close
*
* Description
* brief Teardown context created by _Open
*/
BOOL
FOO_Close(DWORD dwContext)
{
SETFNAME("FOO::Close");
DWORD rc = 0;
FOO_DEV *pFoo;
FOO_INSTANCE *pIns =(FOO_INSTANCE*)dwContext;
DEBUG_OUT(1, (TEXT("%s: FOO driver close"r"n"), pszFname));
if((pIns==NULL)||(pIns->dwCookie!=FOO_INS_COOKIE))
{
DEBUG_OUT(1, (TEXT("Close Foo device error"r"n")));
return rc;
}
pFoo = pIns->pDev;
InterlockedDecrement(&pFoo->instance);
//free memory
LocalFree(pIns);
rc = TRUE;
return rc;
}
/**
* Function FOO_IOControl
*
* Description
* brief process IOCTL's
*/
BOOL
FOO_IOControl(DWORD dwContext,DWORD dwIOControlCode,
PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
BOOL bResult = FALSE;
char* pMap1;
char* pMap2;
COPY_STRUCT *pcs;
FOO_INSTANCE *pIns = (FOO_INSTANCE*)dwContext;
DEBUG_OUT(1, (
L"+FOO_IOControl(0x%x, 0x%x, 0x%x, %d, 0x%x, %d, 0x%x)"r"n",
dwContext, dwIOControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned
));
if((pIns==NULL)||(pIns->dwCookie!=FOO_INS_COOKIE))
{
DEBUG_OUT(1,(TEXT("Error:FOO_IOControl: Incorrect context parameter"r"n")));
return bResult;
}
switch(dwIOControlCode)
{
case IOCTL_FOO_COPYCMD:
if((pInBuf==NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
pcs = (COPY_STRUCT*)pInBuf;
__try{
pMap1 = MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());
pMap2 = MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());
DEBUG_OUT(1, (TEXT("+FOO_IOControl(0x%x,0x%x)"r"n"),pcs->pBuffer1,pcs->pBuffer2));
DEBUG_OUT(1, (TEXT("After map")));
DEBUG_OUT(1, (TEXT("+FOO_IOControl(0x%x,0x%x)"r"n"),pMap1,pMap2));
memcpy(pMap2,pMap1,pcs->nLen);
bResult = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER){
DEBUG_OUT(1,(TEXT("Exception:FOO_IOCTL"r"n")));
break;
}
break;
case IOCTL_FOO_LOCKBUS:
break;
%