Bits eines Druckerports einlesen/ausgeben
-
Hallo Leute!
Kann mir vielleicht jemand sagen wie ich möglichst simpel einzelne Bits des Druckerports setzen und auslesen kann? Der Port hängt an keinem Drucker. Es soll einfach nur mit selbst gebauter Hardware kommuniziert werden.
Hab schon ordentlich gegooglet aber leider nichts passendes gefunden.
Betriebssystem: Win XP
Hoffen jemand kann mir helfen.
Vielen Dank schonmal.
-
CreateFile, ReadFile, WriteFile. Du liest/schreibst dann natürlich byteweise und musste eben mit Bitoperationen arbeiten.
Hier gibt's weiter unten ein Beispiel:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39403-and-start-is-0.html
_inp/_outp funktionieren nur auf alten Betriebssystemen wie Win98, also probier's erst gar nicht...

-
topic: http://electrosofts.com/parallel/
_matze schrieb:
_inp/_outp funktionieren nur auf alten Betriebssystemen wie Win98, also probier's erst gar nicht
unter xp geht's auch, zwar muss man bestimmte tricks anwenden, aber dann klappen selbst assembler in/out-instructions aus dem user mode.

-
Dieser Thread wurde von Moderator/in Nobuo T aus dem Forum ANSI C in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
~fricky schrieb:
topic: http://electrosofts.com/parallel/
_matze schrieb:
_inp/_outp funktionieren nur auf alten Betriebssystemen wie Win98, also probier's erst gar nicht
unter xp geht's auch, zwar muss man bestimmte tricks anwenden, aber dann klappen selbst assembler in/out-instructions aus dem user mode.

Welche Tricks sind das? Ich kenne dafür nur die InpOut32.dll.
-
-
#include "stdafx.h" #include <windows.h> #include <lmcons.h> // missing from mstask.h #include <mstask.h> #include <lmat.h> #include <wchar.h> #include <conio.h> // kbhit #pragma comment(lib, "netapi32.lib") #pragma comment(lib, "mstask.lib") #pragma comment(lib, "D:\\WINDDK\\3790.1830\\lib\\wxp\\i386\\ntdll.lib") extern "C" int __declspec(dllimport) __stdcall ZwSetInformationProcess(int,int,void*,int); #define ZwCurrentProcess() -1 #define ProcessUserModeIOPL 16 int SystemMain(int argc, _TCHAR* argv[]) { _putws(L"toggling LPT bits. Press any key to quit"); while (!_kbhit()) { Beep(900,40); _outp(888, 255); Sleep(200); Beep(900,40); _outp(888, 0); Sleep(200); } return 0; } int _tmain(int argc, _TCHAR* argv[]) { WCHAR text[32]; DWORD cch = 32; GetUserName(text, &cch); if (!_wcsicmp(text, L"SYSTEM")) { int IOPL = 3; ZwSetInformationProcess(ZwCurrentProcess(), ProcessUserModeIOPL, &IOPL, 4); return SystemMain(argc, argv); } // Taskplaner service soll gestarten werden AT_INFO at = {0,0,0,0,GetCommandLine()}; DWORD dwJob; CoInitialize(NULL); NET_API_STATUS status = NetScheduleJobAdd(NULL, (byte*)&at, &dwJob); if (status == 2184) { // this is temporary! You should use StartService() system("sc start schedule"); Sleep(1000); status = NetScheduleJobAdd(NULL, (byte*)&at, &dwJob); } if (!status) { // job name wsprintf(text, L"At%d", dwJob); ITaskScheduler *scheduler; if (!CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&scheduler)) { ITask *task; if (!scheduler->Activate(text, IID_ITask, (IUnknown**)&task)) { if (!task->Run()) { // task is queued for run, wait a little HRESULT hrStatus = SCHED_S_TASK_HAS_NOT_RUN; BOOL fWait = TRUE; while (fWait) { Sleep(200); ITask *task2; if (scheduler->Activate(text, IID_ITask, (IUnknown**)&task2)) break; task2->GetStatus(&hrStatus); if (hrStatus != SCHED_S_TASK_HAS_NOT_RUN) fWait = FALSE; task2->Release(); } } task->Release(); } scheduler->Delete(text); scheduler->Release(); } } CoUninitialize(); return 0; }
-
Hallo.
Wenn du mit einem bisschen "rumgebeepe" zufrienden bist, lies lieber nicht weiter. Nicht alle Assembler-Instruktionen sind privilegiert!
Ich vermute mal, du willst direkt die Register des Schnittstellen-ICs ansprechen (oder den 16550, oder, oder, oder ... die untersten 64 K des BIOS). Das das nicht mehr geht, hat nur bedingt mit dem OS zu tun. Es war eine Vereinbarung zwischen Intel und Microsoft. Der normale Progger kennt das als
USER-MODE (UM)
und
PROTECTED_MODE (PM).
Soll eine Variable X addressiert werden, entscheidet der Prozessor anhand seines Modus (UM/PM) und den Bits 0 und 1 der Addresse (stark vereinfacht), ob das Programm das überhaupt darf (UM: ja, PM: nein).
Diese zwei Bits repräsentieren vier Privilegien (auch stark vereinfacht):0: Kernel (= Hardware),
1: Driver,
2: Konsole,
3: Dein Win32-Programm mit schickem Fenster.Willst Du nun im PM von 3 auf 0 zugreifen, bekommst du eine Exception direkt vom Prozessor: EXCEPTION_PRIVILEGE_resthabichvergessen.
Das kommt aus der PrivilegeMap. Jede Addresse in den untersten 64 K ist in der Map durch ein Bit vertreten: Bit gesetzt = kein Zugriff.
Um das Bit zu löschen, brauchst du einen Treiber (Level 1), der das Bit löscht. Kleines Beispiel in deiner Sache:Du willst auf die Addressen 0378 - 037B (hex, Register LPT1) zugreifen. Über Win32 hast du keine Chance. Also nimmst du den "Service" GIVEIO.SYS. Der setzt dir die o.g. Bitmap komplett auf 0 (Random Access auf HardWare). Jetzt funktionieren alle privilegierten Assembler-Instruktionen (z.B. IN/OUT) wieder.
Handhabung:
0. giveio.sys ins system32
1. CreateFile("\\\giveio.sys\", ...); (das mit den Backslashes kann ich mir nicht merken, sorry. Guckst du MSDN)
2. Treiber muss gestartet sein (OpenSCManager oder Start->Systemsteuerung->...)
3. Have fun and if u dont have the knowledge, use acronis before.VORSICHT! VORSICHT! VORSICHT! Du konkurrierst mit deinem BIOS !!!!!!!!!!!!!
Gruß
Lars
-
1. Die ausfühliche Erklärung steht im Datenblatt vom jeweiligen Intel-Prozessor (selten weniger als 4000 Seiten). Viel Spass beim Lesen.
2. Experiment:
- Starte dein Programm (mit GIVEIO.SYS)
- Starte einen lange dauernden Druckjob
- funke mal dem Spooler dazwischen.
-
... sieht so aus
__asm
assembly-language-instruction__asm
{
assembly-language-instructions
}(MSDN)