经常会在编写流驱动接口的时候必须实现一系列的接口,诸如 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
posted on 2008-05-05 02:15
放屁阿狗 阅读(862)
评论(0) 编辑 收藏 引用 所属分类:
WINCE