Stránka 1 z 1

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

Napsal: 21 říj 2020, 10:42
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)));
}

Napsal: 21 říj 2020, 11:40
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.

Napsal: 21 říj 2020, 11:48
od rnbw
ioperm() volas len pre portD.

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

Napsal: 21 říj 2020, 11:59
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.

Napsal: 23 říj 2020, 00:59
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.

Napsal: 23 říj 2020, 08:32
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").

Napsal: 23 říj 2020, 10:36
od Zmije
/dev/parport vypadá zajímavě
https://mockmoon-cybernetics.ch/computer/linux/programming/parport.html
https://www.kernel.org/doc/html/latest/admin-guide/parport.html
https://github.com/spotify/linux/blob/master/Documentation/parport.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*

Napsal: 23 říj 2020, 11:07
od rnbw
V Debiane su seriove porty v skupine dialout, paralelne v skupine lp. Takze staci pridat pouzivatela do potrebnej skupiny.

Napsal: 23 říj 2020, 11:18
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.

Napsal: 23 říj 2020, 11:30
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.

Napsal: 23 říj 2020, 13:48
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.

Napsal: 23 říj 2020, 14:09
od rnbw
Rucne zavadzat modul bolo potrebne naposledy pri ISA LPT portoch.