[sane-devel] DLL backend doesn't work on 680x0 machines

Dave Huang khym@azeotrope.org
Fri, 11 Apr 2003 18:33:13 -0500


I've been using an old (68k) Mac running NetBSD as my scanning machine,
and ever since upgrading it to NetBSD 1.6, SANE quit working--it says
that it can't find any scanners.

I just got around to trying to figure out what was wrong, and it turns
out the trigger was that NetBSD on 68k machines switched from a.out to
ELF. Along with the change in object formats was a change in the ABI. In
particular, how function return values were returned. With a.out, all
functions return values in the D0 register, but with ELF, integral types
are returned in the D0 register, but pointers are returned in the A0
register.

SANE's DLL backend doesn't work under that scheme, because "op" in
struct backend is declared as "void *(*op[NUM_OPS]) ()". I.e., a
function that returns a pointer. However, in the various backends, the
actual functions generally return SANE_Status, a non-pointer. In my
case, I have an HP scanner, and sane_hp_init() was returning
SANE_STATUS_GOOD in the D0 register. However, when dll.c's init() called
it with:
  status = (long) (*be->op[OP_INIT]) (&version, auth_callback);
it was setting status to the value of the A0 register, which contained
some leftover pointer, and was not SANE_STATUS_GOOD.

There are a couple of solutions... keep "op" in struct backend as a 
function that returns a pointer, and change all the non-void backend 
operations to actually return a pointer; change "op" in struct backend 
to a function that returns an integer (such as intptr_t), and change 
the non-void backend ops to return integers (which they all do already, 
except for get_option_descriptor); or change the places where the ops 
are called and cast the function pointer to match the particular op 
being called, rather than casting the result of the call. E.g., for the 
above call to init:

  status = (*(SANE_Status(*)())be->op[OP_INIT]) (&version, auth_callback);

Since the latter option touches the least amount of code, here's a
patch:

--- backend/dll.c.orig	Wed Dec  4 14:30:26 2002
+++ backend/dll.c	Fri Apr 11 17:50:23 2003
@@ -481,7 +481,7 @@
 
   DBG (3, "init: initializing backend `%s'\n", be->name);
 
-  status = (long) (*be->op[OP_INIT]) (&version, auth_callback);
+  status = (*(SANE_Status(*)())be->op[OP_INIT]) (&version, auth_callback);
   if (status != SANE_STATUS_GOOD)
     return status;
 
@@ -790,7 +790,7 @@
 	if (init (be) != SANE_STATUS_GOOD)
 	  continue;
 
-      status = (long) (*be->op[OP_GET_DEVS]) (&be_list, local_only);
+      status = (*(SANE_Status(*)())be->op[OP_GET_DEVS]) (&be_list, local_only);
       if (status != SANE_STATUS_GOOD || !be_list)
 	continue;
 
@@ -929,7 +929,7 @@
 	return status;
     }
 
-  status = (long) (*be->op[OP_OPEN]) (dev_name, &handle);
+  status = (*(SANE_Status(*)())be->op[OP_OPEN]) (dev_name, &handle);
   if (status != SANE_STATUS_GOOD)
     return status;
 
@@ -973,7 +973,7 @@
   DBG (3,
        "sane_control_option(handle=%p,option=%d,action=%d,value=%p,info=%p)\n",
        handle, option, action, value, info);
-  return (long) (*s->be->op[OP_CTL_OPTION]) (s->handle, option, action, value,
+  return (*(SANE_Status(*)())s->be->op[OP_CTL_OPTION]) (s->handle, option, action, value,
 					     info);
 }
 
@@ -983,7 +983,7 @@
   struct meta_scanner *s = handle;
 
   DBG (3, "sane_get_parameters(handle=%p,params=%p)\n", handle, params);
-  return (long) (*s->be->op[OP_GET_PARAMS]) (s->handle, params);
+  return (*(SANE_Status(*)())s->be->op[OP_GET_PARAMS]) (s->handle, params);
 }
 
 SANE_Status
@@ -992,7 +992,7 @@
   struct meta_scanner *s = handle;
 
   DBG (3, "sane_start(handle=%p)\n", handle);
-  return (long) (*s->be->op[OP_START]) (s->handle);
+  return (*(SANE_Status(*)())s->be->op[OP_START]) (s->handle);
 }
 
 SANE_Status
@@ -1003,7 +1003,7 @@
 
   DBG (3, "sane_read(handle=%p,data=%p,maxlen=%d,lenp=%p)\n",
        handle, data, max_length, length);
-  return (long) (*s->be->op[OP_READ]) (s->handle, data, max_length, length);
+  return (*(SANE_Status(*)())s->be->op[OP_READ]) (s->handle, data, max_length, length);
 }
 
 void
@@ -1022,7 +1022,7 @@
 
   DBG (3, "sane_set_io_mode(handle=%p,nonblocking=%d)\n", handle,
        non_blocking);
-  return (long) (*s->be->op[OP_SET_IO_MODE]) (s->handle, non_blocking);
+  return (*(SANE_Status(*)())s->be->op[OP_SET_IO_MODE]) (s->handle, non_blocking);
 }
 
 SANE_Status
@@ -1031,5 +1031,5 @@
   struct meta_scanner *s = handle;
 
   DBG (3, "sane_get_select_fd(handle=%p,fdp=%p)\n", handle, fd);
-  return (long) (*s->be->op[OP_GET_SELECT_FD]) (s->handle, fd);
+  return (*(SANE_Status(*)())s->be->op[OP_GET_SELECT_FD]) (s->handle, fd);
 }

-- 
Name: Dave Huang         |  Mammal, mammal / their names are called /
INet: khym@azeotrope.org |  they raise a paw / the bat, the cat /
FurryMUCK: Dahan         |  dolphin and dog / koala bear and hog -- TMBG
Dahan: Hani G Y+C 27 Y++ L+++ W- C++ T++ A+ E+ S++ V++ F- Q+++ P+ B+ PA+ PL++