diff --git a/backend/hp-scl.c b/backend/hp-scl.c index 88742ff6c..7469bb208 100644 --- a/backend/hp-scl.c +++ b/backend/hp-scl.c @@ -44,6 +44,9 @@ /* $Log$ + Revision 1.13 2004/03/27 13:52:39 kig-guest + Keep USB-connection open (was problem with Linux 2.6.x) + Revision 1.12 2003/10/09 19:34:57 kig-guest Redo when TEST UNIT READY failed Redo when read returns with 0 bytes (non-SCSI only) @@ -88,6 +91,13 @@ extern int sanei_debug_hp;*/ #define HP_SCSI_CMD_LEN (6) #define HP_SCSI_BUFSIZ (HP_SCSI_MAX_WRITE + HP_SCSI_CMD_LEN) +#define HP_MAX_OPEN_FD 16 +static struct hp_open_fd_s /* structure to save info about open file descriptor */ +{ + char *devname; + HpConnect connect; + int fd; +} asHpOpenFd[HP_MAX_OPEN_FD]; /* @@ -130,6 +140,157 @@ typedef struct } PROCDATA_HANDLE; +/* Initialize structure where we remember out open file descriptors */ +void +hp_init_openfd () +{int iCount; + memset (asHpOpenFd, 0, sizeof (asHpOpenFd)); + + for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) + asHpOpenFd[iCount].fd = -1; +} + + +/* Look if the device is still open */ +static SANE_Status +hp_GetOpenDevice (const char *devname, HpConnect connect, int *pfd) + +{int iCount; + + for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) + { + if (!asHpOpenFd[iCount].devname) continue; + if ( (strcmp (asHpOpenFd[iCount].devname, devname) == 0) + && (asHpOpenFd[iCount].connect == connect) ) + { + if (pfd) *pfd = asHpOpenFd[iCount].fd; + DBG(3, "hp_GetOpenDevice: device %s is open with fd=%d\n", devname, + asHpOpenFd[iCount].fd); + return SANE_STATUS_GOOD; + } + } + DBG(3, "hp_GetOpenDevice: device %s not open\n", devname); + return SANE_STATUS_INVAL; +} + +/* Add an open file descriptor. This also decides */ +/* if we keep a connection open or not. */ +static SANE_Status +hp_AddOpenDevice (const char *devname, HpConnect connect, int fd) + +{int iCount, iKeepOpen; + static int iInitKeepFlags = 1; + + /* The default values which connections to keep open or not */ + static int iKeepOpenSCSI = 0; + static int iKeepOpenUSB = 1; + static int iKeepOpenDevice = 0; + static int iKeepOpenPIO = 0; + + if (iInitKeepFlags) /* Change the defaults by environment */ + {char *eptr; + + iInitKeepFlags = 0; + + eptr = getenv ("SANE_HP_KEEPOPEN_SCSI"); + if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) + iKeepOpenSCSI = (*eptr == '1'); + + eptr = getenv ("SANE_HP_KEEPOPEN_USB"); + if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) + iKeepOpenUSB = (*eptr == '1'); + + eptr = getenv ("SANE_HP_KEEPOPEN_DEVICE"); + if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) + iKeepOpenDevice = (*eptr == '1'); + + eptr = getenv ("SANE_HP_KEEPOPEN_PIO"); + if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) + iKeepOpenPIO = (*eptr == '1'); + } + + /* Look if we should keep it open or not */ + iKeepOpen = 0; + switch (connect) + { + case HP_CONNECT_SCSI: iKeepOpen = iKeepOpenSCSI; + break; + case HP_CONNECT_PIO : iKeepOpen = iKeepOpenPIO; + break; + case HP_CONNECT_USB : iKeepOpen = iKeepOpenUSB; + break; + case HP_CONNECT_DEVICE : iKeepOpen = iKeepOpenDevice; + break; + case HP_CONNECT_RESERVE: + break; + } + if (!iKeepOpen) + { + DBG(3, "hp_AddOpenDevice: %s should not be kept open\n", devname); + return SANE_STATUS_INVAL; + } + + for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) + { + if (!asHpOpenFd[iCount].devname) /* Is this entry free ? */ + { + asHpOpenFd[iCount].devname = sanei_hp_strdup (devname); + if (!asHpOpenFd[iCount].devname) return SANE_STATUS_NO_MEM; + DBG(3, "hp_AddOpenDevice: added device %s with fd=%d\n", devname, fd); + asHpOpenFd[iCount].connect = connect; + asHpOpenFd[iCount].fd = fd; + return SANE_STATUS_GOOD; + } + } + DBG(3, "hp_AddOpenDevice: %s not added\n", devname); + return SANE_STATUS_NO_MEM; +} + + +/* Check if we have remembered an open file descriptor */ +static SANE_Status +hp_IsOpenFd (int fd, HpConnect connect) + +{int iCount; + + for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) + { + if ( (asHpOpenFd[iCount].devname != NULL) + && (asHpOpenFd[iCount].fd == fd) + && (asHpOpenFd[iCount].connect == connect) ) + { + DBG(3, "hp_IsOpenFd: %d is open\n", fd); + return SANE_STATUS_GOOD; + } + } + DBG(3, "hp_IsOpenFd: %d not open\n", fd); + return SANE_STATUS_INVAL; +} + + +static SANE_Status +hp_RemoveOpenFd (int fd, HpConnect connect) + +{int iCount; + + for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) + { + if ( (asHpOpenFd[iCount].devname != NULL) + && (asHpOpenFd[iCount].fd == fd) + && (asHpOpenFd[iCount].connect == connect) ) + { + sanei_hp_free (asHpOpenFd[iCount].devname); + asHpOpenFd[iCount].devname = NULL; + DBG(3, "hp_RemoveOpenFd: removed %d\n", asHpOpenFd[iCount].fd); + asHpOpenFd[iCount].fd = -1; + return SANE_STATUS_GOOD; + } + } + DBG(3, "hp_RemoveOpenFd: %d not removed\n", fd); + return SANE_STATUS_INVAL; +} + + static SANE_Status hp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect) @@ -291,8 +452,13 @@ hp_nonscsi_open (const char *devname, int *fd, HpConnect connect) { DBG(1, "hp_nonscsi_open: open device %s failed\n", devname); } + else + { + DBG(17,"hp_nonscsi_open: device %s opened, fd=%d\n", devname, lfd); + } if (fd) *fd = lfd; + return status; } @@ -320,6 +486,7 @@ hp_nonscsi_close (int fd, HpConnect connect) default: break; } + DBG(17,"hp_nonscsi_close: closed fd=%d\n", fd); } SANE_Status @@ -327,17 +494,26 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect) { HpScsi new; SANE_Status status; + int iAlreadyOpen = 0; new = sanei_hp_allocz(sizeof(*new)); if (!new) return SANE_STATUS_NO_MEM; - status = hp_nonscsi_open(devname, &new->fd, connect); - if (FAILED(status)) + /* Is the device already open ? */ + if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) { - DBG(1, "nonscsi_new: open failed (%s)\n", sane_strstatus(status)); - sanei_hp_free(new); - return SANE_STATUS_IO_ERROR; + iAlreadyOpen = 1; + } + else + { + status = hp_nonscsi_open(devname, &new->fd, connect); + if (FAILED(status)) + { + DBG(1, "nonscsi_new: open failed (%s)\n", sane_strstatus(status)); + sanei_hp_free(new); + return SANE_STATUS_IO_ERROR; + } } /* For SCSI-devices we would have the inquire command here */ @@ -349,25 +525,44 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect) if ( new->devname ) strcpy (new->devname, devname); *newp = new; + + /* Remember the open device */ + if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); + return SANE_STATUS_GOOD; } static void -hp_scsi_close (HpScsi this) +hp_scsi_close (HpScsi this, int completely) {HpConnect connect; DBG(3, "scsi_close: closing fd %ld\n", (long)this->fd); connect = sanei_hp_scsi_get_connect (this); + if (!completely) /* May we keep the device open ? */ + { + if ( hp_IsOpenFd (this->fd, connect) == SANE_STATUS_GOOD ) + { + DBG(3, "scsi_close: not closing. Keep open\n"); + return; + } + + } assert(this->fd >= 0); if (connect != HP_CONNECT_SCSI) hp_nonscsi_close (this->fd, connect); else sanei_scsi_close (this->fd); + + DBG(3,"scsi_close: really closed\n"); + + /* Remove a remembered open device */ + hp_RemoveOpenFd (this->fd, connect); } + SANE_Status sanei_hp_scsi_new (HpScsi * newp, const char * devname) { @@ -377,8 +572,10 @@ sanei_hp_scsi_new (HpScsi * newp, const char * devname) HpScsi new; HpConnect connect; SANE_Status status; + int iAlreadyOpen = 0; connect = sanei_hp_get_connect (devname); + if (connect != HP_CONNECT_SCSI) return sanei_hp_nonscsi_new (newp, devname, connect); @@ -386,13 +583,21 @@ sanei_hp_scsi_new (HpScsi * newp, const char * devname) if (!new) return SANE_STATUS_NO_MEM; - status = sanei_scsi_open(devname, &new->fd, 0, 0); - if (FAILED(status)) - { - DBG(1, "scsi_new: open failed (%s)\n", sane_strstatus(status)); - sanei_hp_free(new); - return SANE_STATUS_IO_ERROR; - } + /* Is the device still open ? */ + if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) + { + iAlreadyOpen = 1; + } + else + { + status = sanei_scsi_open(devname, &new->fd, 0, 0); + if (FAILED(status)) + { + DBG(1, "scsi_new: open failed (%s)\n", sane_strstatus(status)); + sanei_hp_free(new); + return SANE_STATUS_IO_ERROR; + } + } DBG(3, "scsi_inquire: sending INQUIRE\n"); status = sanei_scsi_cmd(new->fd, inq_cmd, 6, new->inq_data, &inq_len); @@ -441,6 +646,10 @@ sanei_hp_scsi_new (HpScsi * newp, const char * devname) if ( new->devname ) strcpy (new->devname, devname); *newp = new; + + /* Remember the open device */ + if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); + return SANE_STATUS_GOOD; } @@ -457,14 +666,14 @@ sanei_hp_scsi_new (HpScsi * newp, const char * devname) * device (from hp-handle.c), and "completely" destroy it when * the frontend closes its handle. */ void -sanei_hp_scsi_destroy (HpScsi this,int UNUSEDARG completely) +sanei_hp_scsi_destroy (HpScsi this,int completely) { /* Moved to hp_scsi_close(): * assert(this->fd >= 0); * DBG(3, "scsi_close: closing fd %d\n", this->fd); */ - hp_scsi_close (this); + hp_scsi_close (this, completely); if ( this->devname ) sanei_hp_free (this->devname); sanei_hp_free(this); } diff --git a/backend/hp.c b/backend/hp.c index 52c024233..e95e70446 100644 --- a/backend/hp.c +++ b/backend/hp.c @@ -43,12 +43,17 @@ HP Scanner Control Language (SCL). */ -static char *hp_backend_version = "1.05"; +static char *hp_backend_version = "1.06"; static char *hp_backend_revision = "$Revision$"; /* Changes: - V 1.05: + V 1.06: $Log$ + Revision 1.20 2004/03/27 13:52:39 kig-guest + Keep USB-connection open (was problem with Linux 2.6.x) + + + V 1.05: Revision 1.19 2003/10/24 17:26:07 kig-guest Use new sanei-thread-interface @@ -804,6 +809,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback UNUSEDARG authorize) DBG(3, "sane_init called\n"); sanei_thread_init (); + hp_init_openfd (); hp_destroy(); if (version_code) diff --git a/backend/hp.h b/backend/hp.h index 97c7d2dda..705437e78 100644 --- a/backend/hp.h +++ b/backend/hp.h @@ -164,6 +164,8 @@ typedef int HpScl; typedef long int HpScl; #endif +void hp_init_openfd (void); + typedef struct { int lines;