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: k...@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++