From 512dcd9fd00b84221a0711a913ec04af6faa545c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Voltz?= Date: Thu, 9 Oct 2003 05:27:39 +0000 Subject: [PATCH] * added automatic parallel port detection, and special keyword in configuration file to use it. Indent cleaning. --- ChangeLog | 7 ++ backend/umax_pp.c | 126 +++++++++++++++++++++++++------ backend/umax_pp.conf | 11 ++- backend/umax_pp_low.c | 170 ++++++++++++++++++++++++++++++++---------- backend/umax_pp_low.h | 3 +- backend/umax_pp_mid.c | 3 +- backend/umax_pp_mid.h | 2 +- 7 files changed, 254 insertions(+), 68 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3efec0b86..7fc227e61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2003-10-09 Stéphane Voltz + + * backend/umax_pp.c backend/umax_pp_low.h backend/umax_pp.h + backend/umax_pp_mid.c backend/umax_pp_low.c backend/umax_pp_mid.h + backend/umax_pp.conf: added automatic parallel port detection, + and special keyword in configuration file to use it. + 2003-10-08 Gerhard Jaeger * backend/Makefile.in : linking plustek_pp- and test-backend against diff --git a/backend/umax_pp.c b/backend/umax_pp.c index 4d53c58ed..6e76ae540 100644 --- a/backend/umax_pp.c +++ b/backend/umax_pp.c @@ -163,7 +163,7 @@ static const SANE_Range u8_range = { #define MM_TO_PIXEL(mm, res) (SANE_UNFIX(mm) * (float )res / MM_PER_INCH) #define PIXEL_TO_MM(px, res) (SANE_FIX((float )(px * MM_PER_INCH / (res / 10)) / 10.0)) -#define UMAX_PP_DEFAULT_PORT 0x378 +#define UMAX_PP_DEFAULT_PORT "/dev/parport0" #define UMAX_PP_RESERVE 259200 /* @@ -316,6 +316,64 @@ attach (const char *devname) return SANE_STATUS_GOOD; } +/* + * walk a port list and try to attach to them + * + */ +static SANE_Int +umax_pp_try_ports (char **ports) +{ + int i; + int rc = SANE_STATUS_INVAL; + + if (ports != NULL) + { + i = 0; + rc = SANE_STATUS_INVAL; + while (ports[i] != NULL) + { + if (rc != SANE_STATUS_GOOD) + { + DBG (3, "umax_pp_try_ports: trying port `%s'\n", ports[i]); + rc = attach (ports[i]); + if (rc != SANE_STATUS_GOOD) + DBG (3, "init: couldn't attach to port `%s'\n", ports[i]); + else + DBG (3, "init: attach to port `%s' successfull\n", ports[i]); + } + free (ports[i]); + i++; + } + free (ports); + } + return rc; +} + +/* + * attempt to auto detect right parallel port + * if safe set to SANE_TRUE, no direct hardware access + * + */ +static SANE_Int +umax_pp_auto_attach (SANE_Int safe) +{ + char **ports; + int rc = SANE_STATUS_INVAL; + + /* safe tests: user parallel port devices */ + ports = sanei_parport_find_device (); + if (ports != NULL) + rc = umax_pp_try_ports (ports); + + /* try for direct hardware access */ + if ((safe != SANE_TRUE) && (rc != SANE_STATUS_GOOD)) + { + ports = sanei_parport_find_port (); + if (ports != NULL) + rc = umax_pp_try_ports (ports); + } + return rc; +} static SANE_Int umax_pp_get_sync (SANE_Int dpi) @@ -693,10 +751,10 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) if (fp == NULL) { - DBG (2, "init: no configuration file, using default `port 0x%03X'\n", + DBG (2, "init: no configuration file, using default `port %s'\n", UMAX_PP_DEFAULT_PORT); - ret = attach (STRINGIFY (UMAX_PP_DEFAULT_PORT)); + ret = attach (UMAX_PP_DEFAULT_PORT); return ret; } @@ -926,13 +984,33 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) cp += 5; cp = sanei_config_skip_whitespace (cp); - DBG (3, "init: trying port `%s'\n", cp); - if (*cp) { - DBG (3, "attach(%s)\n", cp); - if (attach (cp) != SANE_STATUS_GOOD) - DBG (2, "init: couldn't attach to port `%s'\n", cp); + /* here, the argument maybe a device, an address, or special + * keywords 'auto' and 'safe-auto' + */ + if (strcmp (cp, "safe-auto") == 0) + { + /* try every device we can find */ + if (umax_pp_auto_attach (SANE_TRUE) != SANE_STATUS_GOOD) + DBG (2, "init: safe-auto attach failed !"); + } + else if (strcmp (cp, "auto") == 0) + { + /* try every port/device we can find */ + if (umax_pp_auto_attach (SANE_FALSE) != SANE_STATUS_GOOD) + { + DBG (2, "init: auto attach failed !"); + } + } + else + { + DBG (3, "init: trying port `%s'\n", cp); + + DBG (3, "attach(%s)\n", cp); + if (attach (cp) != SANE_STATUS_GOOD) + DBG (2, "init: couldn't attach to port `%s'\n", cp); + } } } else if ((strncmp (cp, "name", 4) == 0) && isspace (cp[4])) @@ -1130,18 +1208,18 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) DBG (3, "open: trying default device %s, port=%s,ppdev=%s\n", devlist[0].sane.name, devlist[0].port, devlist[0].ppdevice); if (devlist[0].port != NULL) - { - if ((devlist[0].port[0] == '0') - && ((devlist[0].port[1] == 'x') || (devlist[0].port[1] == 'X'))) - prt = strtol (devlist[0].port + 2, NULL, 16); - else - prt = atoi (devlist[0].port); + { + if ((devlist[0].port[0] == '0') + && ((devlist[0].port[1] == 'x') || (devlist[0].port[1] == 'X'))) + prt = strtol (devlist[0].port + 2, NULL, 16); + else + prt = atoi (devlist[0].port); rc = sanei_umax_pp_open (prt, NULL); - } + } else - { - rc = sanei_umax_pp_open (0, devlist[0].ppdevice); - } + { + rc = sanei_umax_pp_open (0, devlist[0].ppdevice); + } desc = &devlist[0]; } switch (rc) @@ -1416,14 +1494,14 @@ sane_control_option (SANE_Handle handle, SANE_Int option, case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: - for(i=0;iopt[option].size/sizeof(SANE_Word);i++) - { - if(((SANE_Int *)val)[i]<0 || ((SANE_Int *)val)[i]>255) + for (i = 0; i < dev->opt[option].size / sizeof (SANE_Word); i++) + { + if (((SANE_Int *) val)[i] < 0 || ((SANE_Int *) val)[i] > 255) { - DBG (2, "Value at index %d out of range\n",i); - return SANE_STATUS_INVAL; + DBG (2, "Value at index %d out of range\n", i); + return SANE_STATUS_INVAL; } - } + } memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; diff --git a/backend/umax_pp.conf b/backend/umax_pp.conf index d6d66267b..b9cf5fa36 100644 --- a/backend/umax_pp.conf +++ b/backend/umax_pp.conf @@ -8,15 +8,22 @@ option buffer 2097152 # DEVICES # -# specify the port your scanner is connected to. Possible are 0x378 (lp0) -# 0x278 (lp2) and 0x3c8 (lp1) +# specify the port your scanner is connected to. # +# the value 'auto' will make the backend find the correct value +# by itself, it will scan ppdev, ppi device, then hardware address +# 'safe-auto' will do the same but wn't do direct hardware access # on linux systems, you may provide the device name of the ppdev character # device : /dev/parport0, /dev/parport1, ...... # # on *BSD, you may provide the device name of the ppi device: /dev/ppi0, # /dev/ppi1, ... +# +# Possible hardware addresses are 0x378 (lp0) +# 0x278 (lp2) and 0x3c8 (lp1) +# # default is ppdev since major use of the backend is for linux + port /dev/parport0 # the following options are local to this scanner diff --git a/backend/umax_pp_low.c b/backend/umax_pp_low.c index 5cfee6a51..5db1ba9cd 100644 --- a/backend/umax_pp_low.c +++ b/backend/umax_pp_low.c @@ -736,56 +736,148 @@ static void Insb (int port, unsigned char *dest, int size); static void Insw (int port, unsigned char *dest, int size); -/* - * returns 1 if succeds in getting base addr via /proc - * 0 on failure - * - * on successfull return, *addr will hold parport base addr - */ -int -sanei_parport_info (int number, int *addr) + +char ** +sanei_parport_find_port (void) { - char name[256]; + char **ports = NULL; +#ifdef ENABLE_PARPORT_DIRECTIO + int i, addr, ecpaddr; + int found = 0; + char name[80], buffer[80]; FILE *fic = NULL; - char buffer[64], val[16]; - int baseadr, ecpadr; - /* try 2.4 first */ - sprintf (name, "/proc/sys/dev/parport/parport%d/base-addr", number); - memset (buffer, 0, 64); - memset (val, 0, 16); - fic = fopen (name, "rb"); - if (fic == NULL) + /* direct I/O detection */ + /* linux 2.4 + 2.6 with proc support */ + for (i = 0; i < 4; i++) { - /* open failure, try 2.2 */ - sprintf (name, "/proc/parport/%d/hardware", number); + /* try to ensure loading of lp module */ + sprintf (name, "/dev/lp%d", i); + fic = fopen (name, "wb"); + if (fic != NULL) + fclose (fic); + sprintf (name, "/proc/sys/dev/parport/parport%d/base-addr", i); fic = fopen (name, "rb"); - if (fic == NULL) - { /* no proc at all */ - DBG (1, "sanei_parport_info(): no /proc \n"); - return 0; - } - fread (buffer, 64, 1, fic); - fclose (fic); - sscanf (buffer, "base: %s", val); - baseadr = strtol (val, NULL, 16); - - } - else - { - fread (buffer, 64, 1, fic); - fclose (fic); - if (sscanf (buffer, "%d %d", &baseadr, &ecpadr) < 1) + if (fic != NULL) { - /* empty base file */ - return 0; + fread (buffer, 64, 1, fic); + fclose (fic); + if (sscanf (buffer, "%d %d", &addr, &ecpaddr) > 0) + { + DBG (16, "parport at 0x%X\n", addr); + ports = + (char **) realloc (ports, (found + 2) * sizeof (char *)); + ports[found] = (char *) malloc (19); + sprintf (ports[found], "0x%X", addr); + found++; + ports[found] = NULL; + } } - *addr = baseadr; } - return 1; +#endif + return ports; } +char ** +sanei_parport_find_device (void) +{ + char *devices[] = { "/dev/ppi0", + "/dev/ppi1", + "/dev/ppi2", + "/dev/ppi3", + "/dev/parport0", + "/dev/parport1", + "/dev/parport2", + "/dev/parport3", + NULL + }; + int i, file; + int rc = 0; + int found = 0; + char **ports = NULL; + + + /* device finding */ + i = 0; + while (devices[i] != NULL) + { + DBG (16, "Controling %s: ", devices[i]); + file = open (devices[i], O_RDWR); + if (file < 0) + { + switch (errno) + { + case ENOENT: +#ifdef ENIO + case ENXIO: +#endif +#ifdef ENODEV + case ENODEV: +#endif + DBG (16, "no %s device ...\n", devices[i]); + break; + case EACCES: + DBG (16, "current user cannot use existing %s device ...\n", + devices[i]); + break; + default: + perror (devices[i]); + } + } + else + { +#ifdef HAVE_LINUX_PPDEV_H + /* on kernel < 2.4.23, you have to CLAIM the device + * to check it really exists + * we may hang if another program already claimed it + */ + rc = ioctl (file, PPCLAIM); + if (rc) + { + switch (errno) + { + case ENOENT: +#ifdef ENXIO + case ENXIO: +#endif +#ifdef ENODEV + case ENODEV: +#endif + DBG (16, "no %s device ...\n", devices[i]); + break; + case EACCES: + DBG (16, "current user cannot use existing %s device ...\n", + devices[i]); + break; + default: + DBG (16, "errno=%d\n", errno); + perror (devices[i]); + } + } + else + { + rc = ioctl (file, PPRELEASE); + } +#endif /* HAVE_LINUX_PPDEV_H */ + close (file); + if (!rc) + { + DBG (16, "adding %s to valid devices ...\n", devices[i]); + ports = + (char **) realloc (ports, (found + 2) * sizeof (char *)); + ports[found] = strdup (devices[i]); + found++; + ports[found] = NULL; + } + } + + /* suite */ + i++; + } + return ports; +} + /* diff --git a/backend/umax_pp_low.h b/backend/umax_pp_low.h index fc11ee9ae..071a62b68 100644 --- a/backend/umax_pp_low.h +++ b/backend/umax_pp_low.h @@ -114,7 +114,6 @@ extern void sanei_umax_pp_setport (int port); extern int sanei_umax_pp_getport (void); extern void sanei_umax_pp_setparport (int fd); extern int sanei_umax_pp_getparport (void); -extern int sanei_parport_info (int number, int *addr); extern void sanei_umax_pp_setastra (int mod); extern int sanei_umax_pp_getastra (void); extern int sanei_umax_pp_ScannerStatus (void); @@ -122,5 +121,7 @@ extern int sanei_umax_pp_ReleaseScanner (void); extern int sanei_umax_pp_EndSession (void); extern int sanei_umax_pp_ProbeScanner (int recover); +extern char **sanei_parport_find_port (void); +extern char **sanei_parport_find_device (void); extern int sanei_umax_pp_CmdSync (int cmd); diff --git a/backend/umax_pp_mid.c b/backend/umax_pp_mid.c index 5443b6bee..fec7dab8f 100644 --- a/backend/umax_pp_mid.c +++ b/backend/umax_pp_mid.c @@ -330,7 +330,8 @@ sanei_umax_pp_cancel (void) int sanei_umax_pp_start (int x, int y, int width, int height, int dpi, int color, int autoset, - int brightness, int contrast, int *rbpp, int *rtw, int *rth) + int brightness, int contrast, int *rbpp, int *rtw, + int *rth) { int col = BW_MODE; diff --git a/backend/umax_pp_mid.h b/backend/umax_pp_mid.h index fc8a3d304..e8c35e65c 100644 --- a/backend/umax_pp_mid.h +++ b/backend/umax_pp_mid.h @@ -112,7 +112,7 @@ extern int sanei_umax_pp_lamp (int on); */ -extern int sanei_umax_pp_open (int port,char *name); +extern int sanei_umax_pp_open (int port, char *name);