int21h

Detekce tiskárny

Toto téma je dost nezvyklé a málokdo takovýto problém řešil. Windowsáci přistupují k tiskárně přes ovladače a DOSaři většinou používají jen ten úplně nejzákladnější znakový výstup typu: copy file.txt prn
Jen ty nejlepší programy toho umějí z tiskárny dostat víc. Používají k tomu vlastní sady ovladačů, které jdou obvykle použít jen pro ten jediný program. Klíčavý bod je k tomu nastavení tiskárny. Uživatel musí spustit interaktivní setup, ve kterém si podobně, jako když se zadává zvuková karta, vybere svůj model tiskárny.
Jenže často se stává, že v seznamu tiskáren právě ta uživatelova tiskárna chybí, sice tam jsou podobné typy, ale zrovna ta jeho ne. A on neví, jestli může zvolit nějakou jinou nebo nemůže.
A tady nám pomůže autodetekce. Autodetekční rutina totiž kromě typu tiskárny ještě vrátí její komunikační jazyk (Postscript, PCL, aj.) a další informace.
Základním předpokladem ovšem je, aby tiskárna byla zapnutá a byla připojena na paralelní port. USB port je v DOSu dostupný jen s krajními obtížemi a takové fígle neumím. Paralelní port i tiskárna dále musí splňovat normu IEEE-1284, což kromě vyložených veteránů splňují. Tato norma definuje pod režimů činnosti paralelního portu: Koho zajímají takovéto detaily, nechť se podívá na pěknou českou stránku o paralelního portech - zde.
Následující kód využívá nibble mód. Jak sami vidíte, nejsem autor :-)

program i1284_info;
uses crt;
{The following code is based on the IEEE-1284 probe code from Linux, which was
written by Phil Blundell, Carsten Gross and Jose Renau.

The Turbo Pascal *implementation* is entirely my own creation.

version 1.1 : bugfix. Timing of signals in 'second check' found to work OK
for HP Laserjet 5L, but not for Canon BJ-210. Re-worked code to be compatable
with both types of printers. I assume this is an anomalie with the Linux
code, since the order of operations was copied from there.}

var q,y,z:byte;
    r:array[0..1023] of char;
    i,s:integer;
    f,quit:boolean;

function wait(mask,result:byte) : boolean;	{ wait 35ms for response }
var x,i:byte;
begin
  i:=1;
  repeat
    x:=port[$379];
    inc(i);
    delay(1);
  until ((x and mask)=result) or (i=40);	{ 40 = small error margin }
  if i<40 then wait:=true else wait:=false;
end;

function read_nibble : byte;			{ read 4 bits of info }
var z:byte;
begin
  z:=(port[$379] shr 3) and $f7;
  if z and $10=0 then z:=z or 8;
  read_nibble:=z and $f;
end;

var ff:text;
begin
  Assign(ff,'');
  Rewrite(ff);
  clrscr;
  writeln(ff,'IEEE-1284 Parallel port device scan.');
  writeln(ff);

  port[$378]:=4;				{ request info command }
  delay(5);
  port[$37a]:=port[$37a] and $f7;		{ sel in low }
  port[$37a]:=port[$37a] or 2;			{ autofeed high }
  if wait($78,$38) then
  begin
    writeln(ff,'Passed initial check. An IEEE-1284 device is present.');

    port[$37a]:=port[$37a] or 1;		{ strobe high }
    port[$37a]:=port[$37a] and $fd;		{ autofeed low }
    delay(5);
    port[$37a]:=port[$37a] and $fe;		{ stobe low }
    delay(5);
    if wait($20,0) then
    begin
      writeln(ff,'Passed second check. Device ID is readable.');
      f:=false;
      quit:=false;
      s:=0;					{ s=index into array r() }
      delay(10);
      repeat
        port[$37a]:=port[$37a] or $2;		{ autofeed high }
        if not wait($40,0) then
        begin
          writeln(ff,'Read1 timeout!');
          port[$37a]:=port[$37a] and $fd;	{ autofeed low }
          quit:=true;
        end;
        y:=read_nibble;				{ get 4 bits }
        port[$37a]:=port[$37a] and $fd;		{ autofeed low }
        if not wait($40,$40) then
        begin
          writeln(ff,'Read2 timeout!');
          quit:=true;
        end;
        if f then				{ f signals when a byte is }
        begin					{ ready - each 2 passes }
          f:=not f;
          q:=q + y shl 4;
          r[s]:=chr(q);
          inc(s);
          if port[$379] and 8=8 then quit:=true; { eof? }
        end else
        begin
	  f:=not f;
	  q:=y;
        end;
        if s>1023 then quit:=true;		{ out of table space ? }
      until quit;
      port[$37a]:=(port[$37a] and $fd) or 8;	{ terminate read }
      if wait($80,0) then writeln(ff,'ID Read terminated OK')
        else writeln(ff,'ID Read terminated with error!');

{ Display Result, nicely formatted }

      writeln(ff);
      writeln(ff,'Size our count : ',s);
      writeln(ff,'Size returned  : ',integer(ord(r[0]) shl 8+ord(r[1])));
      write(ff,'Info returned  : ');
      for i:=2 to s do
      begin
        if r[i]=';' then
	begin
	  writeln(ff);
          write(ff,'                 ');
        end else write(ff,r[i]);
      end;
      writeln(ff);
      writeln(ff);
    end else writeln(ff,'Failed second check. No device ID Readable.');
  end else
  begin
    writeln(ff,'Failed initial check. No IEEE-1284 device detected.');
     port[$37a]:=((port[$37a] and $fd) or 8);	{ reset port }
  end;
Close(ff);
end.
Tento prográmek nemusí sloužit jen k detekci tiskáren, ale k libovolnému zařízení připojenému na paralelní port.
Nicméně já ho používám pro tiskárnu a moje tiskárna vrací toto:
IEEE-1284 Parallel port device scan.

Passed initial check. An IEEE-1284 device is present.
Passed second check. Device ID is readable.
ID Read terminated OK

Size our count      MFG:HEWLETT-PACKARD
Size returned       MDL:DESKJET 640C
Info returned       CMD:MLC,PCL,PML
                    CLASS:PRINTER
                    DESCRIPTION:Hewlett-Packard DeskJet 640C
                    VSTATUS:$Cb0$Rc0,ff,DN,IDLE
MFG - je zřejmě Manufacter - tedy výrobce
MDL - model
CMD - říká, jakým komunikačním protokolům zařízení rozumí. Mezi druhými dvěma vidíme PCL - komunikační jazyk společný pro všechny tiskárny od Hewlett-Packard
CLASS - co je to zač - v našem případě tiskárna
DESCRIPTION - oficiální plný název
VSTATUS - jakýsi status, patrně se liší zařízení od zařízení

Vidíte, že tiskárna sama nám dá dostatek informací, abychom věděli, jak k ní přistupovat i bez interaktivního setupu.

DOS-u-akbar!
2007-06-13 | Laaca
Reklamy:
„Láska vdaných žen je nejcennější na světě, manželé o tom ovšem nevědí.“ Oscar Wilde