source: trunk/src/kernel32/hmparport.cpp@ 7476

Last change on this file since 7476 was 7476, checked in by phaller, 24 years ago

added NUL device

File size: 29.7 KB
Line 
1/* $Id: hmparport.cpp,v 1.11 2001-11-29 00:20:48 phaller Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 Parallel Port device access class
7 *
8 * 2001 Patrick Haller <patrick.haller@innotek.de>
9 *
10 */
11
12
13
14#include <os2win.h>
15#include <string.h>
16#include <handlemanager.h>
17#include "handlenames.h"
18#include <heapstring.h>
19#include <winioctl.h>
20#include "hmdevice.h"
21#include "hmparport.h"
22#include "oslibdos.h"
23
24#define DBG_LOCALLOG DBG_hmparport
25#include "dbglocal.h"
26
27
28#define MAGIC_PARPORT 0x4c505431
29
30#define IOCTL_PRINTER 0x0005
31#define PRT_QUERYJOBHANDLE 0x0021
32#define PRT_SETFRAMECTL 0x0042
33#define PRT_SETINFINITERETRY 0x0044
34#define PRT_INITPRINTER 0x0046
35#define PRT_ACTIVATEFONT 0x0048
36#define PRT_SETPRINTJOBTITLE 0x004D
37#define PRT_SETIRQTIMEOUT 0x004E
38#define PRT_SETCOMMMODE 0x0052
39#define PRT_SETDATAXFERMODE 0x0053
40#define PRT_GETFRAMECTL 0x0062
41#define PRT_GETINFINITERETRY 0x0064
42#define PRT_GETPRINTERSTATUS 0x0066
43#define PRT_QUERYACTIVEFONT 0x0069
44#define PRT_VERIFYFONT 0x006A
45#define PRT_QUERYIRQTIMEOUT 0x006E
46#define PRT_QUERYCOMMMODE 0x0072
47#define PRT_QUERYDATAXFERMODE 0x0073
48#define PRT_QUERDEVICEID 0x0074
49
50
51#if 0
52#pragma pack(1)
53typedef struct _DCBINFO
54{
55 USHORT usWriteTimeout; /* Time period used for Write Timeout processing. */
56 USHORT usReadTimeout; /* Time period used for Read Timeout processing. */
57 BYTE fbCtlHndShake; /* HandShake Control flag. */
58 BYTE fbFlowReplace; /* Flow Control flag. */
59 BYTE fbTimeOut; /* Timeout flag. */
60 BYTE bErrorReplacementChar; /* Error Replacement Character. */
61 BYTE bBreakReplacementChar; /* Break Replacement Character. */
62 BYTE bXONChar; /* Character XON. */
63 BYTE bXOFFChar; /* Character XOFF. */
64} DCBINFO;
65typedef DCBINFO *PDCBINFO;
66
67
68typedef struct _RXQUEUE
69{
70 USHORT cch; /* Number of characters in the queue. */
71 USHORT cb; /* Size of receive/transmit queue. */
72} RXQUEUE;
73
74typedef RXQUEUE *PRXQUEUE;
75
76
77typedef struct _MODEMSTATUS
78{
79 BYTE fbModemOn; /* Modem Control Signals ON Mask. */
80 BYTE fbModemOff; /* Modem Control Signals OFF Mask. */
81} MODEMSTATUS;
82
83typedef MODEMSTATUS *PMODEMSTATUS;
84
85
86#pragma pack()
87
88
89#endif
90
91
92#if 0
93
94typedef struct _PARALLEL_PNP_INFORMATION {
95 PHYSICAL_ADDRESS OriginalEcpController;
96 PUCHAR EcpController;
97 ULONG SpanOfEcpController;
98 ULONG PortNumber;
99 ULONG HardwareCapabilities;
100 PPARALLEL_SET_CHIP_MODE TrySetChipMode;
101 PPARALLEL_CLEAR_CHIP_MODE ClearChipMode;
102 ULONG FifoDepth;
103 ULONG FifoWidth;
104 PHYSICAL_ADDRESS EppControllerPhysicalAddress;
105 ULONG SpanOfEppController;
106 ULONG Ieee1284_3DeviceCount;
107 PPARALLEL_TRY_SELECT_ROUTINE TrySelectDevice;
108 PPARALLEL_DESELECT_ROUTINE DeselectDevice;
109 PVOID Context;
110 ULONG CurrentMode;
111 PWSTR PortName;
112} PARALLEL_PNP_INFORMATION, *PPARALLEL_PNP_INFORMATION;
113#endif
114
115
116
117typedef struct _HMDEVPARPORTDATA
118{
119 ULONG ulMagic;
120 // Win32 Device Control Block
121 COMMCONFIG CommCfg;
122 //OS/2 Device Control Block
123} HMDEVPARPORTDATA, *PHMDEVPARPORTDATA;
124
125static VOID *CreateDevData()
126{
127 PHMDEVPARPORTDATA pData;
128 pData = new HMDEVPARPORTDATA();
129 if(NULL!=pData)
130 {
131 memset(pData,0,sizeof(HMDEVPARPORTDATA));
132 pData->ulMagic = MAGIC_PARPORT;
133 pData->CommCfg.dwSize = sizeof(COMMCONFIG);
134 pData->CommCfg.wVersion = 1;
135 pData->CommCfg.dwProviderSubType = PST_PARALLELPORT;
136 }
137 return pData;
138}
139
140
141HMDeviceParPortClass::HMDeviceParPortClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName)
142{
143 dprintf(("HMDeviceParPortClass::HMDevParPortClass(%s)\n",
144 lpDeviceName));
145
146 VOID *pData;
147 dprintf(("HMDeviceParPortClass: Register LPT1 to LPT3 with Handle Manager\n"));
148
149 pData = CreateDevData();
150 if(pData!= NULL)
151 HMDeviceRegisterEx("LPT1", this, pData);
152
153 // add symbolic links to the "real name" of the device
154 {
155 // Note: \\.\LPTx: is invalid (NT4SP6)
156 PSZ pszLPT = strdup("\\\\.\\LPTx");
157 PSZ pszLPT2 = strdup("\\Device\\ParallelPort1");
158 for (char ch = '1'; ch <= '3'; ch++)
159 {
160 pszLPT[7] = ch;
161 pszLPT2[20] = ch;
162 HandleNamesAddSymbolicLink(pszLPT, pszLPT+4);
163 HandleNamesAddSymbolicLink(pszLPT2, pszLPT+4);
164 }
165 free(pszLPT);
166 free(pszLPT2);
167
168 // add "PRN" device
169 HandleNamesAddSymbolicLink("PRN", "LPT1");
170 HandleNamesAddSymbolicLink("PRN:", "LPT1");
171 HandleNamesAddSymbolicLink("\\\\.\\PRN", "LPT1");
172 }
173}
174
175/*****************************************************************************
176 * Name : HMDeviceParPortClass::FindDevice
177 * Purpose : Checks if lpDeviceName belongs to this device class
178 * Parameters: LPCSTR lpClassDevName
179 * LPCSTR lpDeviceName
180 * int namelength
181 * Variables :
182 * Result : checks if name is COMx or COMx: (x=1..8)
183 * Remark :
184 * Status :
185 *
186 * Author : SvL
187 *****************************************************************************/
188BOOL HMDeviceParPortClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
189{
190 // can be both, "LPT1" and "LPT1:"
191 if(namelength > 5)
192 return FALSE; //can't be lpt name
193
194 //first 3 letters 'LPT'?
195 if(lstrncmpiA(lpDeviceName, lpClassDevName, 3) != 0) {
196 return FALSE;
197 }
198
199 if(namelength == 5 && lpDeviceName[4] != ':') {
200 return FALSE;
201 }
202 switch(lpDeviceName[3]) {
203 case '1':
204 case '2':
205 case '3':
206 return TRUE; //we support up to LPT3
207 }
208 return FALSE;
209}
210
211DWORD HMDeviceParPortClass::CreateFile(HANDLE hHandle,
212 LPCSTR lpFileName,
213 PHMHANDLEDATA pHMHandleData,
214 PVOID lpSecurityAttributes,
215 PHMHANDLEDATA pHMHandleDataTemplate)
216{
217 dprintf(("HMDeviceParPortClass::CreateFile(%s,%08xh,%08xh,%08xh)\n",
218 lpFileName,
219 pHMHandleData,
220 lpSecurityAttributes,
221 pHMHandleDataTemplate));
222
223 char lptname[6];
224
225 dprintf(("HMDeviceParPortClass: Parallel port %s open request\n", lpFileName));
226
227 strcpy(lptname, lpFileName);
228 lptname[4] = 0; //get rid of : (if present) (eg LPT1:)
229
230 //AH: TODO parse Win32 security handles
231 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
232 pHMHandleData->hHMHandle = OSLibDosOpen(lptname,
233 OSLIB_ACCESS_READWRITE |
234 OSLIB_ACCESS_SHAREDENYREAD |
235 OSLIB_ACCESS_SHAREDENYWRITE);
236 SetErrorMode(oldmode);
237
238 // check if handle could be opened properly
239 if (0 == pHMHandleData->hHMHandle)
240 {
241 // @@@PH we need to get an OS/2 return code from OSLibDosOpen!
242 // and translate it via error2WinError
243 return ERROR_ACCESS_DENIED; // signal failure
244 }
245
246#if 0
247 if (pHMHandleData->hHMHandle != 0)
248 {
249 ULONG ulLen;
250 APIRET rc;
251 pHMHandleData->lpHandlerData = new HMDEVPARPORTDATA();
252 // Init The handle instance with the default default device config
253 memcpy( pHMHandleData->lpHandlerData,
254 pHMHandleData->lpDeviceData,
255 sizeof(HMDEVPARPORTDATA));
256
257 ulLen = sizeof(DCBINFO);
258
259 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
260 IOCTL_ASYNC,
261 ASYNC_GETDCBINFO,
262 0,0,0,
263 &((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2,ulLen,&ulLen);
264 dprintf(("DCB Of %s :\n"
265 " WriteTimeout : %d\n"
266 " ReadTimeout : %d\n"
267 " CtlHandshake : 0x%x\n"
268 " FlowReplace : 0x%x\n"
269 " Timeout : 0x%x\n"
270 " Error replacement Char : 0x%x\n"
271 " Break replacement Char : 0x%x\n"
272 " XON Char : 0x%x\n"
273 " XOFF Char : 0x%x\n",
274 lptname,
275 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usWriteTimeout,
276 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usReadTimeout,
277 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbCtlHndShake,
278 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbFlowReplace,
279 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbTimeOut,
280 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bErrorReplacementChar,
281 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bBreakReplacementChar,
282 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXONChar,
283 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXOFFChar));
284
285 if(rc)
286 {
287 return -1;
288 }
289 rc = SetBaud(pHMHandleData,9600);
290 dprintf(("Init Baud to 9600 rc = %d",rc));
291 rc = SetLine(pHMHandleData,8,0,0);
292 dprintf(("Set Line to 8/N/1 rc = %d",rc));
293 return 0;
294 }
295 else
296 return -1;
297#endif
298
299 return NO_ERROR;
300}
301
302
303 /* this is a handler method for calls to CloseHandle() */
304BOOL HMDeviceParPortClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
305{
306 dprintf(("HMDeviceParPortClass: Parallel port close request(%08xh)\n",
307 pHMHandleData));
308 delete pHMHandleData->lpHandlerData;
309 return OSLibDosClose(pHMHandleData->hHMHandle);
310}
311
312
313/*****************************************************************************
314 * Name : BOOL HMDeviceParPortClass::WriteFile
315 * Purpose : write data to handle / device
316 * Parameters: PHMHANDLEDATA pHMHandleData,
317 * LPCVOID lpBuffer,
318 * DWORD nNumberOfBytesToWrite,
319 * LPDWORD lpNumberOfBytesWritten,
320 * LPOVERLAPPED lpOverlapped
321 * Variables :
322 * Result : Boolean
323 * Remark :
324 * Status :
325 *
326 * Author : SvL
327 *****************************************************************************/
328
329BOOL HMDeviceParPortClass::WriteFile(PHMHANDLEDATA pHMHandleData,
330 LPCVOID lpBuffer,
331 DWORD nNumberOfBytesToWrite,
332 LPDWORD lpNumberOfBytesWritten,
333 LPOVERLAPPED lpOverlapped)
334{
335 dprintf(("KERNEL32:HMDeviceParPortClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
336 lpHMDeviceName,
337 pHMHandleData->hHMHandle,
338 lpBuffer,
339 nNumberOfBytesToWrite,
340 lpNumberOfBytesWritten,
341 lpOverlapped));
342
343 BOOL ret;
344 ULONG ulBytesWritten;
345
346 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
347 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
348 SetLastError(ERROR_INVALID_PARAMETER);
349 return FALSE;
350 }
351 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
352 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
353 }
354
355 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
356 &ulBytesWritten);
357
358 if(lpNumberOfBytesWritten) {
359 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0;
360 }
361 if(ret == FALSE) {
362 dprintf(("ERROR: WriteFile failed with rc %d", GetLastError()));
363 }
364
365 return ret;
366}
367
368/*****************************************************************************
369 * Name : BOOL WriteFileEx
370 * Purpose : The WriteFileEx function writes data to a file. It is designed
371 * solely for asynchronous operation, unlike WriteFile, which is
372 * designed for both synchronous and asynchronous operation.
373 * WriteFileEx reports its completion status asynchronously,
374 * calling a specified completion routine when writing is completed
375 * and the calling thread is in an alertable wait state.
376 * Parameters: HANDLE hFile handle of file to write
377 * LPVOID lpBuffer address of buffer
378 * DWORD nNumberOfBytesToRead number of bytes to write
379 * LPOVERLAPPED lpOverlapped address of offset
380 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
381 * Variables :
382 * Result : TRUE / FALSE
383 * Remark :
384 * Status : UNTESTED STUB
385 *
386 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
387 *****************************************************************************/
388
389BOOL HMDeviceParPortClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
390 LPVOID lpBuffer,
391 DWORD nNumberOfBytesToWrite,
392 LPOVERLAPPED lpOverlapped,
393 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
394{
395 dprintf(("ERROR: WriteFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
396 lpHMDeviceName,
397 pHMHandleData->hHMHandle,
398 lpBuffer,
399 nNumberOfBytesToWrite,
400 lpOverlapped,
401 lpCompletionRoutine));
402
403 SetLastError(ERROR_INVALID_FUNCTION);
404 return FALSE;
405}
406
407/*****************************************************************************
408 * Name : BOOL HMDeviceParPortClass::ReadFile
409 * Purpose : read data from handle / device
410 * Parameters: PHMHANDLEDATA pHMHandleData,
411 * LPCVOID lpBuffer,
412 * DWORD nNumberOfBytesToRead,
413 * LPDWORD lpNumberOfBytesRead,
414 * LPOVERLAPPED lpOverlapped
415 * Variables :
416 * Result : Boolean
417 * Remark :
418 * Status :
419 *
420 * Author : SvL
421 *****************************************************************************/
422
423BOOL HMDeviceParPortClass::ReadFile(PHMHANDLEDATA pHMHandleData,
424 LPCVOID lpBuffer,
425 DWORD nNumberOfBytesToRead,
426 LPDWORD lpNumberOfBytesRead,
427 LPOVERLAPPED lpOverlapped)
428{
429 dprintf(("KERNEL32:HMDeviceParPortClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
430 lpHMDeviceName,
431 pHMHandleData->hHMHandle,
432 lpBuffer,
433 nNumberOfBytesToRead,
434 lpNumberOfBytesRead,
435 lpOverlapped));
436
437 BOOL ret;
438 ULONG ulBytesRead;
439
440 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
441 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
442 SetLastError(ERROR_INVALID_PARAMETER);
443 return FALSE;
444 }
445 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
446 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
447 }
448
449 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
450 &ulBytesRead);
451
452 if(lpNumberOfBytesRead) {
453 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
454 }
455 if(ret == FALSE) {
456 dprintf(("ERROR: ReadFile failed with rc %d", GetLastError()));
457 }
458 return ret;
459}
460
461/*****************************************************************************
462 * Name : BOOL ReadFileEx
463 * Purpose : The ReadFileEx function reads data from a file asynchronously.
464 * It is designed solely for asynchronous operation, unlike the
465 * ReadFile function, which is designed for both synchronous and
466 * asynchronous operation. ReadFileEx lets an application perform
467 * other processing during a file read operation.
468 * The ReadFileEx function reports its completion status asynchronously,
469 * calling a specified completion routine when reading is completed
470 * and the calling thread is in an alertable wait state.
471 * Parameters: HANDLE hFile handle of file to read
472 * LPVOID lpBuffer address of buffer
473 * DWORD nNumberOfBytesToRead number of bytes to read
474 * LPOVERLAPPED lpOverlapped address of offset
475 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
476 * Variables :
477 * Result : TRUE / FALSE
478 * Remark :
479 * Status : UNTESTED STUB
480 *
481 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
482 *****************************************************************************/
483BOOL HMDeviceParPortClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
484 LPVOID lpBuffer,
485 DWORD nNumberOfBytesToRead,
486 LPOVERLAPPED lpOverlapped,
487 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
488{
489 dprintf(("ERROR: ReadFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
490 lpHMDeviceName,
491 pHMHandleData->hHMHandle,
492 lpBuffer,
493 nNumberOfBytesToRead,
494 lpOverlapped,
495 lpCompletionRoutine));
496
497 SetLastError(ERROR_INVALID_FUNCTION);
498 return FALSE;
499}
500
501BOOL HMDeviceParPortClass::GetCommProperties( PHMHANDLEDATA pHMHandleData,
502 LPCOMMPROP lpcmmp)
503{
504 dprintf(("HMDeviceParPortClass::GetCommProperties(%08xh, %08xh)\n",
505 pHMHandleData,
506 lpcmmp));
507
508 APIRET rc;
509 ULONG ulLen;
510 int i;
511
512#if 0
513 USHORT COMErr;
514 EXTBAUDGET BaudInfo;
515 ulLen = sizeof(EXTBAUDGET);
516 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
517 IOCTL_ASYNC,
518 ASYNC_EXTGETBAUDRATE,
519 0,0,0,
520 &BaudInfo,ulLen,&ulLen);
521#endif
522 rc = NO_ERROR;
523
524 memset(lpcmmp,0,sizeof(COMMPROP));
525 lpcmmp->wPacketLength = sizeof(COMMPROP);
526 lpcmmp->wPacketVersion = 1; //???
527 lpcmmp->dwProvSubType = PST_PARALLELPORT;
528
529#if 0
530 lpcmmp->dwServiceMask = SP_SERIALCOMM;
531 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
532 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
533 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
534 PCF_RTSCTS | PCF_SETXCHAR |
535 PCF_XONXOFF;
536 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
537 SP_HANDSHAKEING | SP_PARITY |
538 SP_PARITY_CHECK | SP_STOPBIT;
539 lpcmmp->dwSettableBaud = 0;
540 for(i=0;i<BaudTableSize;i++)
541 {
542 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
543 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
544 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
545 }
546 lpcmmp->dwSettableBaud |= BAUD_USER;
547 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
548 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
549 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
550 PARITY_MARK | PARITY_SPACE;
551#endif
552
553 return(rc==0);
554}
555
556BOOL HMDeviceParPortClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
557 LPDWORD lpdwErrors,
558 LPCOMSTAT lpcst)
559{
560 dprintf(("HMDeviceParPortClass::ClearCommError(%08xh,%08xh,%08xh)\n",
561 pHMHandleData,
562 lpdwErrors,
563 lpcst));
564
565 APIRET rc;
566 ULONG ulLen;
567 USHORT COMErr;
568
569 ulLen = sizeof(USHORT);
570
571 *lpdwErrors = 0;
572 rc = NO_ERROR;
573
574#if 0
575 // ParPort: CE_DNS, CE_OOP CE_PTO
576
577 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
578 IOCTL_ASYNC,
579 ASYNC_GETCOMMERROR,
580 0,0,0,
581 &COMErr,2,&ulLen);
582 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
583 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
584 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
585 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
586
587 if(lpcst)
588 {
589 UCHAR ucStatus;
590 RXQUEUE qInfo;
591 ulLen = 1;
592 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
593 IOCTL_ASYNC,
594 ASYNC_GETCOMMSTATUS,
595 0,0,0,
596 &ucStatus,ulLen,&ulLen);
597 if(!rc)
598 {
599 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
600 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
601 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
602 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
603 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
604 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
605 lpcst->fTxim = ((ucStatus & 0x40)>0);
606
607 ulLen = sizeof(qInfo);
608 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
609 IOCTL_ASYNC,
610 ASYNC_GETINQUECOUNT,
611 0,0,0,
612 &qInfo,ulLen,&ulLen);
613 if(!rc)
614 {
615 lpcst->cbInQue = qInfo.cch;
616 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
617 IOCTL_ASYNC,
618 ASYNC_GETOUTQUECOUNT,
619 0,0,0,
620 &qInfo,ulLen,&ulLen);
621 if(!rc)
622 lpcst->cbOutQue = qInfo.cch;
623 }
624 }
625 }
626#endif
627
628 return(rc==NO_ERROR);
629}
630
631
632BOOL HMDeviceParPortClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData,
633 DWORD dwIoControlCode,
634 LPVOID lpInBuffer,
635 DWORD nInBufferSize,
636 LPVOID lpOutBuffer,
637 DWORD nOutBufferSize,
638 LPDWORD lpBytesReturned,
639 LPOVERLAPPED lpOverlapped)
640{
641#ifdef DEBUG
642 char *msg = NULL;
643
644 switch(dwIoControlCode)
645 {
646 case IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO:
647 msg = "IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO";
648 break;
649
650 case IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:
651 msg = "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO";
652 break;
653 }
654
655 if(msg) {
656 dprintf(("HMDeviceParPortClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
657 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
658 }
659#endif
660
661 switch(dwIoControlCode)
662 {
663 case IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO:
664 {
665 PPARALLEL_PORT_INFORMATION pPPI = (PPARALLEL_PORT_INFORMATION)lpOutBuffer;
666
667 if(nOutBufferSize < sizeof(PARALLEL_PORT_INFORMATION) || !pPPI)
668 {
669 SetLastError(ERROR_INSUFFICIENT_BUFFER);
670 return FALSE;
671 }
672
673 if(lpBytesReturned)
674 *lpBytesReturned = sizeof(PARALLEL_PORT_INFORMATION);
675
676 // fill in the data values
677
678 // Specifies the bus relative base I/O address of the parallel port registers.
679 pPPI->OriginalController.LowPart = 0; // @@@PH
680 pPPI->OriginalController.HighPart = 0; // @@@PH
681
682 // Pointer to the system-mapped base I/O location of the parallel port registers.
683 pPPI->Controller = 0; // @@@PH
684
685 // Specifies the size, in bytes, of the I/O space, allocated to the parallel port.
686 pPPI->SpanOfController = 0; // @@@PH
687
688 // Pointer to a callback routine that a kernel-mode driver can use to try to allocate the parallel port.
689 pPPI->TryAllocatePort = NULL;
690
691 // Pointer to a callback routine that a kernel-mode driver can use to free the parallel port.
692 pPPI->FreePort = NULL;
693
694 // Pointer to a callback routine that a kernel-mode driver can use to determine the number of requests on the work queue of the parallel port.
695 pPPI->QueryNumWaiters = NULL;
696
697 // Pointer to the device extension of parallel port.
698 pPPI->Context = NULL;
699
700 return TRUE;
701 }
702
703
704 case IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:
705 {
706 PPARALLEL_PNP_INFORMATION pPPI = (PPARALLEL_PNP_INFORMATION)lpOutBuffer;
707
708 if(nOutBufferSize < sizeof(PARALLEL_PNP_INFORMATION) || !pPPI)
709 {
710 SetLastError(ERROR_INSUFFICIENT_BUFFER);
711 return FALSE;
712 }
713
714 if(lpBytesReturned)
715 *lpBytesReturned = sizeof(PARALLEL_PNP_INFORMATION);
716
717 // fill in the data values
718
719 // Specifies the base physical address that the system-supplied function driver for parallel ports uses to control the ECP operation of the parallel port.
720 pPPI->OriginalEcpController.LowPart = 0;
721 pPPI->OriginalEcpController.HighPart = 0;
722
723 // Pointer to the I/O port resource that is used to control the port in ECP mode.
724 pPPI->EcpController = 0;
725
726 // Specifies the size, in bytes, of the I/O port resource.
727 pPPI->SpanOfEcpController = 0;
728
729 // Not used.
730 pPPI->PortNumber = 0;
731
732 // Specifies the hardware capabilities of the parallel port. The following capabilities can be set using a bitwise OR of the following constants:
733 pPPI->HardwareCapabilities = 0;
734 // PPT_1284_3_PRESENT
735 // PPT_BYTE_PRESENT
736 // PPT_ECP_PRESENT
737 // PPT_EPP_32_PRESENT
738 // PPT_EPP_PRESENT
739 // PT_NO_HARDWARE_PRESENT
740
741 // Pointer to a callback routine that a kernel-mode driver can use to change the operating mode of the parallel port.
742 pPPI->TrySetChipMode = 0;
743
744 // Pointer to a callback routine that a kernel-mode driver can use to clear the operating mode of the parallel port.
745 pPPI->ClearChipMode = 0;
746
747 // Specifies the size, in words, of the hardware first in/first out (FIFO) buffer. The FIFO word size, in bits, is the value of FifoWidth.
748 pPPI->FifoDepth = 0;
749
750 // Specifies the FIFO word size, in bits, which is the number of bits handled in parallel.
751 pPPI->FifoWidth = 0;
752
753 // Not used.
754 pPPI->EppControllerPhysicalAddress.LowPart = 0;
755 pPPI->EppControllerPhysicalAddress.HighPart = 0;
756
757 // Not used.
758 pPPI->SpanOfEppController = 0;
759
760 // Specifies the number of daisy-chain devices currently attached to a parallel port. In Microsoftÿ Windowsÿ XP, from zero to two devices can be simultaneously connected to a
761 // parallel port. In Windows 2000, from zero to four devices can be simultaneously connected to a parallel port.
762 pPPI->Ieee1284_3DeviceCount = 0;
763
764 // Pointer to a callback routine that a kernel-mode driver can use to try to select an IEEE 1284.3 device.
765 pPPI->TrySelectDevice = 0;
766
767 // Pointer to a callback routine that a kernel-mode driver can use to deselect an IEEE 1284.3 device.
768 pPPI->DeselectDevice = 0;
769
770 // Pointer to the device extension of a parallel port's function device object (FDO).
771 pPPI->Context = 0;
772
773 // The current operating mode of the parallel port.
774 pPPI->CurrentMode = 0;
775
776 // The symbolic link name of the parallel port.
777 pPPI->PortName = 0;
778
779 return TRUE;
780 }
781 }
782 dprintf(("HMDeviceParPortClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
783 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
784 return FALSE;
785}
786
787
788BOOL HMDeviceParPortClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
789 LPCOMMCONFIG lpCC,
790 DWORD dwSize)
791{
792 dprintf(("HMDeviceParPortClass::SetDefaultCommConfig(%08xh,%08xh,%08xh)\n",
793 pHMHandleData,
794 lpCC,
795 dwSize));
796
797 PHMDEVPARPORTDATA pDevData = (PHMDEVPARPORTDATA)pHMHandleData->lpDeviceData;
798 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_PARPORT) )
799 {
800 SetLastError(ERROR_INVALID_HANDLE);
801 return FALSE;
802 }
803 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
804 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
805
806 return(TRUE);
807}
808
809
810BOOL HMDeviceParPortClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
811 LPCOMMCONFIG lpCC,
812 LPDWORD lpdwSize)
813{
814 dprintf(("HMDeviceParPortClass::GetDefaultCommConfig(%08xh,%08xh,%08xh)\n",
815 pHMHandleData,
816 lpCC,
817 lpdwSize));
818
819
820 PHMDEVPARPORTDATA pDevData = (PHMDEVPARPORTDATA)pHMHandleData->lpDeviceData;
821
822 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
823 *lpdwSize< sizeof(COMMCONFIG) )
824 {
825 SetLastError(ERROR_INSUFFICIENT_BUFFER);
826 *lpdwSize= sizeof(COMMCONFIG);
827 return FALSE;
828 }
829
830 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_PARPORT) )
831 {
832 SetLastError(ERROR_INVALID_HANDLE);
833 return FALSE;
834 }
835
836 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
837 *lpdwSize = sizeof(COMMCONFIG);
838 return(TRUE);
839}
840
841
842BOOL HMDeviceParPortClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
843 LPCOMMCONFIG lpCC,
844 DWORD dwSize )
845{
846 dprintf(("HMDeviceParPortClass::SetCommConfig not implemented"));
847
848 return(TRUE);
849}
850
851
852BOOL HMDeviceParPortClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
853 LPCOMMCONFIG lpCC,
854 LPDWORD lpdwSize )
855{
856 PHMDEVPARPORTDATA pDevData = (PHMDEVPARPORTDATA)pHMHandleData->lpHandlerData;
857
858 dprintf(("HMDeviceParPortClass::GetCommConfig(%08xh,%08xh,%08xh)\n",
859 pHMHandleData,
860 lpCC,
861 lpdwSize));
862
863 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
864 *lpdwSize< sizeof(COMMCONFIG) )
865 {
866 SetLastError(ERROR_INSUFFICIENT_BUFFER);
867 *lpdwSize= sizeof(COMMCONFIG);
868 return FALSE;
869 }
870
871 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_PARPORT) )
872 {
873 SetLastError(ERROR_INVALID_HANDLE);
874 return FALSE;
875 }
876
877 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
878 *lpdwSize = sizeof(COMMCONFIG);
879 return(TRUE);
880}
Note: See TracBrowser for help on using the repository browser.