Invite/Prompt Bash, couleur et line wrapping

Encore un billet qui est davantage un mémo pour moi que pour vous ;)

Si vous tritouillez l’invite du shell bash en ajoutant des couleurs (mise en avant du nom du serveur pour pas se mélanger les pinceaux par exemple), pensez à entourer vos séquences d’échappement de crochets. Ainsi, ceci :

PS1='[t] u@e[1;31mh-plop1(wp)e[0m:w % '

devient ceci :

PS1='[t] u@[e[1;31m]h-plop1(wp)[e[0m]:w % '

Siiiiii…. regardez bien :

e[1;31m

et hop

[e[1;31m]

Cela permettra au shell de bien calculer le nombre de caractères qui composent une ligne et ainsi d’éviter d’écraser le début de la ligne avec des caractères surnuméraires et tout ce que cela implique (gestion des retours à la lignes, chaos dans l’affichage de l’historique des commandes, etc).

Télécommander X avec x2x

Je vais un peu mumuse avec Evony depuis quelque temps. C’est un jeu de stratégie façon Freeciv mais massivement multijoueur et… en Flash (hé oui). Bref, la question n’est pas là. C’est amusant, ça passe le temps mais avoir une fenêtre de navigateur avec un gros machin Flash c’est un peu consommateur de ressources CPU. Autant le faire fonctionner sur une autre machine. Mais voilà, je n’ai pas forcément envie d’avoir 15 claviers/souris sur mon bureau. Un écran LCD supplémentaire, je tolère, mais pas plus.

La solution est donc d’utiliser un sympathique outil appelé x2x. Ça s’installe en deux temps trois mouvements :

denis@MachineCourante:~ % sudo aptitude install x2x
denis@MachineCourante:~ % ssh NouvelleMachine
denis@NouvelleMachine: ~ % export DISPLAY:0.0
denis@NouvelleMachine: ~ % xhost +Machine2Courante
denis@NouvelleMachine: ~ % logout
denis@MachineCourante:~ % x2x -west -to NouvelleMachine:0.0

Et voilà, dès que x2x est lancé la souris pilote automatiquement le display de NouvelleMachine dès qu’elle passe le bord gauche (ouest) de l’écran de MachineCourante. Il est également possible d’utiliser cela au travers de SSH mais ce n’était pas nécessaire ici.

Pour info, NouvelleMachine est une vieille poubelle sous Debian Lenny avec un LXDE et Firefox+Flash. Suffisant pour servir de moniteur pour Evony ou n’importe quelle autre activité tout aussi critique ;)

Install Debian Lenny depuis une clef USB

Pour créer une clef USB d’installation Debian procéder comme suit :

Récupérer le fichier boot.img.gz depuis  un FTP Debian

Le dumper vers la clef USB : zcat boot.img.gz > /dev/sdc

Monter la clef : mount /dev/sdc /mnt/point

Télécharger l’image ISO du CD Netinst depuis le FTP Debian

Copier l’image ISO sur la clef : cp debian-502a-i386-businesscard.iso /mnt/point/ && sync && umount /mnt/point

Connecter la clef à la machine cible et booter

Note : Ce billet est plus un mémo pour moi-même qu’autre chose puisque l’info se trouve un peu partout. Ça m’agace juste de chercher à chaque fois.

Nommage udev en fonction de l’interface (bInterfaceNumber)

Je viens tout juste de recevoir un nouveau programmeur AVR sur port USB. Bonne nouvelle, celui-ci propose non pas un port série de type ttyACM* mais deux (le second fournissant un port USB/TTL simple). Mauvaise nouvelle, une règle udev classique (voir ce billet) ne fonctionne pas. En effet, la règle match les deux interfaces et on se retrouve systématiquement avec un lien symbolique pointant sur la seconde interface. Le programmeur est inaccessible proprement via un Makefile.

Le problème ici est de mixer des attributs provenants à la fois du périphérique (product) et du périphérique parent (bInterfaceNumber). Ceci ne fonctionne donc pas :

SUBSYSTEMS=="usb", KERNEL=="ttyACM*", ATTRS{product}=="Pololu USB AVR Programmer", SYMLINK+="POLOLU"

Pas plus que :

SUBSYSTEMS=="usb", KERNEL=="ttyACM*", ATTRS{product}=="Pololu USB AVR Programmer", ATTRS{bInterfaceNumber}==02, SYMLINK+="POLOLU_SERIAL"

Il faut être plus tordu et réutiliser le nom d’un attribut du périphérique pour nommer le lien symbolique avec :

SUBSYSTEMS=="usb", KERNEL=="ttyACM*", ATTRS{product}=="Pololu USB AVR Programmer",  SYMLINK+="POLOLU%s{bInterfaceNumber}"

Ce qui nous donne :

% ls -l /dev/POL*
13099267 lrwxrwxrwx 1 root root 7 jui 21 21:01 /dev/POLOLU00 -> ttyACM0
13099249 lrwxrwxrwx 1 root root 7 jui 21 21:01 /dev/POLOLU02 -> ttyACM1
Pareil en présence d'un autre programmeur ttyACM* :
13105697 lrwxrwxrwx 1 root root 7 jui 21 21:10 /dev/POLOLU00 -> ttyACM1
13105715 lrwxrwxrwx 1 root root 7 jui 21 21:10 /dev/POLOLU02 -> ttyACM2

Ça n’est pas exactement ce que je voulais (POLOLU0 et POLOLU1) mais c’est fixe et clair. On va pas chercher la petite bête…

Carte FXO X100P Zaptel Dahdi : Failed to initailize DAA, giving up

Heureux propriétaire que je suis d’une carte FXO X100P pour mon Asterisk, j’ai eu la mauvaise idée de mettre à jour mon kernel en 26.29 sur ma chère Debian. Là impossible de recompiler le module avec m-a. Après recherche et environs 50 checkout SVN… je me suis rendu compte qu’il n’y a pas que zaptel-source dans la vie mais aussi dahdi-source.

Ainsi, aptitude install dadhi-source, m-a -t a-i dahdi-source et modprobe wcfxo… et :
[874853.416148] dahdi: Telephony Interface Registered on major 196
[874853.416151] dahdi: Version:
[874853.418471] wcfxo 0000:03:07.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[874853.460005] NOTICE-wcfxo: WCFXO/0: Unknown DAA chip revision: REVB=0
[874853.460008] Failed to initailize DAA, giving up…
[874853.460058] wcfxo: probe of 0000:03:07.0 failed with error -5
Quoi what ? WTF ?

Le problème d’est l’IRQ, la solution c’est un petit bout de code :
Index: wcfxo.c
===================================================================
— wcfxo.c (revision 4616)
+++ wcfxo.c (working copy)
@@ -696,6 +696,16 @@
/* Hardware stuff */
/* Reset PCI Interface chip and registers */
outb(0x0e, wc->ioaddr + WC_CNTL);
+
+ /* Set all to outputs except AUX 4, which is an input */
+ outb(0xef, wc->ioaddr + WC_AUXC);
+
+ /* Reset the DAA (DAA uses AUX5 for reset) */
+ outb(0x00, wc->ioaddr + WC_AUXD);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 + HZ / 800);
+
+ /* Set hook state to on hook & un-reset the DAA */
if (wc->flags & FLAG_RESET_ON_AUX5) {
/* Set hook state to on hook for when we switch.
Make sure reset is high */
@@ -704,9 +714,7 @@
/* Set hook state to on hook for when we switch */
outb(0x24, wc->ioaddr + WC_AUXD);
}
– /* Set all to outputs except AUX 4, which is an input */
– outb(0xef, wc->ioaddr + WC_AUXC);

+
/* Back to normal, with automatic DMA wrap around */
outb(0x01, wc->ioaddr + WC_CNTL);
Donc, on apt-get source dahdi-source, on édite le fichier drivers/dahdi/wcfxo.c, puis on dpkg-buildpackage -rfakeroot pour enfin dpkg -i ../dahdi-source_2.2.0~dfsg~rc5-1_all.deb et re m-a.

Zou :
[876677.300909] dahdi: Telephony Interface Registered on major 196
[876677.300913] dahdi: Version:
[876677.360006] wcfxo: DAA mode is ‘FCC’
[876677.360009] Found a Wildcard FXO: Wildcard X100P
Bonheur !

Merci https://issues.asterisk.org/view.php?id=14232

Installation pseudo-propre de binaires sur Debian

Pris d’une nostalgie coupable, je m’étais mis dans la tête de bruler un peu de mon temps à quelque chose de purement inutile : jouer. Dans ce domaine comme dans quelques autres, les vieux classiques sont souvent les meilleurs solution. J’ai donc opté pour quelque chose de classique : Doom.

Debian fourni un paquet prboom constitué du programme diffusé par Id Software sous GPL et légèrement amélioré. Le paquet freedoom, quant à lui, fourni les données (cartes, monstrer, textures, effets sonores).

Mais je voulais quelque chose de plus… de moins… de mieux ! J’ai donc regardé du côté de Doomsday et compilé tout cela après installation d’une certaine quantité de dépendances (cycle cmake-capamarche-aptitude).

Et voilà, c’est compilé. Arrive le moment d’installer tout cela et là… c’est le drame ! Hors de question de jouer du make install à l’arrache. Je voulais un paquet bien propre.

La solution : checkinstall.

Et donc, au final, dans l’ordre :
% tar xfzv deng-1.9.0-beta6.1
.tar.gz
% cd deng-1.9.0-beta6.1
% mkdir doomsday/mybuild
% cd doomsday/mybuild
% cmake -DCMAKE_INSTALL_PREFIX=/usr  ..
[…]
— CMAKE_INSTALL_PREFIX          /usr
— DENG_BASE_DIR                 /usr/share/deng
— DENG_LIBRARY_DIR              /usr/lib
— DENG_BINARY_DIR               /usr/bin
— DENG_ENGINE_DATA_DIR          /usr/share/deng/data
— DENG_JDOOM_DATA_DIR           /usr/share/deng/data/jdoom
— DENG_JHERETIC_DATA_DIR        /usr/share/deng/data/jheretic
— DENG_JHEXEN_DATA_DIR          /usr/share/deng/data/jhexen
— DENG_JDOOM64_DATA_DIR         /usr/share/deng/data/jdoom64
[…]
% make
% checkinstall
Et voilà. Au final, on retrouve un sympathique doomsday_20090425-1_i386.deb dans le répertoire courant et les fichiers bien proprement installés. Bien sûr, ce n’est pas parfait, aucune dépendance n’est gérée, etc. Mais la désinstallation se fait très bien (via dpkg -P) et c’est le plus important.

Pour une petite demi-heure de jeu et le plaisir de massacrer quelques cacodemons avec des effets 3D bien plus sympathiques que dans le jeu original, c’est suffisant. Accessoirement, le binaire supporte ausso bien Doom, qu’Heretic ou Hexen…

Nostalgie, nostalgie…

ttyUSB0 ? ttyUSB2 ? Non, ttyUSB1… Graaaahh ! udev !

J’ai acheté il y a quelque temps plusieurs de ces petites choses :

Des convertisseurs USB/Série en TTL (0-5V). Ceci permet de connecter directement, sans max232, un adaptateur USB/Série à un montage à base de microcontrôleur (genre Atmel AVR) ou un système embarqué (genre Fonera, remarquez le cavalier permettant de choisir 5V ou 3.3V, convitude). Seulement, voilà :
je branche un adaptateur, il est accessible via /dev/ttyUSB0
j’en branche un autre qui devient /dev/ttyUSB1
je débranche le premier et en branche deux autres et ça devient la fête aux ttyUSB*

Où est ma Fonera 1, où est mon Attiny2313, où est ma Fonera 2… etc…  ?

On trouve dans /sys/bus/usb-serial/devices plein de choses intéressantes avec udevinfo -a -p. Parmi lesquelles :
ATTRS{manufacturer}== »FTDI »
ATTRS{product}== »FT232R USB UART »
ATTRS{serial}== »A90066ai »
Du coup, il ne reste plus qu’à se construire des petites règles sympathiques dans un fichier placé dans /etc/udev/rules.d :
SUBSYSTEMS== »usb », KERNEL== »ttyUSB* », ATTRS{product}== »FT232R USB UART »,
SYSFS{serial}== »A90066j7″, SYMLINK+= »TTYUSB0″
SUBSYSTEMS== »usb », KERNEL== »ttyUSB* », ATTRS{product}== »FT232R USB UART »,
SYSFS{serial}== »A90066ac », SYMLINK+= »TTYUSB1″
SUBSYSTEMS== »usb », KERNEL== »ttyUSB* », ATTRS{product}== »FT232R USB UART »,
SYSFS{serial}== »A900669W », SYMLINK+= »TTYUSB2″
SUBSYSTEMS== »usb », KERNEL== »ttyUSB* », ATTRS{product}== »FT232R USB UART »,
SYSFS{serial}== »A90066ai », SYMLINK+= »TTYUSB3″
On redémarre udev avec un petit /etc/init.d/udev restart et on marque des petits chiffres au feutre indélébile sur les adaptateurs. A la connexion du périphérique identifié par son numéro de série, un lien symbolique est créé dans /dev. Peu importe le /dev/ttyUSB*, le lien symbolique donne toujours accès au bon périphérique.

Done.

PS : ça marche pour plein de périphériques. Ceci inclus les clef USB par exemple :
BUS== »usb », SYSFS{serial}== »123456789ABCDEF », NAME= »%k », SYMLINK= »usbkey1″

Serial luvz ! Couldn't register serial port :(

J’aime le port série (alias l’EIA RS-232C). Le port parallèle disparaît et l’utilisation des convertisseurs USB/lp n’est pas pratique du tout. Reste l’USB qui est encore relativement délicat à mettre en oeuvre et utilisable avec des micocontrôleur encore coûteux (plus qu’un AVR simple). On peut jouer avec les AVR (Attiny2313) et supporter l’USB de manière soft, certes, mais au prix d’une grosse consommation de flash.

Le port série reste donc la meilleure solution pour bidouiller et développer ses propres périphériques. Non seulement les convertisseurs USB/série sont peu cher mais le code pour un AVR est un vrai bonheur. RS232 <3 donc :)

Je me suis payé une sympathique carte PCI 6 ports série chez Think ITX à 38 €. Avec les deux ports présents sur la carte mère cela me donne TTYS0 -> TTYS7. De quoi jouer.  Mais voilà :
[    1.527011] Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled
[    1.527790] ACPI: PCI Interrupt 0000:00:0c.0[A] -> GSI 19 (level, low) -> IRQ 19
[    1.527990] 0000:00:0c.0: ttyS0 at I/O 0xa000 (irq = 19) is a 16550A
[    1.528781] 0000:00:0c.0: ttyS1 at I/O 0xa400 (irq = 19) is a 16550A
[    1.529012] 0000:00:0c.0: ttyS2 at I/O 0xa800 (irq = 19) is a 16550A
[    1.529232] 0000:00:0c.0: ttyS3 at I/O 0xac00 (irq = 19) is a 16550A
[    1.529323] Couldn’t register serial port 0000:00:0c.0: -28
Damn ! J’avais préalablement désactivé les deux ports de la carte mère dans le BIOS. Je devrai donc avoir 6 ports et j’en vois 4 !

Le problème vient du nombre de ports gérés par défaut par le noyau :
% grep SERIAL config-2.6.26-1-686
[…]
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
[…]
Voilà le fameux 4. Vais-je devoir recompiler un noyau ? Non :
config SERIAL_8250_RUNTIME_UARTS
        int « Number of 8250/16550 serial ports to register at runtime »
        depends on SERIAL_8250
        range 0 SERIAL_8250_NR_UARTS
        default « 4 »
        help
          Set this to the maximum number of serial ports you want
          the kernel to register at boot time.  This can be overridden
          with the module parameter « nr_uarts », or boot-time parameter
          8250.nr_uarts
Hop, un petit changement dans les paramètres passés au noyau depuis mon GRUB : 8250.nr_uarts=8. Et c’est trop bonheur :
[    1.536962] 00:07: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    1.537232] 00:08: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
[    1.537628] 0000:00:0c.0: ttyS4 at I/O 0xa000 (irq = 19) is a 16550A
[    1.537854] 0000:00:0c.0: ttyS5 at I/O 0xa400 (irq = 19) is a 16550A
[    1.538077] 0000:00:0c.0: ttyS6 at I/O 0xa800 (irq = 19) is a 16550A
[    1.538299] 0000:00:0c.0: ttyS7 at I/O 0xac00 (irq = 19) is a 16550A
[    1.538516] 0000:00:0c.0: ttyS2 at I/O 0xb000 (irq = 19) is a 16550A
[    1.538733] 0000:00:0c.0: ttyS3 at I/O 0xb400 (irq = 19) is a 16550A
Luvz, je vous, mais luvz quoi :)