[VYŘEŠENO] C: Jak zprovoznit program na čtení 2 portů LPT?

Počítače stolní, notebooky, tablety, tiskárny, scanery a vše, co nějak souvisí s PC

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
MetalGod
Příspěvky: 6556
Registrován: 30 kvě 2006, 02:00
Bydliště: Seč

[VYŘEŠENO] C: Jak zprovoznit program na čtení 2 portů LPT?

#1 Příspěvek od MetalGod »

Dělám prográmek, kterej má zobrazit údaje sebraný paralelním portem o šířce až 12 bitů (8x data na 0x37c, 4x řídící na 0x37a). V Cčku skoro neumím, ale podařilo se mi sesmolit aspoň tohle:

Kód: Vybrat vše

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>

#define portC 0x37a
int main()

{
   if (ioperm(portC, 1, 1))
    fprintf(stderr, "\e[31;43m Nemáš oprávnění \e[0m\n"), exit(1);
    outb(0, portC);
    int dataC = inb(portC);
    printf("%i\n", (256*(dataC-192)));
}
Tady pracuju s portem 0x37a (řídicí; data lze číst i na portu 0x37c v režimu EPP).
Podmínka zjišťuje oprávnění, jestli lze číst a zapisovat, outb zajišťuje nulování, pak se vstup přečte, printfem převede na desítkovou soustavu, odečte 192 (horní 4 bity nelze ovládat a nejsou k nim dráty) a, protože to budou horní 4 bity, vynásobí se to 256. Přestože jsou 3 ze 4 vstupů za invertorem, funguje to na jednom i druhým portu.

Jenže jsem se pokusil do toho nabastlit i čtení z datovýho portu, nevím, kde dělám chybu, sestaví se bez keců, ale hází mi po spuštění SIGSEGV, a to už od druhýho outb (kdy zbytek kódu je z předchozího) a vlastně u další "zdvojený" definice dataC:

Kód: Vybrat vše

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
 
#define portD 0x37c
#define portC 0x37a

int main()
{
   if (ioperm(portD, 1, 1))
    fprintf(stderr, "\e[31;43m Nemáš oprávnění \e[0m\n"), exit(1);
    outb(0, portD);
    outb(0, portC);
    int dataD = inb(portD);
    int dataC = inb(portC);
    printf("%i\n", (dataD+256*(dataC-192)));
}
Naposledy upravil(a) MetalGod dne 21 říj 2020, 12:03, celkem upraveno 2 x.
Kdo není ve dvaceti levičák, nemá srdce,
kdo je levičák ve čtyřiceti, nemá rozum.
— Winston Churchill

p32
Příspěvky: 15069
Registrován: 13 led 2007, 01:00
Bydliště: Olomouc

#2 Příspěvek od p32 »

Nechci ti do toho moc kecat, ale pokud chceš číst ze dvou paralelních portů, tak bych si to vyzkoušel napřed na jednom (podprogramem A) a potom na druhém (podprogramem B). Oba podprogramy A i B by měly mít svoje proměnné, protože nakonec jejich vyselektované části jen na čtení jako A1 a B1 budeš volat z jednoho hlavního programu do dalších proměnných (či adresového buffru). Ten zbytek pro inicializaci portů z programů A a B po vyselektování A1 a B1 dáš do části hlavního programu na začátek a případně na konec pro zavření portů apod.
Schválně jsem to tak psal (selsky), protože si to upravíš už podle svého. Jsem zvyklý psát programy s padesáti tisíci řádků a více, takže vím, že každý si to výsledně zmuchlá podle svého. Tzn. že každý si to udělá tak, aby se v tom za týden ještě vyznal nebo ne a potom je ztracenej. :wink:

Zkus si to psát od začátku ve stylu:

#define portC 0x37a
#define portD 0x37c

místo

#define portD 0x37c
#define portC 0x37a

atd.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#3 Příspěvek od rnbw »

ioperm() volas len pre portD.

P.S. Pri praci s bitmi pouzivaj bitove operacie.

Uživatelský avatar
MetalGod
Příspěvky: 6556
Registrován: 30 kvě 2006, 02:00
Bydliště: Seč

#4 Příspěvek od MetalGod »

rnbw: Aha, to je ono! Už to funguje!
Měl jsem za to, že tím iopermem akorát zjišťuju dostupnost jednoho z portů, kdy je logický, že druhej bude spolu s ním stejně dostupnej.

Takže tohle funguje:

Kód: Vybrat vše

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>

#define portD 0x37c
#define portC 0x37a

int main()
{
	if ((ioperm(portD, 1, 1)) | (ioperm(portC, 1, 1)))
	fprintf(stderr, "\e[31;43m Nemáš oprávnění \e[0m\n"), exit(1);
	outb(0, portD);
	outb(0, portC);
	int dataD = inb(portD);
	int dataC = inb(portC);
	printf("%i\n", (dataD+256*(dataC-192)));
}
Díky, chlapi!

P. S.: Asi by to nešlo zaonačit, abych to nemusel spouštět přes roota, co? Třeba kouzlením s /dev/lp0.
Kdo není ve dvaceti levičák, nemá srdce,
kdo je levičák ve čtyřiceti, nemá rozum.
— Winston Churchill

Uživatelský avatar
Zmije
Příspěvky: 1513
Registrován: 30 čer 2005, 02:00
Bydliště: Pardubický kraj

#5 Příspěvek od Zmije »

Předpokládám, že to řešení je pro Linux. Ve zdrojácích Avrdude je řešení pro Linux, FreeBSD a Windows

Speciální oprávnění (root, skupina, výjimka v sudores, ...) bude asi potřeba vždy, když se šahá přímo na HW.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#6 Příspěvek od rnbw »

Inak v Linuxe sa da pouzit namiesto priameho pristupu k HW zariadenie /dev/parport*. Potom to nemusi bezat pod rootom a moze to fungovat aj na inych paralelnych portoch (nielen "typu PC").

Uživatelský avatar
Zmije
Příspěvky: 1513
Registrován: 30 čer 2005, 02:00
Bydliště: Pardubický kraj

#7 Příspěvek od Zmije »

/dev/parport vypadá zajímavě
https://mockmoon-cybernetics.ch/compute ... rport.html
https://www.kernel.org/doc/html/latest/ ... rport.html
https://github.com/spotify/linux/blob/m ... arport.txt
https://www.htlinux.com/parallel_port_control_in_linux

U těch oprávnění asi hodně záleží jak je to nastavené v distribuci, třeba Ubuntu po mě chce sudo i když přistupuji na obyčejnou USB-seriovku /dev/ttyUSB*
Naposledy upravil(a) Zmije dne 18 lis 2020, 11:30, celkem upraveno 1 x.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#8 Příspěvek od rnbw »

V Debiane su seriove porty v skupine dialout, paralelne v skupine lp. Takze staci pridat pouzivatela do potrebnej skupiny.

Uživatelský avatar
Zmije
Příspěvky: 1513
Registrován: 30 čer 2005, 02:00
Bydliště: Pardubický kraj

#9 Příspěvek od Zmije »

V tom případě by mohla existovat možnost vytvořit novou skupinu třeba directio a tu nastavit tak, aby uživatele v ní mohli přistupovat přímo k HW.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#10 Příspěvek od rnbw »

To nejde, pre priamy pristup na I/O porty musi mat proces pravo CAP_SYS_RAWIO a k tomu sa bez roota nedostane.

Uživatelský avatar
Zmije
Příspěvky: 1513
Registrován: 30 čer 2005, 02:00
Bydliště: Pardubický kraj

#11 Příspěvek od Zmije »

A co takhle
sudo setcap cap_sys_rawio jmeno_programu

Ono se ani to /dev/parport možná neobejde bez roota, protože je potřeba udělat insmod ovladače, pokud s ním není kernel už přeložený.

Potom se nabízí obejít to pomocí démona pod rootem, který se spustí během initu a bude poslouchat na tcp / udp na loopbacku, nebo unix socketu, případně přes IPC.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#12 Příspěvek od rnbw »

Rucne zavadzat modul bolo potrebne naposledy pri ISA LPT portoch.

Odpovědět

Zpět na „Výpočetní technika“