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

Last change on this file since 7564 was 7564, checked in by sandervl, 24 years ago

overlappedio, com & lpt updates

File size: 20.1 KB
Line 
1/* $Id: hmparport.cpp,v 1.18 2001-12-07 11:28:10 sandervl 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// Hardwired parallel port configuration information.
51// @@@PH better query the Resource Manager
52typedef struct tagParallelPortConfiguration
53{
54 ULONG ulNumber;
55 ULONG ulPortBase;
56 ULONG ulPortSpan;
57 ULONG ulEcpPortBase;
58 ULONG ulEcpPortSpan;
59} PARALLELPORTCONFIGURATION, *PPARALLELPORTCONFIGURATION;
60
61#define MAX_PARALLEL_PORTS_CONFIGURATION 3
62static PARALLELPORTCONFIGURATION arrParallelPorts[MAX_PARALLEL_PORTS_CONFIGURATION] =
63{
64 {1, 0x378, 8, 0x778, 3},
65 {2, 0x278, 8, 0x678, 3},
66 {3, 0x3bc, 8, 0x000, 0}
67};
68
69
70typedef struct _HMDEVPARPORTDATA
71{
72 ULONG ulMagic;
73
74 // Win32 Device Control Block
75 COMMCONFIG CommCfg;
76
77 // hardware configuration block
78 PPARALLELPORTCONFIGURATION pHardwareConfiguration;
79} HMDEVPARPORTDATA, *PHMDEVPARPORTDATA;
80
81//******************************************************************************
82//******************************************************************************
83static VOID *CreateDevData()
84{
85 PHMDEVPARPORTDATA pData;
86 pData = new HMDEVPARPORTDATA();
87 if(NULL!=pData)
88 {
89 memset(pData,0,sizeof(HMDEVPARPORTDATA));
90 pData->ulMagic = MAGIC_PARPORT;
91 pData->CommCfg.dwSize = sizeof(COMMCONFIG);
92 pData->CommCfg.wVersion = 1;
93 pData->CommCfg.dwProviderSubType = PST_PARALLELPORT;
94 }
95 return pData;
96}
97//******************************************************************************
98//******************************************************************************
99HMDeviceParPortClass::HMDeviceParPortClass(LPCSTR lpDeviceName) :
100 HMDeviceHandler(lpDeviceName)
101{
102 dprintf(("HMDeviceParPortClass::HMDevParPortClass(%s)\n",
103 lpDeviceName));
104
105#ifndef DEVINFO_PRINTER
106#define DEVINFO_PRINTER 0
107#endif
108
109 // first, we determine the number of parallel port devices available
110
111 // PH 2001-12-04 Note:
112 // This call will not return any information about redirected LPT ports.
113 // We have a specific application requiring exactly this behaviour as it
114 // cannot talk to redirected LPTs anyway.
115 // For any change in this behaviour, we'd require a configuration switch.
116 bNumberOfParallelPorts = 0;
117 DWORD rc = OSLibDosDevConfig(&bNumberOfParallelPorts,
118 DEVINFO_PRINTER);
119 dprintf(("HMDeviceParPortClass: Parallel ports reported: %d\n",
120 bNumberOfParallelPorts));
121 if (0 == bNumberOfParallelPorts)
122 return;
123
124 VOID *pData;
125 dprintf(("HMDeviceParPortClass: Registering LPTs with Handle Manager\n"));
126
127 pData = CreateDevData();
128 if(pData!= NULL)
129 HMDeviceRegisterEx("LPT1", this, pData);
130
131 // add symbolic links to the "real name" of the device
132 if (bNumberOfParallelPorts > 0)
133 {
134 // Note: \\.\LPTx: is invalid (NT4SP6)
135 PSZ pszLPT = strdup("\\\\.\\LPTx");
136 PSZ pszLPT2 = strdup("\\Device\\ParallelPort0");
137 for (char ch = '1'; ch <= '1' + (bNumberOfParallelPorts - 1); ch++)
138 {
139 pszLPT[7] = ch;
140 pszLPT2[20] = ch - 1; // \DeviceParallelPort0 -> LPT1
141 HandleNamesAddSymbolicLink(pszLPT, pszLPT+4);
142 HandleNamesAddSymbolicLink(pszLPT2, pszLPT+4);
143 }
144 free(pszLPT);
145 free(pszLPT2);
146
147 // add "PRN" device
148 HandleNamesAddSymbolicLink("PRN", "LPT1");
149 HandleNamesAddSymbolicLink("PRN:", "LPT1");
150 HandleNamesAddSymbolicLink("\\\\.\\PRN", "LPT1");
151 }
152}
153
154/*****************************************************************************
155 * Name : HMDeviceParPortClass::FindDevice
156 * Purpose : Checks if lpDeviceName belongs to this device class
157 * Parameters: LPCSTR lpClassDevName
158 * LPCSTR lpDeviceName
159 * int namelength
160 * Variables :
161 * Result : checks if name is COMx or COMx: (x=1..8)
162 * Remark :
163 * Status :
164 *
165 * Author : SvL
166 *****************************************************************************/
167BOOL HMDeviceParPortClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
168{
169 // Don't accept any name if no parallel ports have been detected
170 if (bNumberOfParallelPorts == 0)
171 return FALSE;
172
173 // can be both, "LPT1" and "LPT1:"
174 if(namelength > 5)
175 return FALSE; //can't be lpt name
176
177 //first 3 letters 'LPT'?
178 if(lstrncmpiA(lpDeviceName, lpClassDevName, 3) != 0)
179 return FALSE;
180
181 if(namelength == 5 && lpDeviceName[4] != ':')
182 return FALSE;
183
184 // can support up tp LPT9
185 if ( (lpDeviceName[3] >= '1') &&
186 (lpDeviceName[3] <= '1' + bNumberOfParallelPorts) )
187 {
188 return TRUE;
189 }
190
191 return FALSE;
192}
193//******************************************************************************
194//******************************************************************************
195DWORD HMDeviceParPortClass::CreateFile(LPCSTR lpFileName,
196 PHMHANDLEDATA pHMHandleData,
197 PVOID lpSecurityAttributes,
198 PHMHANDLEDATA pHMHandleDataTemplate)
199{
200 dprintf(("HMDeviceParPortClass::CreateFile(%s,%08xh,%08xh,%08xh)\n",
201 lpFileName,
202 pHMHandleData,
203 lpSecurityAttributes,
204 pHMHandleDataTemplate));
205
206 char lptname[6];
207
208 dprintf(("HMDeviceParPortClass: Parallel port %s open request\n", lpFileName));
209
210 // Don't accept any name if no parallel ports have been detected
211 if (bNumberOfParallelPorts == 0)
212 {
213 return ERROR_DEV_NOT_EXIST;
214 }
215
216 strcpy(lptname, lpFileName);
217 lptname[4] = 0; //get rid of : (if present) (eg LPT1:)
218
219 //AH: TODO parse Win32 security handles
220 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
221 pHMHandleData->hHMHandle = OSLibDosOpen(lptname,
222 OSLIB_ACCESS_READWRITE |
223 OSLIB_ACCESS_SHAREDENYREAD |
224 OSLIB_ACCESS_SHAREDENYWRITE);
225 SetErrorMode(oldmode);
226
227 // check if handle could be opened properly
228 if (0 == pHMHandleData->hHMHandle)
229 {
230 return ERROR_ACCESS_DENIED; // signal failure
231 }
232 else
233 {
234 ULONG ulLen;
235 APIRET rc;
236 pHMHandleData->lpHandlerData = new HMDEVPARPORTDATA();
237
238 // Init The handle instance with the default default device config
239 memcpy( pHMHandleData->lpHandlerData,
240 pHMHandleData->lpDeviceData,
241 sizeof(HMDEVPARPORTDATA));
242
243 // determine which port was opened
244 ULONG ulPortNo = lptname[3] - '1';
245
246 // safety check (device no 0..8 -> LPT1..9)
247 if (ulPortNo > MAX_PARALLEL_PORTS_CONFIGURATION)
248 {
249 HMDeviceParPortClass::CloseHandle(pHMHandleData);
250 return ERROR_DEV_NOT_EXIST;
251 }
252
253 // and save the hardware information
254 PHMDEVPARPORTDATA pPPD = (PHMDEVPARPORTDATA)pHMHandleData->lpHandlerData;
255 pPPD->pHardwareConfiguration = &arrParallelPorts[ulPortNo];
256
257 return NO_ERROR;
258 }
259}
260
261/*****************************************************************************
262 * Name : DWORD HMDeviceParPortClass::GetFileType
263 * Purpose : determine the handle type
264 * Parameters: PHMHANDLEDATA pHMHandleData
265 * Variables :
266 * Result : API returncode
267 * Remark :
268 * Status :
269 *
270 * Author : SvL
271 *****************************************************************************/
272
273DWORD HMDeviceParPortClass::GetFileType(PHMHANDLEDATA pHMHandleData)
274{
275 dprintf(("KERNEL32: HMDeviceParPortClass::GetFileType %s(%08x)\n",
276 lpHMDeviceName, pHMHandleData));
277
278 return FILE_TYPE_PIPE; //this is what NT4 returns
279}
280//******************************************************************************
281/* this is a handler method for calls to CloseHandle() */
282//******************************************************************************
283BOOL HMDeviceParPortClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
284{
285 dprintf(("HMDeviceParPortClass: Parallel port close request(%08xh)\n",
286 pHMHandleData));
287
288 delete pHMHandleData->lpHandlerData;
289 return OSLibDosClose(pHMHandleData->hHMHandle);
290}
291
292
293/*****************************************************************************
294 * Name : BOOL HMDeviceParPortClass::WriteFile
295 * Purpose : write data to handle / device
296 * Parameters: PHMHANDLEDATA pHMHandleData,
297 * LPCVOID lpBuffer,
298 * DWORD nNumberOfBytesToWrite,
299 * LPDWORD lpNumberOfBytesWritten,
300 * LPOVERLAPPED lpOverlapped
301 * Variables :
302 * Result : Boolean
303 * Remark :
304 * Status :
305 *
306 * Author : SvL
307 *****************************************************************************/
308
309BOOL HMDeviceParPortClass::WriteFile(PHMHANDLEDATA pHMHandleData,
310 LPCVOID lpBuffer,
311 DWORD nNumberOfBytesToWrite,
312 LPDWORD lpNumberOfBytesWritten,
313 LPOVERLAPPED lpOverlapped,
314 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
315{
316 dprintf(("KERNEL32:HMDeviceParPortClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
317 lpHMDeviceName,
318 pHMHandleData->hHMHandle,
319 lpBuffer,
320 nNumberOfBytesToWrite,
321 lpNumberOfBytesWritten,
322 lpOverlapped));
323
324 BOOL ret;
325 ULONG ulBytesWritten;
326
327 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
328 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
329 SetLastError(ERROR_INVALID_PARAMETER);
330 return FALSE;
331 }
332 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
333 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
334 }
335 if(lpCompletionRoutine) {
336 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
337 }
338
339 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
340 &ulBytesWritten);
341
342 if(lpNumberOfBytesWritten) {
343 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0;
344 }
345 if(ret == FALSE) {
346 dprintf(("ERROR: WriteFile failed with rc %d", GetLastError()));
347 }
348
349 return ret;
350}
351
352/*****************************************************************************
353 * Name : BOOL HMDeviceParPortClass::ReadFile
354 * Purpose : read data from handle / device
355 * Parameters: PHMHANDLEDATA pHMHandleData,
356 * LPCVOID lpBuffer,
357 * DWORD nNumberOfBytesToRead,
358 * LPDWORD lpNumberOfBytesRead,
359 * LPOVERLAPPED lpOverlapped
360 * Variables :
361 * Result : Boolean
362 * Remark :
363 * Status :
364 *
365 * Author : SvL
366 *****************************************************************************/
367
368BOOL HMDeviceParPortClass::ReadFile(PHMHANDLEDATA pHMHandleData,
369 LPCVOID lpBuffer,
370 DWORD nNumberOfBytesToRead,
371 LPDWORD lpNumberOfBytesRead,
372 LPOVERLAPPED lpOverlapped,
373 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
374{
375 dprintf(("KERNEL32:HMDeviceParPortClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
376 lpHMDeviceName,
377 pHMHandleData->hHMHandle,
378 lpBuffer,
379 nNumberOfBytesToRead,
380 lpNumberOfBytesRead,
381 lpOverlapped));
382
383 BOOL ret;
384 ULONG ulBytesRead;
385
386 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
387 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
388 SetLastError(ERROR_INVALID_PARAMETER);
389 return FALSE;
390 }
391 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
392 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
393 }
394 if(lpCompletionRoutine) {
395 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
396 }
397
398 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
399 &ulBytesRead);
400
401 if(lpNumberOfBytesRead) {
402 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
403 }
404 if(ret == FALSE) {
405 dprintf(("ERROR: ReadFile failed with rc %d", GetLastError()));
406 }
407 return ret;
408}
409//******************************************************************************
410//******************************************************************************
411BOOL HMDeviceParPortClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData,
412 DWORD dwIoControlCode,
413 LPVOID lpInBuffer,
414 DWORD nInBufferSize,
415 LPVOID lpOutBuffer,
416 DWORD nOutBufferSize,
417 LPDWORD lpBytesReturned,
418 LPOVERLAPPED lpOverlapped)
419{
420#ifdef DEBUG
421 char *msg = NULL;
422
423 switch(dwIoControlCode)
424 {
425 case IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO:
426 msg = "IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO";
427 break;
428
429 case IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:
430 msg = "IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO";
431 break;
432 }
433
434 if(msg) {
435 dprintf(("HMDeviceParPortClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
436 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
437 }
438#endif
439
440 switch(dwIoControlCode)
441 {
442 case IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO:
443 {
444 PPARALLEL_PORT_INFORMATION pPPI = (PPARALLEL_PORT_INFORMATION)lpOutBuffer;
445
446 if(nOutBufferSize < sizeof(PARALLEL_PORT_INFORMATION) || !pPPI)
447 {
448 SetLastError(ERROR_INSUFFICIENT_BUFFER);
449 return FALSE;
450 }
451
452 if(lpBytesReturned)
453 *lpBytesReturned = sizeof(PARALLEL_PORT_INFORMATION);
454
455 // fill in the data values
456 PHMDEVPARPORTDATA pPPD = (PHMDEVPARPORTDATA)pHMHandleData->lpHandlerData;
457
458 // @@@PH
459 // Specifies the bus relative base I/O address of the parallel port registers.
460 pPPI->OriginalController.LowPart = pPPD->pHardwareConfiguration->ulPortBase;
461 pPPI->OriginalController.HighPart = 0;
462
463 // Pointer to the system-mapped base I/O location of the parallel port registers.
464 pPPI->Controller = NULL;
465
466 // Specifies the size, in bytes, of the I/O space, allocated to the parallel port.
467 pPPI->SpanOfController = pPPD->pHardwareConfiguration->ulPortSpan;
468
469 // Pointer to a callback routine that a kernel-mode driver can use to try to allocate the parallel port.
470 pPPI->TryAllocatePort = NULL;
471
472 // Pointer to a callback routine that a kernel-mode driver can use to free the parallel port.
473 pPPI->FreePort = NULL;
474
475 // 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.
476 pPPI->QueryNumWaiters = NULL;
477
478 // Pointer to the device extension of parallel port.
479 pPPI->Context = NULL;
480
481 return TRUE;
482 }
483
484
485 case IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:
486 {
487 PPARALLEL_PNP_INFORMATION pPPI = (PPARALLEL_PNP_INFORMATION)lpOutBuffer;
488
489 if(nOutBufferSize < sizeof(PARALLEL_PNP_INFORMATION) || !pPPI)
490 {
491 SetLastError(ERROR_INSUFFICIENT_BUFFER);
492 return FALSE;
493 }
494
495 if(lpBytesReturned)
496 *lpBytesReturned = sizeof(PARALLEL_PNP_INFORMATION);
497
498 // fill in the data values
499 PHMDEVPARPORTDATA pPPD = (PHMDEVPARPORTDATA)pHMHandleData->lpHandlerData;
500
501 // @@@PH
502 // Specifies the base physical address that the system-supplied
503 // function driver for parallel ports uses to control the ECP
504 // operation of the parallel port.
505 pPPI->OriginalEcpController.LowPart = pPPD->pHardwareConfiguration->ulEcpPortBase;
506 pPPI->OriginalEcpController.HighPart = 0;
507
508 // Pointer to the I/O port resource that is used to control the
509 // port in ECP mode.
510 pPPI->EcpController = NULL;
511
512 // Specifies the size, in bytes, of the I/O port resource.
513 pPPI->SpanOfEcpController = pPPD->pHardwareConfiguration->ulEcpPortSpan;
514
515 // Not used.
516 pPPI->PortNumber = 0;
517
518 // Specifies the hardware capabilities of the parallel port. The following capabilities can be set using a bitwise OR of the following constants:
519 pPPI->HardwareCapabilities = 0;
520 // PPT_1284_3_PRESENT
521 // PPT_BYTE_PRESENT
522 // PPT_ECP_PRESENT
523 // PPT_EPP_32_PRESENT
524 // PPT_EPP_PRESENT
525 // PT_NO_HARDWARE_PRESENT
526
527 // Pointer to a callback routine that a kernel-mode driver can use to change the operating mode of the parallel port.
528 pPPI->TrySetChipMode = 0;
529
530 // Pointer to a callback routine that a kernel-mode driver can use to clear the operating mode of the parallel port.
531 pPPI->ClearChipMode = 0;
532
533 // 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.
534 pPPI->FifoDepth = 0;
535
536 // Specifies the FIFO word size, in bits, which is the number of bits handled in parallel.
537 pPPI->FifoWidth = 0;
538
539 // Not used.
540 pPPI->EppControllerPhysicalAddress.LowPart = 0;
541 pPPI->EppControllerPhysicalAddress.HighPart = 0;
542
543 // Not used.
544 pPPI->SpanOfEppController = 0;
545
546 // 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
547 // parallel port. In Windows 2000, from zero to four devices can be simultaneously connected to a parallel port.
548 pPPI->Ieee1284_3DeviceCount = 0;
549
550 // Pointer to a callback routine that a kernel-mode driver can use to try to select an IEEE 1284.3 device.
551 pPPI->TrySelectDevice = 0;
552
553 // Pointer to a callback routine that a kernel-mode driver can use to deselect an IEEE 1284.3 device.
554 pPPI->DeselectDevice = 0;
555
556 // Pointer to the device extension of a parallel port's function device object (FDO).
557 pPPI->Context = 0;
558
559 // The current operating mode of the parallel port.
560 pPPI->CurrentMode = 0;
561
562 // The symbolic link name of the parallel port.
563 pPPI->PortName = 0;
564
565 return TRUE;
566 }
567 }
568 dprintf(("HMDeviceParPortClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
569 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
570 return FALSE;
571}
572//******************************************************************************
573//******************************************************************************
574
575
Note: See TracBrowser for help on using the repository browser.