Hi all,
I am new to windows programming. I want to communicate with the PIC programmer  which my friend has developed.
I am using BAFO 1284 parallel printing cable for this since laptop does not have any LPT port
I reffered following links for the same.

http://www.asmcommunity.net/board/index.php?action=printpage;topic=21143.0
http://blog.peter.skarpetis.com/.
I developed the code using the Visual  studio 6.0.

while debugging the WriteFile() is able to write successfuly, atleast the number of bytes sent is 1.
but the data is not seen on the actual port pins.
At first the Writefile was hanging up , but i reffered link 1 mentioned above, after i connected pin 10 and 11 to ground using 440 ohms(220+220) the api started working. also when i plug in the BAFO 1284 (in debug mode) i am able to get the guid string, and when i remove the BAFO 1284 printing cable, the code exits as expected.
Can any one please help me, and tell me why the data is not seen on port, even though nACK and BUSY pin status is succesfully checked by WritFile().
This is my code :  :) means the one i have assembled using this  forum
/***********************************************************************************/
/* Code to find the device path for a usbprint.sys controlled
* usb printer and print to it
*/
#include <windows.h>
#include "iostream.h"
#include<stdio.h>
#include <SETUPAPI.H>
#include <MALLOC.H>
#include <SETUPAPI.H>
#include <MALLOC.H>
#include <time.h>


void sleep(unsigned int mseconds)
{
    clock_t goal = mseconds + clock();
    while (goal > clock());
}


//const GUID GUID_DEVINTERFACE_USBPRINT = {0x36FC9E60,0xC465,0x11CF,0x8056,0x444553540000};

/* This define is required so that the GUID_DEVINTERFACE_USBPRINT variable is
* declared an initialised as a static locally, since windows does not include it in any
* of its libraries
*/
/*
#define SS_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \

static const GUID DECLSPEC_SELECTANY name \
= { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

SS_DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11D1, 0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);
*/
const GUID GUID_DEVINTERFACE_USBPRINT = {0x28d78fad,0x5a12,0x11D1,0xae,0x5b,0x00,0x00,0xf8,0x03,0xa8,0xc2};
void main()
{ DWORD err =0;
  HDEVINFO devs;
  HANDLE port;
  DWORD devcount;
  DWORD dataType;
  SP_DEVINFO_DATA devinfo;
  SP_DEVICE_INTERFACE_DATA devinterface;
  DWORD size;
  GUID intfce;
  PSP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;
  err = GetLastError();
  intfce = GUID_DEVINTERFACE_USBPRINT;
  devs = SetupDiGetClassDevs(&intfce, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
  if (devs == INVALID_HANDLE_VALUE) {
    return;
  }
  devcount = 0;
  devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  while (SetupDiEnumDeviceInterfaces(devs, 0, &intfce, devcount, &devinterface)) {
    //  The following buffers would normally be malloced to he correct size
    // but here we just declare them as large stack variables
    // to make the code more readable
    //
    char driverkey[2048];
    char interfacename[2048];
    char location[2048];

err = GetLastError();    
    //If this is not the device we want, we would normally continue onto the next one
    //so something like if (!required_device) continue; would be added here
    ///
    devcount++;
    size = 0;
    // See how large a buffer we require for the device interface details //
    SetupDiGetDeviceInterfaceDetail(devs, &devinterface, 0, 0, &size, 0);
    devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
    interface_detail = calloc(1, size);
    if (interface_detail) {
      interface_detail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
      devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
      if (!SetupDiGetDeviceInterfaceDetail(devs, &devinterface, interface_detail, size, 0, &devinfo)) {
free(interface_detail);
SetupDiDestroyDeviceInfoList(devs);
return;
      }
      // Make a copy of the device path for later use //
      strcpy(interfacename, interface_detail->DevicePath);
      free(interface_detail);
      // And now fetch some useful registry entries //
      size = sizeof(driverkey);
      driverkey[0] = 0;
      if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo, SPDRP_DRIVER, &dataType, (LPBYTE)driverkey, size, 0)) {
SetupDiDestroyDeviceInfoList(devs);
return;
      }
      size = sizeof(location);
      location[0] = 0;
      if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo, SPDRP_LOCATION_INFORMATION, &dataType, (LPBYTE)location, size, 0)) {
SetupDiDestroyDeviceInfoList(devs);
return;
      }
      port = CreateFile(interfacename, GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
      if (port != INVALID_HANDLE_VALUE) {
/* Now perform all the writing to the device ie.*/
OVERLAPPED olWrite = { 0 };

olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
err = GetLastError();
   
while (1)
{  DWORD bytes_written = 0;

    static int buf= 0;
char ret1 = 0;
// size = 1;
DWORD  errors=0;
COMSTAT lpStat;
ClearCommError(port, &errors, &lpStat);
ret1= WriteFile(port, &buf, 2,&bytes_written,&olWrite);
buf++;
if(ret1 ==0)
{
DWORD err =0;
    err = GetLastError();
printf("ERROR");
//break;
}
else
{  static int i = 0;
    i++;
printf("%d\r\n",i);
sleep(1000);
}
}


CloseHandle(port);
      }
    }
  }
  SetupDiDestroyDeviceInfoList(devs);
}
/*******************************************************************************/

Best regards
Rohit

Posted on 2010-01-01 23:20:23 by rohitd
Your WriteFile call sends two bytes, but you increment the bufferpointer by one byte.
Posted on 2010-01-01 23:41:43 by Homer
opps , sorry, that was one of the change i made to see if the number of bytes sent make any difference. if it is 1 even then the same thing happens
Posted on 2010-01-01 23:48:40 by rohitd
It's not jumping out at me.
Start adding debug lines after each api call, and check all the return values, from the top down.
As you go, you can eliminate the debug lines behind you, until you find the offending api.
Not the most efficient, but it will work.
Posted on 2010-01-01 23:58:31 by Homer
Hi Homer,

Thanks a lot for replying.
The WriteFile() api returns 1 and bytes_written is also 1. the problem is some how the data is not replicated on the port pins.
the input pins i.e nAck and BUSY are being sensed succesfully.
The problem is somethign related to some setting, related to parallel port which i am missing.
I think some thing related to registry key ....
Also i dont know how to set the port out put mode ECP, EPP and so on

Thanks
Rohit
Posted on 2010-01-02 00:09:38 by rohitd
You are grounding the ACK and BUSY lines !!

Pin10 is ACK
Pin11 is BUSY

Your device can tell the computer that "the printer is busy" by holding the BUSY line HIGH.
It should do this in response to the Stobe line being toggled.
Holding it LOW when the computer is allowed to send some data.

Since you're using Printer api, ignore that and lets move on.
You can't just hold the ACK line low.
It's meant to be normally HIGH, and given a low pulse when your Device has accepted the Byte.

Once the printer has accepted data, it will acknowledge the byte by a negative pulse about 5uS on the nAck line.

Posted on 2010-01-02 00:56:00 by Homer
Hi Homer,

:) It worked.
Thanks a lot.
what i did was i removed the register connection of pin 10 i.e ACK. The register connecting the pin 11 (BUSY)to ground is still present. Now when i write a byte then the data is seen on the port, but still the write API  has not returned, and nothing is printed on the output terminal(i.e. printf is not executed), now when i connect the pin 10 register to ground again the writefile api returns 1, and message is printed on output. if i do not toggele the pin 10 writefile() hangs. so if i have to output next byte i need to connect the pin 10 nACK to ground via 440 ohms register once and disconnect again. also if i exit the code, change the byte to send to some other value ,recompile the code and re-run the code, the new byte wont come on the port unless i ack the previous one. :) So its up and running now :) i will be making a DLL and post it here so that every body can use it. Thanks again Homer for your promt answers.

Best regards
Rohit
Posted on 2010-01-02 01:47:14 by rohitd
Hi,

i have one more query .
How can i access other i/o pins, i need to write to strobe and one or two output pins,and i need to read some of the other input pins (not the data port).

the programmer (to whihc i want t communicate)is using these pins for some syncronisation and reading the PIC micro controller information.

thanks and regards
rohit
Posted on 2010-01-02 02:09:02 by rohitd
You don't need to write to Strobe.

The computer will check the BUSY line, and if its ok, it will put its data out, and toggle the Strobe line.
Your device needs to somehow detect the Strobe line toggling.
It might be done by connecting it to the device's Clock line, assuming you can use an external clock!

So, once your device sees Strobe toggle, it knows theres some data, and accepts it (flashes its Load line, or whatever).
Shortly thereafter, it toggles the ACK line, which tells the computer it's time to check the BUSY line again.
So you could think of the ACK line as being the IRQ line.

So your problem isn't in the software at all, its in your interface design. Time to think about what goes where and when, but you're very close !
Posted on 2010-01-02 02:35:30 by Homer
hi,

since i am interfacing the PIC18F programmer to the parallel port, i need to interface all the pins as if i am using a normal LPT port. so i need to read few of the parallel port pins and write to parallel port pins [ none of these pins are from D0-D7 data port pins]. these port pins are needed to do some controlling work during flashing of the microcontroller.Initialy this programmer was designed for LPT port using the inputout32.dll, but if I want to use this programmer on the printer cable i should be able to access all the port pins available on printer port individualy. so i am wondering how to do this usning the windows api.

Best regards
rohit
Posted on 2010-01-02 03:17:48 by rohitd
If using a NT based OS you will need to use something like WinIO, which is an api that allows you to write to all the pins, and could be a replacement for all your existing code, giving you full control.

Here's the pinouts and the IO Port addresses for the data, control and status pins:
http://www.easyfreeware.com/images/screenshots/parallel_port_viewer_internet___networking-7310-screenshot.gif
Posted on 2010-01-02 03:47:53 by Homer
Hi Homer,
thanks for the information.
I downloaded winio.dll from the net. but  i was not able to get any VC source code using this dll. do you have any link from where i can download the cexample code for using the dll. also do i need to download any other supporting files.

best regards
rohit
Posted on 2010-01-02 04:45:42 by rohitd
Genuine package is here http://www.internals.com/utilities/winio.zip
Contains full source + C example also.
Posted on 2010-01-02 05:00:15 by Homer
Hi homer,
Thanks a lot for the files.
But how do i determine the physical address of my parallel port. since it is detected as a printing device. if i go in to the device manager there is no physical address asigned only some hardware id,matching device ids etc. BTW i am working on windows XP. Can api MapPhysToLin() be used for detecting the physical address.



best regards
rohit
Attachments:
Posted on 2010-01-02 06:09:38 by rohitd
Hi rohitd.

Is it too much to ask if you could just attach the complete project files? The code you have posted is in C#?.

Im trying to use this code with a similar adapter like yours.

Thank you, again.
Posted on 2010-01-14 21:58:01 by BrunoF
Well, i finally re-started all again but in VB6.

Its running ok, but really slow. It takes up to 3 seconds in sending 256 bytes to the port. I would like to believe that its because im not changing the ACK pin, so its changing with every timeout...

And, actually im with a pulldown  resistor on pin 10, and pin 11 floating...

I guess i will have to continue trying. I will connect a microcontroller tomorrow to make the ACK signal and see if i can speed it up.

Posted on 2010-01-17 21:59:08 by BrunoF
P.S.

Im using a "Manhatan" brand USB to parallel adapter.

Cheers.
Posted on 2010-01-17 21:59:58 by BrunoF
Maybe this could help.

Im investigating a little more, and seems that WriteFileEx() its similar to WriteFile(), but asynchronously. This may be helpful to, maybe(didnt test it) avoid acknowledge from device.

Cant tell the difference really. I have a testboard but tomorow will get final results.

Posted on 2010-01-17 22:24:05 by BrunoF
The only new thing in WriteFileEx is support for specifying a 'Completion Callback' function to be called when the IO request actually completes.

WriteFile/WriteFileEx BOTH support the use of OVERLAPPED IO, which is an alternative (and preferred) way to obtain notification of Completion of your IO request, via a data structure called Overlapped (which can contain your desired 64bit file offset for each IO request), and noting that you'll need to use FILE_OVERLAPPED flag in call to CreateFile.
Notification is typically received via triggering of an event handle (you placed in the overlapped struct), but it's also possible to use this kind of file io with IOCP thread pooling... allowing optimal performance on machines with more than one logical cpu through concurrent execution of one worker thread per logical cpu.

You have to ask yourself why you're using asynch file io - the caller will be returned control instantly, but the operation itself may still be pending completion, and any buffer associated with it must not be touched until it does complete... you end up , usually, having to work with lots of little data buffers (heap memory objects etc) which represent your io operations, and dispose of them when you're notified of their Completion - which, by the way, is your only chance to check for errors with Overlapped io model, since the Read/WriteFile calls will just return ERROR_IO_PENDING, meaning "your io operation will complete sometime later, don't call us, we'll call you".
Unless you have a lot of independant data channels, there's often little reason to use asynch io, and the more you expect from it, the more complicated your implementation can become.

For asynchronous io, Completion Callbacks are simple, but don't perform as well as Overlapped io, and don't scale as well as Overlapped IO with IO Completion Port event handling via a pool of worker threads.

It may be worth looking at the CreateFile flags again, you might want to try turning off the internal buffering etc. since your device doesn't have trouble keeping up with the port.

But WriteFileEx is not a solution by itself.
Problems... the hEvent field of the Overlapped struct is ignored by this api function, so we HAVE to use the Completion Routine, or the IOCP method.
And it gets worse.
The io subsystem will call your completion routine (or post a completion message to your iocp) when the first io operation completes.
But it won't post any subsequent notifications until your completion routine returns (or your iocp message is dequeued by a worker).
So even though several pending io operations may have completed, you'll only be notified about one of them!
The subtle difference between callback and iocp notifications is that the iocp workers can concurrently be dequeuing completion messages without blocking, whereas the completion callback notification scheme is actually BLOCKING!!!
Not really that asynchronous after all? They've just moved the bottleneck LOL!!!




Posted on 2010-01-18 00:26:47 by Homer
Hi Homer.

First, thanks for all before and actual assistence.

So, WriteFileEx isn't the solution. I started to believe it yesterday, when i start to play with FLAGS and nothing happens. The only difference, as you have perfectly said, is that the function returns before data send completion.

So, now the big question is how yo speed up data out, because its REALLY slow(like 80 Bps). I cant believe this could be used in any kind of decent printer...

Maybe with device ACK, times between data bytes will decreace.

Thx again.
Posted on 2010-01-18 07:34:22 by BrunoF