I'm trying to write out a byte to the parallel port under Windows XP. I searched over the internet, and everybody (even MSDN) says that it should be working in this way:

tLpt1    db 'LPT1',0
Data    db 0a5h
hLpt    dd ?
NrBytes  dd ?
...
invoke CreateFile, addr tLpt1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL
mov    hLpt, eax

invoke WriteFile, hLpt, addr Data, 1, addr NrBytes, NULL

invoke CloseHandle, hLpt

The problem is that WriteFile hangs up. It does not return. My program stops responding.
The CreateFile executes successfully, it does not return INVALID_HANDLE_VALUE, nor some error flag.

I tried to set the TimeOuts, and other communication parameters (similar to the COM1 case), but these functions simply fail, and the GetLastError returns the value 87 (87: The parameter is incorrect. ERROR_INVALID_PARAMETER):
  GetCommState
  SetCommState
  PurgeComm
  ClearCommError
  ClearCommBreak
  SetCommTimeouts


Has anybody encountered this problem? Is it possible to write a byte to the parallel port using ONLY WinAPI functions?

I know that there are those directio.dll, winio.dll and other DLL solutions, but I want to use only WinAPI functions for my program to be portable to other Windows versions too.
Posted on 2005-05-16 04:34:18 by bszente
I managed to solve the problem with the Inpout32.dll
It's easy to use, the source code is also available.

However the question still remains open: Is it possible to write a byte to the parallel port using ONLY WinAPI functions (standard Printer port driver) under Win XP? Similar to the serial I/O, which is working well...
Posted on 2005-05-16 05:51:07 by bszente
bszente,

I use the following with Win95 -> WinXP:


PPort  db "LPT1", 0
emph_p db 27, 69

hComm HWND ?
nobw DWORD ?


INVOKE CreateFile, ADDR PPort, GENERIC_READ or GENERIC_WRITE, \
NULL, NULL, OPEN_EXISTING, NULL, NULL

mov hComm,eax

invoke WriteFile, hComm, ADDR emph_p, 2, ADDR nobw, NULL


hth,

farrier
Posted on 2005-05-16 08:51:57 by farrier
Thanks farrier for your reply, but if I do exactly the same thing, my programs just hangs up in the WriteFilein the same way, like he would wait for some acknowledge signal or something. It simply does not return from call, and if I measure the voltage on the pins they all are 3.3V (so the all are 1). I just don't get it.
I'm sorry to ask, but is it realy working on your computer?

Does any of you guys managed to write out bytes under WinXP to the LPT1 using only those CreateFile & WriteFile WinAPI functions?
Posted on 2005-05-20 17:12:59 by bszente
bszente,

It's kinda funny, I've mentioned this many times on this and the MASM32 forum, and most say it can't be done; that you have to use iodrivers.  I can assure you that the code I posted works everyday on Win95, WinME, and WinXP computers using standard LPT ports.  The first thing to do, is to check the return value from CreateFile.  Make sure to include both, GENERIC_READ or GENERIC_WRITE.

Basically the same code is used in one routine to write to a parallel printer or a serial printer, depending on which printer is active at the time.  The serial ports require much more setup, but the WriteFile works equally well.

This actually works, and I got the code directly from the example code from the SDK

What kind of printer are you trying to write to?

farrier
Posted on 2005-05-20 22:46:38 by farrier
I put the parameters exactly, as you posted. CreateFile returns with success. It opens normally the port. Also CloseHandle return with success.
The problem is with WriteFile. And it does not return anything, because it hangs up  :sad:

I used the serial port, that works fine, I managed to do transfer with 115kbaud between the computer and a PIC16F876. So with the serial communication I don't have problem.

But let me think... you are saying that it works for you for a printer. I'm not writing to a printer, I just want to set the bits high or low (for control purpose). I would like to ask you, to try your code without the printer. Deattach your printer and run your program. I think that the printer sets some acknowledge signals back to computer, and that's the reason of succesfull working of your program. I think that your program too should hang up without an attached printer.

In my case I dont have anything attached (yet) to the port, I just want to set the appropiate data bits to a certain level. I keep getting the feeling, that WriteFile is waiting for the acknowledge signal or something. But this is stupid. It should simply put out those bits to the parralel port register.
I tried to disable ECP from my BIOS, I set the parallel port in Output Only mode. WriteFile hanged up in the same way.
Posted on 2005-05-21 02:09:23 by bszente
bszente,

That is probably the problem, the parallel port is waiting for the printer/device to signal that it is ready for data, before the WriteFile will actually send the data to the port.  According to a parallel port manual I have, the input pins for the parallel port are:

pin 10 is ack, active low
pin 11 is busy, active high
pin 12 is pe, active high
pin 13 is Select which would correspnd with the select button on the front of the printer,  active high
pin 15 is error, active low
pin 16 is init, active low

farrier
Posted on 2005-05-21 08:31:28 by farrier
I use the WinIO Library from http://www.internals.com/.

quote from site:
This library allows direct I/O port and physical memory access under Windows 9x/NT/2000 and XP.
..and can be used from non-administrative accounts under Windows NT/2000 and XP.

You choose a port and give it a value. Just like in DOS.

WriteFile sounds good when dealing with serial ports.. for parallel this seems enough.
I just hate it when the "Print Error" Dialog pops up (while playing with PP)

Sorry for not answering your question.

Best Regards
Posted on 2005-05-24 02:27:21 by Azrim
bszente,

These links discuss handshaking for the parallel port.  There are different modes for the parallel port: legacy; EPP; ECP; SPP; ...  Each may have different handshaking requirements.

google -> parallel port handshaking

http://www.beyondlogic.org/epp/epp.htm
http://www.beyondlogic.org/ecp/ecp.htm

hth

farrier
Posted on 2005-05-24 05:43:22 by farrier
I found it... at last. Thanks Azrim and farrier for your time. BTW I knew about beyondlogic, I took the ECP specification from there when I needed to design a pcb.

In this case I wanted simply to set the data bits to a certain level, I did not wanted to do handshaking or any other wonders... And I tought that I need to write simply a byte to LPT1.

So here is what's happening: the WriteFile respects the Standard Parallel Port specification, as described here.
The WriteFile sets the data lines, and asserts the strobe if the busy line is not high. After asserting the strobe line, the device should set the acknowledge signal to low to end the transfer.

Both Busy and nAck cause the hangup, they are always in high (a TTL pin left unconnected is assumed as high by default), so the program is waiting.

Solution: pull down both Busy(pin 11) and nAck(pin 10) to the GND by a 560 Ohm resistor. Simply bypass pin 25 to pin 11 and pin 24 to pin 10 with the resitors. That's it. After that WriteFile works like charm.

Now let me explain, why is essential for me to use only WinAPI functions... The new laptops does not have LPT ports (Dell Inspiron for example). I bought an USB-to-Parallel adaptor which is IEEE 1284 compliant and this way I can use it. I open the USB001 (or whatever is it's name) port with CreateFile, and after that I simply use WriteFile.
With those WinIO, DirectIO, Inpout32, etc. drivers I can't do that. I cannot access that Virtual Parallel Port.

Regards,
bszente
Posted on 2005-05-24 15:07:00 by bszente