diff --git a/backend/hpsj5s.c b/backend/hpsj5s.c index 63037a282..f994221bb 100644 --- a/backend/hpsj5s.c +++ b/backend/hpsj5s.c @@ -38,7 +38,7 @@ whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ -#define BUILD 2 +#define BUILD 3 #define BACKEND_NAME hpsj5s #define HPSJ5S_CONFIG_FILE "hpsj5s.conf" @@ -57,13 +57,12 @@ #include #include #include -#include #define LINES_TO_FEED 480 /*Default feed length */ static int scanner_d = -1; /*This is handler to the only-supported. Will be fixed. */ -static char scanner_path[PATH_MAX] = "/dev/hpsj5s"; /*String for device-file */ +static char scanner_path[PATH_MAX] = "parport0"; /*String for device-file */ static SANE_Byte bLastCalibration; /*Here we store calibration result */ static SANE_Byte bCalibration; /*Here we store new calibration value */ static SANE_Byte bHardwareState; /*Here we store copy of hardware flags register */ @@ -156,6 +155,8 @@ LengthForRes (SANE_Word Resolution, SANE_Word Length) } } +static struct parport_list pl; /*List of detected parallel ports. */ + SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { @@ -209,6 +210,9 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) sod[1].constraint.range = &ImageWidthRange; /*Width option */ sod[2].constraint.word_list = &ImageResolutionsList[0]; /*Resolution option */ + /*Search for ports in system: */ + ieee1284_find_ports (&pl, 0); + return SANE_STATUS_GOOD; } @@ -217,9 +221,13 @@ sane_exit (void) { if (scanner_d != -1) { - close (scanner_d); + CloseScanner (scanner_d); scanner_d = -1; } + + /*Free alocated ports information: */ + ieee1284_free_ports (&pl); + DBG (2, "sane_exit\n"); return; } @@ -253,13 +261,15 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) }; /*Device was not opened. */ - scanner_d = open (scanner_path, O_RDWR); + scanner_d = OpenScanner (scanner_path); if (scanner_d == -1) /*No devices present */ { + DBG (1, "failed to open scanner.\n"); *device_list = void_devlist; return SANE_STATUS_GOOD; } + DBG (1, "port opened.\n"); /*Check device. */ DBG (1, "sane_get_devices: check scanner started."); @@ -276,7 +286,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) } /*We do not need it any more */ - close (scanner_d); + CloseScanner (scanner_d); scanner_d = -1; return SANE_STATUS_GOOD; @@ -309,7 +319,8 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) return SANE_STATUS_DEVICE_BUSY; DBG (1, "sane_open: scanner device path name is \'%s\'\n", scanner_path); - scanner_d = open (scanner_path, O_RDWR); + + scanner_d = OpenScanner (scanner_path); if (scanner_d == -1) return SANE_STATUS_DEVICE_BUSY; /*This should be done more carefully */ @@ -318,7 +329,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) if (DetectScanner () == 0) { /*Device malfunction! */ DBG (1, "sane_open: Device malfunction."); - close (scanner_d); + CloseScanner (scanner_d); scanner_d = -1; return SANE_STATUS_IO_ERROR; } @@ -332,11 +343,11 @@ void sane_close (SANE_Handle handle) { DBG (2, "sane_close\n"); - /*We support only single device - so ignore handle (FIX IT LATTER) */ + /*We support only single device - so ignore handle (FIX IT LATER) */ if ((handle != (SANE_Handle) scanner_d) || (scanner_d == -1)) return; /* wrong device */ StandByScanner (); - close (scanner_d); + CloseScanner (scanner_d); scanner_d = -1; } @@ -614,7 +625,9 @@ DetectScanner (void) Result2 = InputCheck (); if (!(Result1 || Result2)) /*If all are 0 - it's error */ - return 0; + { + return 0; + } WriteScannerRegister (0x7C, 0x80); WriteScannerRegister (0x7F, 0x1); @@ -1187,8 +1200,8 @@ OutputCheck () WriteAddress (0x3F); if (ReadDataByte () & 0x80) return 0; - else - return 1; + + return 1; } static int @@ -1199,13 +1212,16 @@ InputCheck () WriteAddress (0x3E); for (i = 0; i < 256; i++) - Buffer[i] = ReadDataByte (); + { + Buffer[i] = ReadDataByte (); + } for (i = 0; i < 256; i++) { if (Buffer[i] != i) return 0; } + return 1; } @@ -1235,9 +1251,10 @@ CallCheck () ReadDataBlock (Buffer, 256); for (i = 0; i < 255; i++) - if (Buffer[i + 1] != (SANE_Byte) i) - return 0; - + { + if (Buffer[i + 1] != (SANE_Byte) i) + return 0; + } return 1; } @@ -1269,39 +1286,31 @@ LoadingPaletteToScanner () static void WriteAddress (SANE_Byte Address) { - strOperationBlock OpBlock; - OpBlock.Code = OP_WRITE_ADDRESS; - OpBlock.Parameters.WrAddr.Address = Address; - write (scanner_d, &OpBlock, sizeof (OpBlock)); + ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */ + ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); + ieee1284_epp_write_addr (pl.portv[scanner_d], 0, (char *) &Address, 1); } static void WriteData (SANE_Byte Data) { - strOperationBlock OpBlock; - OpBlock.Code = OP_WRITE_DATA_BYTE; - OpBlock.Parameters.WrData.Data = Data; - write (scanner_d, &OpBlock, sizeof (OpBlock)); + ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */ + ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); + ieee1284_epp_write_data (pl.portv[scanner_d], 0, (char *) &Data, 1); } static void WriteScannerRegister (SANE_Byte Address, SANE_Byte Data) { - strOperationBlock OpBlock; - OpBlock.Code = OP_WRITE_SCANER_REGISTER; - OpBlock.Parameters.WrScannerReg.Address = Address; - OpBlock.Parameters.WrScannerReg.Data = Data; - write (scanner_d, &OpBlock, sizeof (OpBlock)); + WriteAddress (Address); + WriteData (Data); } static void CallFunctionWithParameter (SANE_Byte Function, SANE_Byte Parameter) { - strOperationBlock OpBlock; - OpBlock.Code = OP_CALL_FUNCTION_WITH_PARAMETER; - OpBlock.Parameters.FuncParam.Function = Function; - OpBlock.Parameters.FuncParam.Parameter = Parameter; - write (scanner_d, &OpBlock, sizeof (OpBlock)); + WriteScannerRegister (REGISTER_FUNCTION_CODE, Function); + WriteScannerRegister (REGISTER_FUNCTION_PARAMETER, Parameter); } static SANE_Byte @@ -1316,12 +1325,161 @@ static SANE_Byte ReadDataByte () { SANE_Byte Result; - read (scanner_d, &Result, 1); + + ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */ + ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); + ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) &Result, 1); return Result; } static void -ReadDataBlock (SANE_Byte * Buffer, int lenght) +ReadDataBlock (SANE_Byte * Buffer, int length) { - read (scanner_d, Buffer, lenght); + + ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */ + ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); + ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) Buffer, length); +} + +/* Send a daisy-chain-style CPP command packet. */ +int +cpp_daisy (struct parport *port, int cmd) +{ + unsigned char s; + + ieee1284_data_dir (port, 0); /*forward direction */ + ieee1284_write_control (port, C1284_NINIT); + ieee1284_write_data (port, 0xaa); + usleep (2); + ieee1284_write_data (port, 0x55); + usleep (2); + ieee1284_write_data (port, 0x00); + usleep (2); + ieee1284_write_data (port, 0xff); + usleep (2); + s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Converted for PC-style */ + + s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT); + + if (s != (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT)) + { + DBG (1, "%s: cpp_daisy: aa5500ff(%02x)\n", port->name, s); + return -1; + } + + ieee1284_write_data (port, 0x87); + usleep (2); + s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Convert to PC-style */ + + s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT); + + if (s != (S1284_SELECT | S1284_NFAULT)) + { + DBG (1, "%s: cpp_daisy: aa5500ff87(%02x)\n", port->name, s); + return -1; + } + + ieee1284_write_data (port, 0x78); + usleep (2); + ieee1284_write_control (port, C1284_NINIT); + ieee1284_write_data (port, cmd); + usleep (2); + ieee1284_frob_control (port, C1284_NSTROBE, C1284_NSTROBE); + usleep (1); + ieee1284_frob_control (port, C1284_NSTROBE, 0); + usleep (1); + s = ieee1284_read_status (port); + ieee1284_write_data (port, 0xff); + usleep (2); + + return s; +} + +/*Daisy chain deselect operation.*/ +void +daisy_deselect_all (struct parport *port) +{ + cpp_daisy (port, 0x30); +} + +/*Daisy chain select operation*/ +int +daisy_select (struct parport *port, int daisy, int mode) +{ + switch (mode) + { + /*For these modes we should switch to EPP mode: */ + case M1284_EPP: + case M1284_EPPSL: + case M1284_EPPSWE: + return cpp_daisy (port, 0x20 + daisy) & S1284_NFAULT; + /*For these modes we should switch to ECP mode: */ + case M1284_ECP: + case M1284_ECPRLE: + case M1284_ECPSWE: + return cpp_daisy (port, 0xd0 + daisy) & S1284_NFAULT; + /*Nothing was told for BECP in Daisy chain specification. + May be it's wise to use ECP? */ + case M1284_BECP: + /*Others use compat mode */ + case M1284_NIBBLE: + case M1284_BYTE: + case M1284_COMPAT: + default: + return cpp_daisy (port, 0xe0 + daisy) & S1284_NFAULT; + } +} + +/*Daisy chain assign address operation.*/ +int +assign_addr (struct parport *port, int daisy) +{ + return cpp_daisy (port, daisy); +} + +static int +OpenScanner (const char *scanner_path) +{ + int handle; + int caps; + + for (handle = 0; handle < pl.portc; handle++) + { + if (strcmp (scanner_path, pl.portv[handle]->name) == 0) + break; + } + if (handle == pl.portc) /*No match found */ + return -1; + + /*Open port */ + if (ieee1284_open (pl.portv[handle], 0, &caps) != E1284_OK) + return -1; + + /*Claim port */ + if (ieee1284_claim (pl.portv[handle]) != E1284_OK) + return -1; + + /*Total chain reset. */ + daisy_deselect_all (pl.portv[handle]); + + /*Assign addresses. */ + assign_addr (pl.portv[handle], 0); /*Assume we have device first in chain. */ + + /*Select required device. For now - first in chain. */ + daisy_select (pl.portv[handle], 0, M1284_EPP); + + return handle; +} + +static void +CloseScanner (int handle) +{ + if (handle == -1) + return; + + daisy_deselect_all (pl.portv[handle]); + + ieee1284_release (pl.portv[handle]); + + ieee1284_close (pl.portv[handle]); } diff --git a/backend/hpsj5s.conf b/backend/hpsj5s.conf index 21ddeba81..51645f5ea 100644 --- a/backend/hpsj5s.conf +++ b/backend/hpsj5s.conf @@ -1,2 +1,2 @@ #hpsj5s.conf -/dev/hpsj5s \ No newline at end of file +parport0 \ No newline at end of file diff --git a/backend/hpsj5s.h b/backend/hpsj5s.h index 97269bc46..0361acdb2 100644 --- a/backend/hpsj5s.h +++ b/backend/hpsj5s.h @@ -2,7 +2,25 @@ #define __HPSJ5S_MIDDLE_LEVEL_API_HEADER__ -#include "hpsj5s_int.h" +#include + +/*Scanner hardware registers*/ +#define REGISTER_FUNCTION_CODE 0x70 /*Here goes function code */ +#define REGISTER_FUNCTION_PARAMETER 0x60 /*Here goes function param */ + +#define ADDRESS_RESULT 0x20 /*Here we get result */ + +/*Scanner functions (not all - some of them I cann't identify)*/ +#define FUNCTION_SETUP_HARDWARE 0xA0 + +/*Scanner hardware control flags:*/ +/*Set this flag and non-zero speed to start rotation*/ +#define FLAGS_HW_MOTOR_READY 0x1 +/*Set this flag to turn on lamp*/ +#define FLAGS_HW_LAMP_ON 0x2 +/*Set this flag to turn indicator lamp off*/ +#define FLAGS_HW_INDICATOR_OFF 0x4 + /* Types: @@ -14,6 +32,10 @@ enumColorDepth; /*Middle-level API:*/ +static int OpenScanner (const char *scanner_path); + +static void CloseScanner (int handle); + static int DetectScanner (void); static void StandByScanner (void); @@ -63,4 +85,18 @@ static SANE_Byte ReadDataByte (void); static void ReadDataBlock (SANE_Byte * Buffer, int lenght); +/*Daisy chaining API: (should be moved to ieee1284 library in future)*/ + +/*Deselect all devices in chain on this port.*/ +static void daisy_deselect_all (struct parport *port); + +/*Select device with number 'daisy' in 'mode'.*/ +static int daisy_select (struct parport *port, int daisy, int mode); + +/*Setup address for device in chain on this port*/ +static int assign_addr (struct parport *port, int daisy); + +/* Send a daisy-chain-style CPP command packet. */ +static int cpp_daisy (struct parport *port, int cmd); + #endif diff --git a/doc/descriptions/hpsj5s.desc b/doc/descriptions/hpsj5s.desc index b4ca8c043..2bb00931d 100644 --- a/doc/descriptions/hpsj5s.desc +++ b/doc/descriptions/hpsj5s.desc @@ -10,7 +10,7 @@ ; :backend "hpsj5s" ; name of backend -:version "0.02" ; version of backend +:version "0.03" ; version of backend :status :new ; :alpha, :beta, :stable, :new :manpage "sane-hpsj5s" ; name of manpage (if it exists) :url "http://hpsj5s.sourceforge.net/" ; backend's web page @@ -23,7 +23,7 @@ :url "http://www.hp.com/" :model "HP ScanJet 5s" ; name models for above-specified mfg. :interface "Parport (EPP)" -:comment "Driver for abstraction layer required" +:comment "Requires libieee1284 library" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level.