lundi 8 février 2016

Utiliser un minitel comme un terminal avec un Raspberry Pi

Encore un article sur l'utilisation d'un minitel en tant que terminal, mais celui ci est plus direct, car les articles que j'ai lu datent d'une époque ou systemd n'était encore qu'a ses débuts dans Debian (Raspbian pour les Pis).



Le truc qui m'a le plus embetté dans ma recherche d'infos c'est de voir des articles ou l'auteur avait acheté un adapteur USB-UART au lieu d'utiliser directement l'UART présent sur raspberry pi.

Le montage électronique : 


Alors, tout d'abord faites attention encore un coût caché du raspberry : ses entrées/sorties ne sont pas protégées ! Donc à vous d'utiliser un buffer qui adaptera le signal au GPIOs ou comme sur mon schéma d'utiliser des diodes Zener de 3,3V pour empécher toute surtension suceptible de griller vos précieuses entrées (je n'ai pas confiance en ce vieux minitel dont la broche Rx peut monter jusqu'a 15V). On utilise le 3,3V du Pi, sa masse (qu'on relie à celle du minitel) et les broches TX0 et RX0.
Le brochage DIN du minitel vu coté soudure
Pour la conversion en elle même : la broche transmission du minitel (Tx mi) est en collecteur ouvert, cela signifie qu'il y a un transistor qui impose le 0.
Sur le schéma on j'ai mis une resistance de rappel de 200k ohm (30k est déjà assez grand) vous pouvez vous en passer si connecté sur le raspberry Pi (les GPIO sont déjà équipé de résistance de ~50k). Je conseil de la laisser pour faire des tests de connection (par exemple faire un retour la sortie Tx du minitel sur son Rx).

La branche de réception du minitel semble être une résistance de tirage, je lui ai mesuré une tension de 4V en entrée. Le montage se comporte ainsi: lorsque Tx pi est en état bas le transistor est passant (Rx mi relié à la masse = 0V), lorsque que Tx pi est à l'état haut (3,3V) le transistor est bloqué, Rx mi est "tiré" à 4V par le minitel.

Configurer le minitel

Appuyez en même temps sur Fnct+T, puis A (passage en mode périphérique)
Puis : Fnct+T puis E (désactivation de l'echo du terminal)
Puis : Fnct+P puis 4 (Passage à une connection à 4800 baud/s)

Par défaut le minitel est a une connection à 1200 bauds. Chaque caractère est envoyé sur 7 bits, avec une parité paire (bit de controle) et un bit de stop.

Tester la connection

Dans un terminal tapez :

#Pour configurer la connection série et le tty
stty -F /dev/ttyUSB0 4800 istrip cs7 parenb -parodd brkint \
ignpar icrnl ixon ixany opost onlcr cread hupcl isig icanon \
echo echoe echok
# Tester l'envoi vers le minitel
echo 'Hello World' > /dev/ttyAMA0
# Tester la réception des données depuis le minitel (elle
seront seulement affichées sur le minitel si vous n'appuyez pas sur entrée)
cat /dev/ttyAMA0

Vous pouvez déjà essayer d'avoir un tty avec (attention c'est sale mais vous pouvez tout de même vous logger) :

agetty ttyAMA0 4800

Avoir un tty au démarrage

La configuration peut être extrèmement simple : ajoutez à /boot/cmdline.txt

console=ttyAMA0,4800e7 loglevel=1

4800 bauds sur 7 bits et de parité paire (even en anglais).
L'option logelevel=1 est utile pour avoir le moins d'info envoyé au terminal (la connection est plutôt lente et va ralentir le démarrage).

Si vous voulez avoir les erreurs du kernel ajoutez-y également :
kgdboc=ttyAMA0

Ce moyen marche plutôt bien, on a même les logs de boot mais agetty affiche d'immondes rectangles blancs, en effet il essaye de resetté les paramètres du terminal. De plus le fichier terminfo qui contient la définition de tout les caractères d'échappement (ces caractères qui permettent de faire bipper le minitel, de changer ses paramètre par exemple) ne correspond pas au terminal (par défault vt100 et pas minitel1b-80). Vous aurez un terminal qui fonctionne mais des logiciels avec des interfaces curse aura des problèmes (exemple raspi-config, menu-wifi... etc.).

À propos, le fichier /boot/cmdline.txt est l'ensemble des arguments fourni au kernel lors au démarrage. Sur un linux avec grub ce sont les paramètres que l'on retrouve sur les ligne "linux" dans le grub.conf.

Comment avoir un terminal "propre"

Il nous faut donc le fichier de définition du minitel il n'est pas sur debian par défaut. Télécharger le ici et placer le dans /etc/terminfo/m/ (il est possible qu'il soit déjà présent dans votre /usr/share/terminfo). Dans ce tuto on utilise le fichier minitel1b-80.

Je trouve que la définition minitel1b-80 n'est pas parfaite, je m'attarderai peut être à le modifier un jour. Quelqu'un l'a fait !  Alexandre MONTARON qui a bien gentiment mis un lien vers cet article. Il met à jour les terminfos pour les différents minitels (le mien est un de 80 colonnes en noir et blanc).

Pour avoir sa version télécharger (il donne le fichier source !!!) le fichier mntl.ti ici et compilez le.

tic mntl.ti -dir /etc/terminfo

Vous pouvez par la suite sélectionner le bon fichier de définition (m1b, m1b-nb, m1b-x80).

Le fichier de définition est utilisé ainsi avec agetty (alternative getty qui est une version en ligne de commande de getty) :

agetty -c ttyAMA0 4800 minitel1b-80

L'option -c pour agetty corrige le problème des rectangles blanc dont j'ai parlé plus haut.

Maintenant il nous faut dire à notre système d'utiliser cette commande. Avec Raspbian Jessie l'inittab n'est plus utilisé (systemd gère l'obtention de tty), /etc/inittab est toujours présent mais inutile.

Du coup, l'obtention du tty marche ainsi :
  • soit le kernel dit qu'il veut un tty (avec l'option console=...)
  • soit un fichier de configuration systemd existe
Un mix des deux est possible, le kernel dit qu'il veut un tty, qu'il va utiliser pour afficher ses log de démarrage, mais systemd utilise le fichier de configuration si il est présent.

Il va falloir créer un fichier de configuration systemd avec les bons paramètres :

/etc/systemd/system/serial-getty\@.service 
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Serial Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
BindsTo=dev-%i.device
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

[Service]
ExecStart=-/sbin/agetty -c %i 4800 minitel1b-80
Type=idle
Restart=always
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target

Ensuite il n'y a plus qu'a activer le service au démarrage et le lancer.
ln -s /etc/systemd/system/serial-getty@.service /etc/systemd/system/getty.target.wants/serial-getty@ttyAMA0.service
systemctl daemon-reload
systemctl start serial-getty@ttyS2.service

Voilà maintenant amusez vous à modifier les messages d'accueil dans /etc/issue et /etc/motd :)

Bonus 

Quelques combinaisons de touches non triviales :

Ctrl+1  {   Ctrl+4  ~
Ctrl+2  |    Ctrl+5  '
Ctrl+3  }   Ctrl+6  _

Fnct+1 F1
Fnct+2 F2
   ...       ...
Fnct+0 F10

Et à essayez à tout prix, le starwars en ASCII :

telnet towel.blinkenlights.nl

À propos de mgetty

Certains essayent de remplacer agetty par mgetty, passez votre route... J'ai passé une journée entière dessus. Il faut compiler les sources patchées et même là, on a un login moche qui ne marche pas car mgetty n'aime pas être en dehors de son groupe de processus "terminal" (i.e. être lancé au démarrage).

Sources

http://www.jbase.com/r5/knowledgebase/howto/general/common/CreateTerminfo/modify.htm
http://pila.fr/wordpress/?p=361
http://minitel.lozi.org/
http://tldp.org/HOWTO/Text-Terminal-HOWTO-16.html
http://www.tldp.org/HOWTO/Text-Terminal-HOWTO-19.html
http://www.faqs.org/docs/Linux-HOWTO/Remote-Serial-Console-HOWTO.html#GETTY-GETTY

Aucun commentaire:

Publier un commentaire