#pragma comment(linker, "/NOD /OPT:NOWIN98 /ALIGN:4096 /RELEASE") #include #include HANDLE hStdIn, hStdOut, hStdErr; HANDLE hAccess; BYTE gError; void outb(BYTE a, BYTE b) { BYTE IoData[2]; DWORD BytesRet; IoData[0]=a; IoData[1]=b; DeviceIoControl(hAccess, CTL_CODE(FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS), IoData,sizeof(IoData),NULL,0,&BytesRet,NULL); } BYTE inb(BYTE a) { BYTE IoData[1]; DWORD BytesRet; IoData[0]=a|0x10; // Lese-Bit DeviceIoControl(hAccess, CTL_CODE(FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS), IoData,sizeof(IoData),IoData,sizeof(IoData),&BytesRet,NULL); return IoData[0]; } void _cdecl printf(const char*t,...){ TCHAR buf[256]; DWORD len; len=wvsprintf(buf,t,(va_list)(&t+1)); CharToOemBuff(buf,buf,len); WriteConsole(hStdOut,buf,len,&len,NULL); } int JaNein(void){ char c; DWORD len,OldMode; GetConsoleMode(hStdIn,&OldMode); SetConsoleMode(hStdIn,0); ReadConsole(hStdIn,&c,1,&len,NULL); printf("%c\n",c); SetConsoleMode(hStdIn,OldMode); switch (c){ case 'J': case 'j': case 'Y': case 'y': return IDYES; case 'N': case 'n': return IDNO; } return 0; } void Check(BYTE bData, BYTE bStatus, BYTE bControl, BYTE bDoOut){ if (bDoOut){ outb(0,bData); outb(1,(bStatus^0x80)|0x07); outb(2,(bControl^0x0B)&0x0F); } bData^=inb(0); bStatus^=inb(1)^0x80; bStatus&=0xF8; bControl^=inb(2)^0x0B; bControl&=0x0F; if (bData) printf("Datenfehler: %02X\n",bData); if (bStatus) printf("Statusfehler: %02X\n",bStatus); if (bControl) printf("Steuerfehler: %02X\n",bControl); gError|=bData|bStatus|bControl; } int _cdecl mainCRTStartup(){ BYTE b; WORD adr,date; DWORD sn,br; hStdIn =GetStdHandle(STD_INPUT_HANDLE); hStdOut=GetStdHandle(STD_OUTPUT_HANDLE); hStdErr=GetStdHandle(STD_ERROR_HANDLE); rept: for (sn=8;sn;sn--){ // von hinten probieren TCHAR DevName[8]; wsprintf(DevName,"LPT%u",sn); hAccess=CreateFile(DevName, GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); if (hAccess!=INVALID_HANDLE_VALUE) break; } if (hAccess==INVALID_HANDLE_VALUE){ printf("USB2LPT anstecken, muss LPTx sein!\n"); goto ende; } outb(0x0A,0x00); // SPP-Modus outb(0x0D,0x00); // Statusleitungen Ausgänge if (inb(0x0D)&0xF8){ printf("Dieser Test erfordert Firmware 060629 oder neuer!\n"); goto ende; } #if 0 // C2-Byte löschen (Brücke funktioniert nicht!) adr=0; sn=(DWORD)-1; DeviceIoControl(hAccess, CTL_CODE(FILE_DEVICE_UNKNOWN,0x08A2,METHOD_IN_DIRECT,FILE_ANY_ACCESS), &adr,sizeof(adr), &sn,sizeof(sn),&br,NULL); #endif adr=0xFFFC; // Seriennummer-Position DeviceIoControl(hAccess, CTL_CODE(FILE_DEVICE_UNKNOWN,0x08A2,METHOD_OUT_DIRECT,FILE_ANY_ACCESS), &adr,sizeof(adr), &sn,sizeof(sn),&br,NULL); if (!(~sn&0xFFFFFF)) sn>>=24; // Seriennummer im MSB (altes Format) printf("Seriennummer: %u\n",sn); adr=0x0006; // Datums-Position DeviceIoControl(hAccess, CTL_CODE(FILE_DEVICE_UNKNOWN,0x08A3,METHOD_OUT_DIRECT,FILE_ANY_ACCESS), &adr,sizeof(adr), &date,sizeof(date),&br,NULL); printf("Firmware-Erstellungsdatum: %u-%02u-%02u\n", (date>>9)+1980,(date>>5)&0x0F,date&0x1F); gError=FALSE; // Prüfen auf Kurz- und Masseschlüsse printf("Automatische Kurzschluss- und Masseschluss-Prüfung...\n"); for(b=1;b;b<<=1) { // Daten testen Check(b,0,0,TRUE); Check(~b,0xFF,0xFF,TRUE); } for(b=8;b;b<<=1) { // Statusleitungen Check(0,b,0,TRUE); Check(0xFF,~b,0xFF,TRUE); } for(b=1;b<0x10;b<<=1) {// Steuerleitungen Check(0,0,b,TRUE); Check(0xFF,0xFF,~b,TRUE); } outb(2,0xFF^0x0B); // Prüfen auf Vorhandensein der Pullups outb(0x0C,0xFF); // Alles Eingänge outb(0x0D,0xFF); outb(0x0E,0xFF); Check(0xFF,0xFF,0xFF,FALSE); // muss alles High sein // Gegenprobe funktioniert nur mit Rev.3 outb(0x0F,0x80); // Pullups AUS (Feature) printf("Rev.3: Sind die LEDs (vom LptChk) jetzt sehr dunkel? "); if (JaNein()==IDNO) gError|=1; outb(0x0F,0x00); // Pullups EIN outb(0x0C,0x00); outb(0x0D,0x00); outb(0x0E,0x00); printf("Leuchten alle LEDs hell? "); if (JaNein()==IDNO) gError|=1; // Prüfung, ob die Pins angelötet(!) sind Check(0x00,0x00,0x00,TRUE); printf("Sind alle LEDs aus? "); if (JaNein()==IDNO) gError|=1; if (gError){ SetConsoleTextAttribute(hStdOut,FOREGROUND_RED|FOREGROUND_INTENSITY); printf("!!! FEHLER !!! Lötarbeit!\n"); SetConsoleTextAttribute(hStdOut,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); }else{ SetConsoleTextAttribute(hStdOut,FOREGROUND_GREEN|FOREGROUND_INTENSITY); printf("Keine Kurz- und Masseschlüsse. Alles OK.\n"); SetConsoleTextAttribute(hStdOut,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); } outb(0x0D,0xFF); // Eingänge Check(0xFF,0xFF,0x07,TRUE); // etwaiger Ausgangszustand Check(0x00,0xFF,0x07,TRUE); ende: CloseHandle(hAccess); printf("\nBeliebige Taste zum Programmende drücken (J für Wiederholung)..."); if (JaNein()==IDYES) goto rept; return 0; }