Retrouvez cet article dans : Linux Magazine Hors série 27
Ce n'est pas un scoop, les ports d'E/S faciles d'accès sont en voie de disparition. Le port série n'est presque plus présent sur les nouvelles configurations et le port parallèle ne devrait pas tarder à suivre le même destin. L'USB s'est donc définitivement installé comme port à tout faire par défaut.
Il y a bien longtemps (à l'échelle de l'évolution des technologies), les ordinateurs de type PC disposaient d'un bus très facile d'accès permettant toutes sortes de bidouilles : le bus ISA. L'arrivée en masse du PCI a non seulement éliminé l'ISA, mais a également marqué la fin de l'accès aisé direct au matériel. Le développement de cartes prototypes PCI " faites maison " est une activité coûteuse et pénible. Restait alors le port série permettant de dialoguer avec tout montage externe, mais celui-ci est maintenant en voie d'extinction. Certes, il est toujours possible d'utiliser une carte PCI série, mais il faut se rendre à l'évidence : l'USB remplace globalement toutes les autres interfaces d'E/S petit à petit. Le port parallèle, précédemment traité dans le hors-série 23, est encore présent sur les machines PC actuelles, mais ce n'est qu'une question de temps. De plus, les architectures non-PC comme les Mac ou d'autres plateformes n'ont jamais disposé d'interfaces compatibles IEEE 1284 (port parallèle). Il faut donc se tourner vers le seul port disponible et présent sur toutes les plateformes matérielles : l'USB. Malheureusement, bien que plus accessible que le bus PCI, l'USB n'est pas simple à mettre en œuvre. La solution pour obtenir un jeu d'E/S via USB est alors d'utiliser les modules dédiés comme ceux utilisant les puces FTDI disposant de pilotes pour Linux. Ces composants ou modules coûtent entre 20 et 40 euros et peuvent être utilisés directement via le support du noyau ou en utilisant la libUSB. Il existe cependant une solution à la fois plus économique et plus simple à mettre en œuvre. Pour peu que l'on contourne un certain problème.
Adaptateur USB/parallèle : le problème
La gestion des ports parallèles sous Linux se compose en plusieurs éléments ou couches. Nous avons tout d'abord le pilote chargé de dialoguer directement avec le matériel. Sur PC, il s'agit du support parport_pc. Reposant sur cette couche, se place ensuite le support parport permettant l'interfaçage avec une API unique pour l'accès au port. Une troisième couche, ppdev, permet un accès au port depuis l'espace utilisateur en utilisant directement une entrée /dev/parport[0-9].
En jetant un œil aux sources du noyau, on constate qu'il existe plusieurs supports de bas niveau pour les ports parallèles (parport_cs, parport_sunbpp ou encore parport_amiga), mais pas de parport_usb. Côté support USB, nous trouvons usblp et un mystérieux uss720.
usblp n'offre pas de support parport contrairement à uss720 qui, pourtant, est bien un pilote pour convertisseur USB/parallèle de fabrication Lucent ou Belkin. Pourquoi ? Le pilote uss720 concerne un matériel bien précis utilisant la puce du même nom. Il a été développé et est maintenu par Thomas Sailer. C'est le seul pilote vous permettant d'obtenir un /dev/parport[0-9] et ainsi de bénéficier du support ppdev. Lors du chargement sous la forme d'un module, un avertissement vous signale que, pour une utilisation avec une imprimante, il est fortement recommandé d'utiliser usblp plutôt que ce module.
Les adaptateurs USB/parallèle sont en réalité mal nommés. On devrait, en effet, plutôt parler d'adaptateur ou de ponts USB vers imprimante. Les circuits logiques spécialisés utilisés pour ces adaptateurs sont, en effet, destinés à fonctionner avec des imprimantes et non à offrir un accès aux lignes du port parallèle. Ils intègrent ainsi un certain nombre d'opérations spécifiques à la communication avec une imprimante.
usblp n'est pas un pilote pour un ou plusieurs périphériques USB précis, mais pour une classe de périphériques. Le système de classes permet de regrouper les constructeurs de périphériques USB autour de spécifications communes. Une interface unique permet ainsi de faciliter la mise en œuvre du matériel. C'est pour cette raison que n'importe quel adaptateur USB/imprimante se déclarant comme faisant partie de la classe USB Printer fonctionnera sous Linux. Il en va de même pour d'autres périphériques comme les claviers et les souris répondant aux spécifications de la classe HID ou encore les disques USB supportés par usb-storage.
En toute logique, si vous voulez jouer avec les signaux du port parallèle d'un adaptateur USB, soit vous avez la chance d'avoir l'un des périphériques intégrant une puce uss720, soit vous devez développer votre propre support noyau pour le périphérique en question. Il n'existe aucune volonté parmi les développeurs noyau d'écrire des dizaines de pilotes pour utiliser une architecture parport. C'est bien compréhensible lorsqu'on sait que la quasi-totalité des utilisateurs font un usage " normal " de ce type de périphériques.
parport!=lp
Qu'est-ce qui différencie donc un /dev/parport[0-9] d'un /dev/lp[0-9] ? La réponse tient en quelques mots : le niveau d'abstraction vis-à -vis du matériel. lp signifie " Line Printer ". L'entrée dans /dev est un point d'accès vers une imprimante. En accédant à une entrée parport, vous contrôlez l'état des lignes en entrée et en sortie. Avec lp, vous envoyez simplement des données à une imprimante, le noyau prend en charge le protocole de communication. C'est ce qui vous permet de faire cat fichier.ps > /dev/lp0 par exemple. Si cela ne fonctionne pas (plus de papier, imprimante offline, etc.), le support noyau se charge de gérer les erreurs et de retourner, au besoin, un message à l'utilisateur.
Le protocole de communication vers une imprimante n'est pas quelque chose de strictement défini. Il en va de même avec les lignes du port lui-même. La succession de standards ayant pour origine l'IBM PC puis l'AT a fait qu'une partie des spécifications ont évolué et se sont déclinées plus ou moins précisément en fonction des fabricants. Il n'en reste pas moins que, dans les grandes lignes, un véritable standard a vu le jour sous le nom d'IEEE 1284.

Fig -1 Chronogramme d'une communication entre un PC et une imprimante
- La figure 1 montre un dialogue simplifié entre un ordinateur et une imprimante ainsi que l'utilisation des différentes lignes de l'interface :
- Préparation des données et configuration des lignes D0 à D7.
- L'ordinateur passe /STROBE à l'état bas pendant 1.5usec (+/- 500nsec), signalant la disponibilité des données à traiter.
- Le périphérique alerté par le changement d'état de /STROBE se signale occupé en passant BUSY à l'état haut. Dès lors, l'ordinateur sait qu'il ne doit plus envoyer de données.
- Après traitement des données, le périphérique signale la fin du traitement en passant ACK à l'état bas. Il accuse réception des informations transmises.
- Le périphérique se déclare libre pour le traitement des prochaines données et repasse BUSY à l'état bas.
- Les données présentées par l'ordinateur sont maintenant invalides (obsolètes) et le processus peut reprendre pour les données suivantes.
Adaptateur USB/imprimante : la solution
- Pour rendre la pseudo-imprimante disponible, nous ramenons le signal PAPEREND/PAPEROU/OUTPA, broche 12 du connecteur Centronic (36 broches) à la masse. Nous avons toujours du papier. Nous faisons de même avec la broche 11 correspondant au signal BUSY. Le périphérique n'est donc jamais occupé, ce qui est une violation évidente du protocole.
- L'adaptateur nous présente les données sur les lignes D0 à D7 (broches 2 à 9).
- Une fois ces lignes de données stables, l'adaptateur passe brièvement le signal /STROBE (broche 1) à l'état bas (masse). Il nous signale la disponibilité des données.
- Nous utiliserons directement le signal /STROBE (qui est inversé) pour accuser réception des données en le connectant à l'entrée /ACK (qui est aussi inversée).
- Le signal /STROBE nous permettra également de stocker les données transmises dans un latch, un composant relativement simple, sorte d'interrupteur logique stockant les informations qu'il reçoit.
- Une fois le signal ACK reçu, l'adaptateur USB/imprimante repasse toutes les lignes de données à l'état bas ou, éventuellement, présente les données suivantes.

Fig-2 L'émulateur d'imprimante
La figure 2 montre le schéma de notre montage. Les résistances utilisées pour piloter les LED sont des 470 ohms, mais selon les LED en question (bleues par exemple), leur valeur peut varier. N'oubliez pas LA formule de base : U=R*I. Coté réalisation, la partie délicate concerne principalement le connecteur Centronic 36 broches. La figure 3 présente un connecteur femelle récupéré sur une vielle imprimante hors d'usage, mais il est parfaitement possible d'en commander chez un détaillant de composants électroniques pour moins de 3 euros.
Fig-3 Brochage du connecteur Centronic
Pour ce qui concerne les brochages à proprement parler, nous ne rencontrons pas de difficulté. Les signaux qui nous intéressent sont tous côte à côte en partant de la broche 1 : /STROBE, D0 à D7, /ACK, BUSY et PAPEROUT. Il faut simplement de petits doigts et de la patience pour les soudures.
Logiciel
Une fois le montage réalisé sur platine (figure 4) avec une alimentation directement tirée sur bus USB, nous pouvons expérimenter. Le premier test sera des plus simples. Après chargement si nécessaire du module usblp, nous envoyons des données aléatoires sur /dev/usb/lp0 :
 $ cat /dev/urandom > /dev/usb/lp0
Vous devriez alors voir s'affoler les LED connectées au latch au rythme des données reçues. Ceci montre non seulement que le montage fonctionne malgré les libertés prises avec le protocole, mais également la simplicité d'accès en sortie. Il suffit, en effet, d'envoyer un ou plusieurs caractères dans /dev/usb/lp0 pour contrôler les LED. Cette simplicité offre un large choix quant aux langages qu'il est alors possible d'utiliser.

Fig-4 L'émulateur sur platine à essai
 Même en C, les opérations se limitent à une simple écriture dans le pseudo-fichier :
int fd;
char tab[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
fd = open("/dev/usb/lp0",O_WRONLY, 0);
if (pp < 0) {
fprintf(stderr,"Open Error : %s (%d)\n",
strerror(errno),errno);
exit(EXIT_FAILURE);
} else {
printf("Open\n");
}
if(write( fd, &tab, 8 ) != 8){
fprintf(stderr,"Write Error : %s (%d)\n",
strerror(errno),errno);
exit(EXIT_FAILURE);
}
close(fd);
 Ce code écrit tout simplement les 8 caractères stockés dans tab[] dans /dev/usb/lp0. Bien entendu, le traitement par le montage est si rapide que seule est visible la dernière valeur sous la forme de l'allumage de la LED sur D7. Pour voir quelque chose, vous devrez écrire caractère par caractère en incrémentant le pointeur sur tab[] (avec un usleep si besoin).
Notons qu'un certain nombre d'ioctl sont normalement disponibles pour manipuler un /dev/lp[0-9]. Malheureusement, la plupart ne sont pas utilisables avec un adaptateur USB/imprimante, car le périphérique n'offre pas assez de finesse en termes de contrôle des lignes. Seule une ou deux lignes en entrée sont facilement utilisables, dont PAPEROUT. Pour lire l'état de la ligne, il suffit d'utiliser LPGETSTATUS :
char ibuf;
if(ioctl( fd, LPGETSTATUS, &ibuf ) < 0){
fprintf(stderr,"LPGETSTATUS Error : %s (%d)\n",
strerror(errno),errno);
exit(EXIT_FAILURE);
} else {
printf(":Status %X\n", ibuf);
if(ibuf & LP_POUTPA) {
printf(":LP_POUTPA\n");
}
}
Il faudra inclure le fichier linux/lp.h (oui, utiliser les en-têtes du noyau c'est mal, mais on est plus à ça près). L'utilisation du signal PAPEROUT n'est pas bloquant. L'imprimante peut, en effet, signaler l'absence de papier tout en continuant à traiter les données et remplir un buffer interne. Lorsque le buffer est plein, l'imprimante utilise le signale BUSY. Nous disposons ainsi de 8 sorties et deux entrées librement utilisables pour tout type d'applications (SLCT est la seconde).
Améliorations
Un certain nombre de choses peuvent être améliorées par rapport au simple montage présenté ici. Tout d'abord, on peut respecter un peu plus le protocole de communication en ajoutant un délai entre le signal STROBE qui active le latch et l'émission du signal /ACK. La simple connexion de /STROBE et /ACK est cavalière et peut entraîner des problèmes en pilotant le port à haute vitesse. Vous pouvez très simplement en faire l'essai en envoyant des données au montage à l'aide de cat. Déconnectez ensuite la ligne /ACK du 74LS04. Non seulement l'écriture sur l'entrée dans /dev/usb est bloquée, mais vous ne pouvez pas la relancer en interrompant le processus avec ^C et en relançant l'envoi. Le périphérique USB est toujours en attente de l'accusé réception des dernières données. Seule solution, connecter par intermittence la ligne /ACK à la masse pour en changer plusieurs fois son état. On dépile ainsi les données en attente. Là , nous sommes dans le " bricolo " dans toute sa grandeur et le système le signal clairement : usblp0: on fire, write error: Appel système interrompu.
Une meilleure solution consisterait donc à utiliser un microcontrôleur en lieu et place des deux circuits logiques de manière à véritablement contrôler le flux de données et utiliser le signal /ACK judicieusement.
La déconnexion de la ligne BUSY est moins catastrophique. En effet, du fait de sa fonction, BUSY nous permet de mettre en attente le flux des données. Déconnectez BUSY, patientez, reconnectez... les opérations suivent leur court.
Conclusion
Les informations données dans cet article ont été testées avec deux adaptateurs USB différents. Le premier, acheté chez un détaillant, est un produit d'entrée de gamme sans marque. Celui-ci est identifié par Linux sous la désignation 067b:2305 Prolific Technology, Inc. PL2305 Parallel Port. Le second est un modèle un peu plus ancien, détecté comme 047e:1001 Agere Systems, Inc. (Lucent) USS720 Parallel Port. Comme vous pouvez le voir, il intègre la puce USS720, mais a néanmoins été utilisé ici avec le module usblp.
Le comportement des deux adaptateurs est différent. Le Prolific Technology semble plus lent et ne renvoie pas les mêmes informations que l'adaptateur Agere Systems. En effet, la lecture de l'état avec LPGETSTATUS sur le premier retourne simplement LP_PSELECD, alors que le second retourne en plus LP_OFFL signifiant que l'imprimante serait Offline. Il apparaît cependant que cela ne gêne en rien le fonctionnement du montage, puisque le cat /dev/urandom redirigé vers l'entrée /dev/usb correspondante fonctionne parfaitement.
Il semble donc que les constructeurs prennent quelques libertés qui ne dérangent pas le support usblp. Mais je ne saurais garantir que ce hack fonctionnera avec tous les adaptateurs existants. Si vous rencontrez des problèmes, assurez-vous que le montage est correct et essayez, si possible, avec un autre modèle. J'ai également remarqué que toutes les broches du port Centronic référencées comme étant des masses ne le sont pas toujours. Le multimètre est votre ami.
Enfin, dernière recommandation. En cas de comportement étrange, connectez éventuellement la broche 31 (/INIT) aux entrées 13 (SLCT) et 32 (/ERROR). Avec la mise à la masse de BUSY et PAPEROUT ainsi que la connexion /STROBE sur /ACK cela constitue un " Null Parallel Adapter " permettant à certains vieux logiciels MS/DOS de tester le port parallèle.
Retrouvez cet article dans : Linux Magazine Hors série 27





Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.