经常会在编写流驱动接口的时候必须实现一系列的接口,诸如 xxx_init,xxx_open,xxx_write等等,某些接口函数虽然无需功能的实现但也必须定义一个空的函数接口。由于多年的c++思路,利用虚函数(virtual)和重载(override)把这些驱动的实现封装起来,来简化代码量。 程序的实现,采用了两种方式: 宏定义和类继承 希望对编写wince 流驱动的开发人员有所帮助
1 /* 2 driverbase.h 3 scott 2008.1.1 4 5 */ 6 7 #ifndef _DRIVERBASE_H 8 #define _DRIVERBASE_H 9 10 #include <windows.h> 11 #include <types.h> 12 #include <excpt.h> 13 #include <tchar.h> 14 #include <cardserv.h> 15 #include <cardapi.h> 16 #include <tuple.h> 17 #include <devload.h> 18 #include <diskio.h> 19 #include <nkintr.h> 20 #include <windev.h> 21 22 /** 23 class SimpleInterruptHandler 24 example: 25 New_InterruptHandler(irq12) 26 New_InterruptHandler(irq13) 27 class MyDriver:public InterruptHandlerClassName(irq12),public InterruptHandlerClassName(irq13){ 28 public: 29 void run_irq12(){ 30 while( !broken_irq12() ){ 31 //repeate doing interrupt 32 } 33 } 34 void run_irq13(){ 35 36 } 37 } 38 MyDriver driver; 39 driver.set_irq_irq12(IRQ_ADC); 40 driver.start_irq12(); 41 driver.start_irq13(); 42 driver.stop_irq12(); 43 ======== 44 driver 能处理多种中断,但是每个中断处理必须消耗一个线程资源 45 **/ 46 47 #define INVALID_IRQ_VALUE 0xffff 48 #define InterruptHandlerClassName(cls) SimpleInterruptHandler_##cls 49 #define New_InterruptHandler(cls) \ 50 class SimpleInterruptHandler_##cls{\ 51 public:\ 52 SimpleInterruptHandler_##cls(){\ 53 set_irq_##cls(INVALID_IRQ_VALUE); \ 54 _irq_sys = INVALID_IRQ_VALUE;\ 55 _ev_exit = CreateEvent(NULL, TRUE, FALSE, NULL);\ 56 _broken = false;\ 57 }\ 58 ~SimpleInterruptHandler_##cls(){\ 59 CloseHandle(_ev_exit);\ 60 }\ 61 void set_irq_##cls(DWORD irqhw){\ 62 _irq_hw = irqhw;\ 63 }\ 64 bool start_##cls(){\ 65 if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &_irq_hw, sizeof(DWORD), &_irq_sys, sizeof(DWORD), NULL)){\ 66 return false;\ 67 }\ 68 _evInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);\ 69 if( !_evInterrupt ){\ 70 KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &_irq_sys, sizeof(DWORD), 0, 0, NULL);\ 71 return false;\ 72 }\ 73 if(!InterruptInitialize(_irq_sys,_evInterrupt,NULL,NULL)){\ 74 return false;\ 75 }\ 76 DWORD threadID;\ 77 CreateThread(0, 0, (LPTHREAD_START_ROUTINE) SimpleInterruptHandler_##cls::entry, (LPVOID)this, 0, &threadID);\ 78 return true;\ 79 }\ 80 void stop_##cls(){\ 81 _broken = true;\ 82 WaitForSingleObject(_ev_exit,INFINITE);\ 83 CloseHandle(_evInterrupt);\ 84 KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &_irq_sys, sizeof(DWORD), 0, 0, NULL);\ 85 }\ 86 protected:\ 87 bool broken_##cls(){\ 88 return _broken;\ 89 }\ 90 virtual void run_##cls(){}\ 91 private:\ 92 static void entry(void * user){\ 93 SimpleInterruptHandler_##cls* h = (SimpleInterruptHandler_##cls*) user;\ 94 ResetEvent(h->_ev_exit);\ 95 h->_broken = false;\ 96 h->run_##cls();\ 97 SetEvent(h->_ev_exit);\ 98 }\ 99 private:\ 100 DWORD _irq_hw;\ 101 DWORD _irq_sys;\ 102 HANDLE _evInterrupt;\ 103 HANDLE _ev_exit;\ 104 bool _broken;\ 105 }; 106 107 108 // second method, binding function of class 109 // base template interrupt handle 110 class InterruptHandler{ 111 public: 112 InterruptHandler(void * user){ 113 _irq_sys = INVALID_IRQ_VALUE; 114 _ev_exit = CreateEvent(NULL, TRUE, FALSE, NULL); 115 _broken = false; 116 } 117 ~InterruptHandler(){ 118 CloseHandle(_ev_exit); 119 } 120 void * get_user(){ return _user;} 121 bool broken(){ 122 return _broken; 123 } 124 125 public: 126 DWORD _irq_hw; 127 DWORD _irq_sys; 128 HANDLE _evInterrupt; 129 HANDLE _ev_exit; 130 bool _broken; 131 void * _user; 132 }; 133 134 template <typename T> 135 class SimpleInterruptHandler:public InterruptHandler{ 136 public: 137 SimpleInterruptHandler(T* user):InterruptHandler((void*)user){ 138 _entry = NULL; 139 } 140 ~SimpleInterruptHandler(){ 141 } 142 void bind_entry( void (T::*entry)(InterruptHandler*) ){ 143 _entry = entry; 144 } 145 void set_irq(DWORD irq){ //设置硬件中断编号 146 _irq_hw = irq; 147 } 148 bool start(){ 149 if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &_irq_hw, sizeof(DWORD), &_irq_sys, sizeof(DWORD), NULL)){ 150 return false; 151 } 152 _evInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL); 153 if( !_evInterrupt ){ 154 KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &_irq_sys, sizeof(DWORD), 0, 0, NULL); 155 return false; 156 } 157 if(!InterruptInitialize(_irq_sys,_evInterrupt,NULL,NULL)){ 158 return false; 159 } 160 DWORD threadID; 161 CreateThread(0, 0, (LPTHREAD_START_ROUTINE) SimpleInterruptHandler<T>::entry, (LPVOID)this, 0, &threadID); 162 return true; 163 } 164 void stop(){ 165 _broken = true; 166 WaitForSingleObject(_ev_exit,INFINITE); 167 CloseHandle(_evInterrupt); 168 KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &_irq_sys, sizeof(DWORD), 0, 0, NULL); 169 } 170 private: 171 static void entry(void * user){ 172 SimpleInterruptHandler<T>* h = (SimpleInterruptHandler<T>*) user; 173 ResetEvent(h->_ev_exit); 174 175 h->_broken = false; 176 if( h->_entry ){ 177 (((T*)h->_user)->*h->_entry)( h); 178 } 179 SetEvent(h->_ev_exit); 180 } 181 private: 182 void (T::*_entry)(InterruptHandler*); 183 }; 184 185 186 187 188 189 190 //class StreamDriver 191 // 流接口设备驱动基础类 192 193 class StreamDriver{ 194 public: 195 StreamDriver(){} 196 virtual ~StreamDriver(){}; 197 virtual BOOL Close(DWORD hOpenContext ){ 198 return TRUE; 199 } 200 virtual BOOL Deinit(DWORD hDeviceContext ){ 201 return TRUE; 202 } 203 virtual DWORD Init(LPCTSTR pContext,LPCVOID lpvBusContext){ 204 return DWORD(this); 205 } 206 virtual BOOL IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut ){ 207 return TRUE; 208 } 209 virtual DWORD Open(DWORD hDeviceContext,DWORD AccessCode,DWORD ShareMode ){ 210 return NULL; 211 } 212 virtual void PowerDown(DWORD hDeviceContext ){} 213 virtual void PowerUp(DWORD hDeviceContext ){} 214 virtual BOOL PreClose(DWORD hOpenContext ){ 215 return TRUE; 216 } 217 virtual BOOL PreDeinit(DWORD hDeviceContext ){ 218 return TRUE; 219 } 220 virtual DWORD Read(DWORD hOpenContext,LPVOID pBuffer,DWORD Count ){ 221 return 0; 222 } 223 virtual DWORD Seek(DWORD hOpenContext,long Amount,WORD Type ){ 224 return 0; 225 } 226 virtual DWORD Write(DWORD hOpenContext,LPCVOID pBuffer,DWORD Count ){ 227 return 0; 228 } 229 private: 230 231 }; 232 233 #define DRIVER_ENTRY_CLOSE(prefix,pcls) \ 234 BOOL prefix##_Close(DWORD hOpenContext ){\ 235 return pcls->Close(hOpenContext); \ 236 } 237 #define DRIVER_ENTRY_DEINIT(prefix,pcls) \ 238 BOOL prefix##_Deinit(DWORD hDeviceContext ){\ 239 return pcls->Deinit(hDeviceContext); \ 240 } 241 #define DRIVER_ENTRY_INIT(prefix,pcls) \ 242 BOOL prefix##_Init(LPCTSTR pContext,LPCVOID lpvBusContext ){\ 243 return pcls->Init( pContext,lpvBusContext ); \ 244 } 245 #define DRIVER_ENTRY_IOCONTROL(prefix,pcls) \ 246 BOOL prefix##_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut ){\ 247 return pcls->IOControl( hOpenContext, dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut ); \ 248 } 249 #define DRIVER_ENTRY_OPEN(prefix,pcls) \ 250 BOOL prefix##_Open(DWORD hDeviceContext,DWORD AccessCode,DWORD ShareMode ){\ 251 return pcls->Open(hDeviceContext,AccessCode,ShareMode); \ 252 } 253 #define DRIVER_ENTRY_POWERDOWN(prefix,pcls) \ 254 void prefix##_PowerDown(DWORD hOpenContext ){\ 255 pcls->PowerDown(hOpenContext); \ 256 } 257 #define DRIVER_ENTRY_POWERUP(prefix,pcls) \ 258 void prefix##_PowerUp(DWORD hOpenContext ){\ 259 pcls->PowerUp(hOpenContext); \ 260 } 261 #define DRIVER_ENTRY_PRECLOSE(prefix,pcls) \ 262 BOOL prefix##_PreClose(DWORD hOpenContext ){\ 263 return pcls->PreClose(hOpenContext); \ 264 } 265 #define DRIVER_ENTRY_PREDEINIT(prefix,pcls) \ 266 BOOL prefix##_PreDeinit(DWORD hOpenContext ){\ 267 return pcls->PreDeinit(hOpenContext); \ 268 } 269 270 #define DRIVER_ENTRY_READ(prefix,pcls) \ 271 BOOL prefix##_Read(DWORD hOpenContext,LPVOID pBuffer,DWORD Count ){\ 272 return pcls->Read( hOpenContext, pBuffer, Count); \ 273 } 274 #define DRIVER_ENTRY_SEEK(prefix,pcls) \ 275 BOOL prefix##_Seek(DWORD hOpenContext,long Amount,WORD Type){\ 276 return pcls->Seek( hOpenContext, Amount, Type); \ 277 } 278 #define DRIVER_ENTRY_WRITE(prefix,pcls) \ 279 BOOL prefix##_Write(DWORD hOpenContext,LPCVOID pBuffer,DWORD Count ){\ 280 return pcls->Write( hOpenContext, pBuffer, Count); \ 281 } 282 283 #define DRIVER_DLLENTRY \ 284 BOOL DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved){\ 285 switch ( dwReason ) {\ 286 case DLL_PROCESS_ATTACH:\ 287 DisableThreadLibraryCalls((HMODULE) hInstDll);\ 288 break;\ 289 }\ 290 return (TRUE);\ 291 } 292 293 /** 294 定义流式驱动入口接口函数 295 NEW_DRIVER_ENTRIES(prefix,pcls) 296 prefix 驱动类别前缀 297 pcls 必须是StreamDriver的 子类实现对象地址 298 299 example: 300 class PowerKeyDriver:public StreamDriver{}s 301 PowerKeyDriver pkdrv; 302 NEW_DRIVER_ENTRIES("PWK",&pkdrv); 303 */ 304 305 #define NEW_DRIVER_ENTRIES(prefix,pcls) \ 306 DRIVER_ENTRY_CLOSE(prefix,(pcls))\ 307 DRIVER_ENTRY_DEINIT(prefix,(pcls))\ 308 DRIVER_ENTRY_INIT(prefix,(pcls))\ 309 DRIVER_ENTRY_IOCONTROL(prefix,(pcls))\ 310 DRIVER_ENTRY_OPEN(prefix,(pcls))\ 311 DRIVER_ENTRY_POWERDOWN(prefix,(pcls))\ 312 DRIVER_ENTRY_POWERUP(prefix,(pcls))\ 313 DRIVER_ENTRY_PRECLOSE(prefix,(pcls))\ 314 DRIVER_ENTRY_PREDEINIT(prefix,(pcls))\ 315 DRIVER_ENTRY_READ(prefix,(pcls))\ 316 DRIVER_ENTRY_SEEK(prefix,(pcls))\ 317 DRIVER_ENTRY_WRITE(prefix,(pcls))\ 318 DRIVER_DLLENTRY 319 320 #define DBGMSG(m) RETAILMSG(1,m) 321 322 #endif 323
测试代码:
1 2 #include "driverbase.h" 3 4 5 //基于宏的中断处理方法 6 //扩展函数命名实现在容器中自由定义中断处理过程 7 New_InterruptHandler(touch); 8 New_InterruptHandler(pwrkey); 9 class test_interrupt:public InterruptHandlerClassName(touch),public InterruptHandlerClassName(pwrkey){ 10 public: 11 void run_touch(){ 12 while( !broken_touch() ){ 13 } 14 } 15 void run_pwrkey(){ 16 } 17 void driver_start(){ 18 set_irq_touch(10); 19 start_touch(); 20 } 21 void driver_terminate(){ 22 stop_touch(); // it will block until working thread endding 23 } 24 }; 25 26 27 28 class test_drv:public StreamDriver{ 29 public: 30 DWORD Init(LPCTSTR pContext,LPCVOID lpvBusContext){ 31 DBGMSG( (TEXT("Init::test driver %d"),1)); 32 ::MessageBox(NULL,L"Init() Test",L"",MB_OK); 33 return NULL; 34 } 35 BOOL Deinit(DWORD hDeviceContext ){ 36 DBGMSG( (TEXT("DeInit::test driver %d"),2)); 37 ::MessageBox(NULL,L"DeInit() Test",L"",MB_OK); 38 return TRUE; 39 } 40 }; 41 42 test_drv driver; 43 44 NEW_DRIVER_ENTRIES(TST,&driver); 45 46 /* 47 [HKEY_LOCAL_MACHINE\Drivers\BuiltIn_\test] 48 "Order"=dword:0 49 "Prefix"="TST" 50 "Dll"="test.dll" 51 52 53 test.dll $(_FLATRELEASEDIR)\test.dll NK SH 54 55 */ 56 57 //example 3. 58 class MyDriver2{ 59 public: 60 MyDriver2():itTouch(this){ 61 } 62 void do_irq_touch(InterruptHandler* h){ 63 // touch irq will come in 64 //这里判别中断类型等信息 65 while(!h->broken()){ 66 //if exception occur or completed, jump out 67 break; 68 } 69 } 70 void start(){ 71 itTouch.set_irq(10); 72 itTouch.bind_entry(&MyDriver2::do_irq_touch); 73 itTouch.start(); 74 } 75 void stop(){ 76 itTouch.stop(); //将等待中断处理线程完全退出 77 } 78 private: 79 SimpleInterruptHandler<MyDriver2> itTouch; 80 }; 81 82
|