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…

Connexion n810 sur Asterisk over OpenVPN

Le tabletPC n810 de Nokia est un super jouet. La première chose installée est un client OpenVPN pour pouvoir se connecter à ses ressources en toute sécurité (relative) depuis n’importe où. Parmi ses ressources il y a un serveur Asterisk. Le n810 intègre, en effet, un client VoIP. De quoi s’amuser, téléphoner via un forfait depuis n’importe quel endroit et surtout recevoir des appels comme si on était chez soi.

Seulement voilà : çapamarche ! Impossible de s’enregistrer sur le serveur Asterisk pourtant  à l’autre bout du VPN. Après quelques recherche, il s’avère que le problème ne vient pas d’Asterisk et encore moins d’OpenVPN mais bien de la configuration sur le n810. Le bestiaux n’utilise pas l’adresse local VPN par défaut, il faut le lui préciser explicitement.

On ouvre donc un terminal (j’adore des périphériques mobiles avec un terminal), on passe en root avec root et on utilise :
mc-account set sip0 string:local-ip-address=ADRESSE_LOCALE_DU_VPN
Magie, le client sip/VoIP se connecte et tout roule.

Il est possible d’automatiser la configuration mais j’étais trop impatient pour configurer cela avant de poster. Explications sur : http://talk.maemo.org/archive/index.php/t-20921.html

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

MOD vers MP3, la scène Amiga représente grave !

Coup de nostalgie ! Bien avant MP3, bien avant GNU/Linux… il y avait des machines de rêve comme l’Amiga, le ST… et pour mal part le C64 (mais rien à voir). En ce temps là, il y avait un format : le MOD.

Pour faire revenir les sons du passé dans le présent, sur mon iPod Nano, il me fallait convertir ces MODs en MP3. Après 5mn de recherches infructueuses, j’ai décider d’utiliser la méthode bouts-de-ficelles :
#!/bin/bash
MIKMOD=/usr/bin/mikmod
LAME=/usr/bin/toolame
SOX=/usr/bin/sox
ID3V2=/usr/bin/id3v2
HEAD=/usr/bin/head

SONGNAME=`basename $1 .mod`

$MIKMOD  -p 0 $1
mv music.raw $SONGNAME.raw

$SOX -r 44100 -c 2 -w -s $SONGNAME.raw $SONGNAME.wav
rm $SONGNAME.raw

$LAME $SONGNAME.wav $SONGNAME.mp3
rm $SONGNAME.wav

$ID3V2 -t « `$HEAD -c 20 $1` » -A « MODFILES » -a « MODlovers » $SONGNAME.mp3
mikmod, par défaut produit un fichier RAW, stéréo, 16bits, 44100Hz. Sur la base de ces informations, on peut utiliser sox pour en faire un WAV qui sera, ensuite compresser en MP3 avec toolame.

Enfin, le format MOD permet d’inclure un titre au morceau sous la forme des 20 premiers octets du fichier (avec un padding avec des espaces). On peut donc utiliser head pour récupérer ces infos et en faire le tag « titre » ID3v2 du MP3 avec id3v2.

Embarquer une image dans HTML

Bon, clairement, je ne sais pas trop à quoi cela pourrait servir mais c’est possible. Donc, bon.

En faisant quelques recherche avec Google, j’ai remarqué que l’indicateur de popularité du site (à gauche de l’URL en vert) dans les résultats de recherches n’était pas un fichier PNG mais des données PNG embarquées directement dans le HTML. En creusant un peu, voici…

On fait un petit script PHP pour simplifier les choses :
#!/usr/bin/php
<?php
while($line=fgets(STDIN)){
  echo (rawurlencode($line));
}
?>
Puis on utiliser tout simplement cat pour dumper les données et les envoyer sur STDIN du script et rediriger le tout dans un fichier :
% cat ~/deblogo.png | ./rawurlencode > /tmp/index.html
On ajoute ensuite les balises HTML qui vont bien :
<html>
<body>
<img src= »data:image/png,%89PNG%0D%0A%1A[…]%AEB%60%82″ width= »48″ height= »48″>
</body>
</html>
Et voilà ! Ça peut toujours servir pour une interface HTML d’un système embarqué…

Ah oui ! Il est aussi possible d’encoder en base64, ce qui évite d’utiliser PHP :
% base64 -w 0 ~/deblogo.png > index.html
La syntaxe du tag précise alors l’encodage en question :
<img src= »data:image/png;base64,iVBORw0KGgoAA[…]FTkSuQmC » width= »48″ height= »48″>

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…

Programmeur ISP USB pour AVR

Les programmeurs de type dapa sont économiques, efficaces et très simples. Mais ils dépendent d’un port clairement en voie de disparition sur les machines modernes : le port parallèle. Peu d’adaptateurs USB/parallèle existent, il s’agit en forte majorité d’USB/printer (lp) avec lesquels il n’est pas possible de contrôler les lignes DATA, CONTROL et STATUS individuellement.

On peut alors se tourner vers le dasa, adaptateur pour port série utilisant du bit banging mais, là encore, on rencontre des problèmes puisque tous les pilotes ne supportent pas la palette d’ioctl nécessaires.

Finalement, pour pouvoir développer et programmer un Atmel AVR via USB (sur un lappy par exemple), il ne reste pas d’autre choix simple que d’investir quelques euros (moins de 30 euros avec le port sur eBay)  dans un programmeur USB compatible STK500v2 (chercher « USB ISP-Programmer »).

(Le miens est vert fluo et livré avec un câble également vert, très bon produit, joli design, super propre)

La chose est reconnu comme ttyACM0: USB ACM device par Linux et on en profite pour ajouter une règle udev :
SUBSYSTEMS== »usb », KERNEL== »ttyACM* », ATTRS{product}== »DX-ISP », SYMLINK+= »STK500″
Ainsi, le périphérique est accessible systématiquement via /dev/STK500. On flash un AVR avec avrdude ainsi :
% avrdude -p t13 -c stk500v2 -P /dev/STK500 -i 5 -U flash:w:main.hex
A moi le développement AVR dans le TER. Luvz !

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″