int main (int argc, char** argv) { bool pass = false; list *cache = NULL; SANE_Status status = SANE_STATUS_GOOD; /* Log at least broken promises and unmet requirements. */ setenv ("SANE_DEBUG_EPKOWA", "FATAL", false); msg_init (); cache = (list *) model_info_cache_init (getenv ("srcdir"), &status); if (!cache) { err_fatal ("cannot initialise model info cache (%s)", sane_strstatus (status)); return EXIT_FAILURE; } while (--argc && ++argv) { const void *info = model_info_cache_get_info (*argv, &status); if (!info) { err_major ("cannot get info for '%s' (%s)", *argv, sane_strstatus (status)); } } pass = check_cache_content (cache); cache = model_info_cache_exit (cache); return (pass ? EXIT_SUCCESS : EXIT_FAILURE); }
int usb_dev_request (struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen) { SANE_Status status; size_t len = cmdlen; if (cmd && cmdlen) { status = sanei_usb_write_bulk (dev->dn, cmd, &cmdlen); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: sanei_usb_write_bulk: %s\n", __FUNCTION__, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } if (cmdlen != len) { DBG (1, "%s: sanei_usb_write_bulk: wanted %lu bytes, wrote %lu bytes\n", __FUNCTION__, (size_t)len, (size_t)cmdlen); return SANE_STATUS_IO_ERROR; } } if (resp && resplen) { status = sanei_usb_read_bulk (dev->dn, resp, resplen); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: sanei_usb_read_bulk: %s\n", __FUNCTION__, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } return SANE_STATUS_GOOD; }
void KSaneScanThread::readData() { SANE_Int readBytes = 0; m_saneStatus = sane_read(m_saneHandle, m_readData, SCAN_READ_CHUNK_SIZE, &readBytes); switch (m_saneStatus) { case SANE_STATUS_GOOD: // continue to parsing the data break; case SANE_STATUS_EOF: if (m_frameRead < m_frameSize) { kDebug() << "frameRead =" << m_frameRead << ", frameSize =" << m_frameSize << "readBytes =" << readBytes; if ((readBytes > 0) && ((m_frameRead + readBytes) <= m_frameSize)) { kDebug() << "This is not a standard compliant backend"; copyToScanData(readBytes); } m_readStatus = READ_READY; // It is better to return a broken image than nothing return; } if (m_params.last_frame == SANE_TRUE) { // this is where it all ends well :) m_readStatus = READ_READY; return; } else { // start reading next frame m_saneStatus = sane_start(m_saneHandle); if (m_saneStatus != SANE_STATUS_GOOD) { kDebug() << "sane_start =" << sane_strstatus(m_saneStatus); m_readStatus = READ_ERROR; return; } m_saneStatus = sane_get_parameters(m_saneHandle, &m_params); if (m_saneStatus != SANE_STATUS_GOOD) { kDebug() << "sane_get_parameters =" << sane_strstatus(m_saneStatus); m_readStatus = READ_ERROR; sane_cancel(m_saneHandle); return; } //kDebug() << "New Frame"; m_frameRead = 0; m_frame_t_count++; break; } default: kDebug() << "sane_read=" << m_saneStatus << "=" << sane_strstatus(m_saneStatus); m_readStatus = READ_ERROR; sane_cancel(m_saneHandle); return; } copyToScanData(readBytes); }
void KSaneScanThread::run() { m_dataSize = 0; m_readStatus = READ_ON_GOING; m_saneStartDone = false; // Start the scanning with sane_start m_saneStatus = sane_start(m_saneHandle); m_saneStartDone = true; if (m_readStatus == READ_CANCEL) { return; } if (m_saneStatus != SANE_STATUS_GOOD) { kDebug() << "sane_start=" << sane_strstatus(m_saneStatus); m_readStatus = READ_ERROR; // oneFinalScanDone() does the sane_cancel() return; } // Read image parameters m_saneStatus = sane_get_parameters(m_saneHandle, &m_params); if (m_saneStatus != SANE_STATUS_GOOD) { kDebug() << "sane_get_parameters=" << sane_strstatus(m_saneStatus); m_readStatus = READ_ERROR; // oneFinalScanDone() does the sane_cancel() return; } // calculate data size m_frameSize = m_params.lines * m_params.bytes_per_line; if ((m_params.format == SANE_FRAME_RED) || (m_params.format == SANE_FRAME_GREEN) || (m_params.format == SANE_FRAME_BLUE)) { m_dataSize = m_frameSize*3; } else { m_dataSize = m_frameSize; } m_data->clear(); if (m_dataSize > 0) { m_data->reserve(m_dataSize); } m_frameRead = 0; m_frame_t_count = 0; m_readStatus = READ_ON_GOING; while (m_readStatus == READ_ON_GOING) { readData(); } }
static SANE_Status st400_wait_ready( int fd ) { #define SLEEPTIME 100000L /* 100ms */ long max_sleep = 60000000L; /* 60 seconds */ SANE_Status status; DBG(DCODE, "st400_wait_ready(%d)\n", fd); while(1) { status = st400_test_ready(fd); switch( status ) { case SANE_STATUS_DEVICE_BUSY: if( max_sleep > 0 ) { usleep(SLEEPTIME); /* retry after 100ms */ max_sleep -= SLEEPTIME; break; } /* else fall through */ default: DBG(DERR, "st400_wait_ready: failed, error=%s\n", sane_strstatus(status)); /* fall through */ case SANE_STATUS_GOOD: return status; } } /*NOTREACHED*/ }
bool KSaneOption::writeData(void *data) { SANE_Status status; SANE_Int res; if (state() == STATE_DISABLED) { return false; } status = sane_control_option(m_handle, m_index, SANE_ACTION_SET_VALUE, data, &res); if (status != SANE_STATUS_GOOD) { qDebug() << m_optDesc->name << "sane_control_option returned:" << sane_strstatus(status); // write failed. re read the current setting readValue(); return false; } if ((res & SANE_INFO_INEXACT) && (m_widget != 0)) { //qDebug() << "write was inexact. Reload value just in case..."; readValue(); } if (res & SANE_INFO_RELOAD_OPTIONS) { emit optsNeedReload(); // optReload reloads also the values } else if (res & SANE_INFO_RELOAD_PARAMS) { // 'else if' because with optReload we force also valReload :) emit valsNeedReload(); } return true; }
static SANE_Status wait_ready (int fd) { SANE_Status status; int i; for (i = 0; i < 1000; ++i) { DBG(3, "wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } DBG(1, "wait_ready: timed out after %d attempts\n", i); return SANE_STATUS_INVAL; }
/** Function GetDevices * @brief Request all devices from SANE * * @param[out] device_list pointer to -> NULL terminated array of SANE_Device's * @param[out] size the number of devices * @return 0 OK - else error * */ int GetDevices(const SANE_Device *** device_list, int *size) { int status, s = 0; const SANE_Device **dl = NULL; printf(PRFX "Scanning SANE devices..."); fflush(NULL); status = sane_get_devices(&dl, SANE_FALSE); if (status != SANE_STATUS_GOOD) { SANE_msg(oyMSG_WARN, 0, "%s()\n Cannot get sane devices: %s\n", __func__, sane_strstatus(status)); fflush(NULL); return 1; } *device_list = dl; while (dl[s]) s++; *size = s; printf("OK [%d]\n", s); fflush(NULL); return 0; }
static PyObject *getErrorMessage(PyObject * self, PyObject * args) { int st; if (!PyArg_ParseTuple (args, "i", &st)) raiseError("Invalid arguments."); return Py_BuildValue("s", sane_strstatus (st)); }
static SANE_Status st400_set_window( ST400_Device *dev ) { unsigned short xoff, yoff; SANE_Byte th; struct { /* 10byte command */ SANE_Byte cmd, lun, reserved1[4], tr_len[3], ctrl; /* 40byte window struct */ SANE_Byte reserved2[6], wd_len[2], winnr, reserved3; SANE_Byte x_res[2], y_res[2]; /* resolution: 200, 300, 400 */ SANE_Byte x_ul[2], y_ul[2]; /* upper left corner */ SANE_Byte width[2], height[2]; SANE_Byte reserved4, threshold; SANE_Byte reserved5, halftone; /* ht: 0 or 2 */ SANE_Byte bitsperpixel, reserved6[13]; /* bpp: 1 or 8 */ } scsi_cmd; /* The PC/Amiga source uses reserved5 to indicate A4/A5 paper size * (values 4 and 5), but a comment implies that this is only for the * scanning program and the value is ignored by the scanner. */ SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_SET_WINDOW; set24(scsi_cmd.tr_len, 40); set16(scsi_cmd.wd_len, 32); /* These offsets seem to be required to avoid damaging the scanner: * If a scan with 0/0 as the top left corner is started, the scanner * seems to try to move the carriage over the bottom end (not a * pretty sound). */ xoff = (11L * dev->val[OPT_RESOLUTION]) / 100; yoff = 6; th = (double)maxval(dev->model->bits) * SANE_UNFIX(dev->val[OPT_THRESHOLD]) / 100.0; scsi_cmd.winnr = 1; set16(scsi_cmd.x_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.y_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.x_ul, dev->x + xoff); set16(scsi_cmd.y_ul, dev->wy + yoff); set16(scsi_cmd.width, dev->w); set16(scsi_cmd.height, dev->wh); scsi_cmd.threshold = th; scsi_cmd.halftone = (dev->val[OPT_DEPTH] == 1) ? 0 : 2; scsi_cmd.bitsperpixel = dev->val[OPT_DEPTH]; DBG(DSCSI, "SCSI: sending SET_WINDOW (x=%hu y=%hu w=%hu h=%hu wy=%hu wh=%hu th=%d\n", dev->x, dev->y, dev->w, dev->h, dev->wy, dev->wh, (int)th); status = sanei_scsi_cmd(dev->fd, &scsi_cmd, sizeof(scsi_cmd), 0, 0); DBG(DSCSI, "SCSI: result=%s\n", sane_strstatus(status)); return status; }
/* Raise a SANE exception */ PyObject * PySane_Error(SANE_Status st) { const char *string; if (st==SANE_STATUS_GOOD) {Py_INCREF(Py_None); return (Py_None);} string=sane_strstatus(st); PyErr_SetString(ErrorObject, string); return NULL; }
/** * cd_sane_client_refresh: **/ static void cd_sane_client_refresh (CdMainPrivate *priv) { CdMainDev *tmp; const SANE_Device **device_list = NULL; gint idx; guint i; SANE_Status status; status = sane_init (NULL, NULL); if (status != SANE_STATUS_GOOD) { g_warning ("failed to init SANE: %s", sane_strstatus (status)); goto out; } /* get scanners on the local server */ status = sane_get_devices (&device_list, TRUE); if (status != SANE_STATUS_GOOD) { g_warning ("failed to get devices from SANE: %s", sane_strstatus (status)); goto out; } /* nothing */ if (device_list == NULL || device_list[0] == NULL) goto out; /* add them */ for (idx = 0; device_list[idx] != NULL; idx++) cd_sane_client_add (priv, device_list[idx]); /* remove any that are invalid */ for (i = 0; i < priv->array->len; i++) { tmp = g_ptr_array_index (priv->array, i); if (tmp->valid) continue; cd_sane_client_remove (priv, tmp->device); } out: g_main_loop_quit (priv->loop); }
void sane_exit (void) { Mustek_Usb_Device *dev, *next; SANE_Status status; DBG (5, "sane_exit: start\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; if (dev->is_prepared) { status = usb_high_scan_clearup (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_clearup returned %s\n", sane_strstatus (status)); } status = usb_high_scan_exit (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_exit returned %s\n", sane_strstatus (status)); if (dev->chip) { status = usb_high_scan_exit (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_exit: while closing %s, usb_high_scan_exit returned: " "%s\n", dev->name, sane_strstatus (status)); } free ((void *) dev->name); free (dev); } first_dev = 0; if (devlist) free (devlist); devlist = 0; DBG (5, "sane_exit: exit\n"); }
static void build_menu(Widget widget, XtPointer clientdata, XtPointer call_data) { WidgetList children,wlist; Cardinal nchildren; const SANE_Device **list; Widget push; XmString str; char action[256]; int rc,i; /* del old */ XtVaGetValues(widget, XtNchildren,&children, XtNnumChildren,&nchildren, NULL); wlist = malloc(sizeof(Widget*)*nchildren); memcpy(wlist,children,sizeof(Widget*)*nchildren); for (i = 0; i < nchildren; i++) XtDestroyWidget(wlist[i]); free(wlist); /* create new */ if (SANE_STATUS_GOOD != (rc = sane_init(NULL,NULL))) { fprintf(stderr,"sane_init: %s\n",sane_strstatus(rc)); goto done; } sane_get_devices(&list,0); if (NULL == list[0]) goto done; for (i = 0; list[i] != NULL; i++) { if (debug) fprintf(stderr,"sane dev: %s | %s | %s | %s\n", list[i]->name, list[i]->vendor, list[i]->model, list[i]->type); str = XmStringGenerate((char*)list[i]->model, NULL, XmMULTIBYTE_TEXT, NULL); push = XtVaCreateManagedWidget(list[i]->name, xmPushButtonWidgetClass,widget, XmNlabelString,str, NULL); XmStringFree(str); sprintf(action,"Scan(%s)",list[i]->name); XtAddCallback(push,XmNactivateCallback,action_cb,strdup(action)); } done: sane_exit(); }
void sane_cancel (SANE_Handle handle) { Mustek_Usb_Scanner *s = handle; SANE_Status status; DBG (5, "sane_cancel: start\n"); status = usb_high_scan_stop_scan (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_cancel: usb_high_scan_stop_scan returned `%s' for `%s'\n", sane_strstatus (status), s->hw->name); usb_high_scan_back_home (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_cancel: usb_high_scan_back_home returned `%s' for `%s'\n", sane_strstatus (status), s->hw->name); if (s->scanning) { s->scanning = SANE_FALSE; if (s->total_bytes != (s->params.bytes_per_line * s->params.lines)) DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d " "bytes\n", s->total_bytes, s->params.bytes_per_line * s->params.lines); else DBG (3, "sane_cancel: scan finished, scanned %d bytes\n", s->total_bytes); } else { DBG (4, "sane_cancel: scan has not been initiated yet, " "or it is already aborted\n"); } DBG (5, "sane_cancel: exit\n"); return; }
/*! \brief Returns a best-effort model name based on \a fw_name. * * The caller gets to manage the memory occupied by the string that * is returned. Note that \c NULL may be returned. */ char * model_info_cache_get_model (const char *fw_name) { SANE_Status s = SANE_STATUS_GOOD; _model_info_t *m = NULL; log_call ("(%s)", fw_name); require (_cache && _datadir); if (!fw_name || 0 == strlen (fw_name)) { err_minor ("%s", sane_strstatus (SANE_STATUS_INVAL)); return strdup ("(unknown model)"); } m = _model_info_cache_get_info (fw_name, &s); if (!m) { err_minor ("%s", sane_strstatus (s)); return strdup (fw_name); /* best we can do */ } return strdup (m->name); }
/* Raise a SANE exception using a SANE_Status code */ PyObject *raiseSaneError (SANE_Status st) { const char *string; if (st == SANE_STATUS_GOOD) { Py_INCREF (Py_None); return (Py_None); } string = sane_strstatus (st); //PyErr_SetString (ErrorObject, string); PyErr_SetObject(ErrorObject, PyInt_FromLong(st)); return NULL; }
static SANE_Status st400_cmd6( int fd, SANE_Byte cmd, SANE_Byte ctrl ) { struct { SANE_Byte cmd, lun, reserved[2], tr_len, ctrl; } scsi_cmd; SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = cmd; scsi_cmd.ctrl = ctrl; DBG(DSCSI, "SCSI: sending cmd6 0x%02x (ctrl=%d)\n", (int)cmd, (int)ctrl); status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), 0, 0); DBG(DSCSI, "SCSI: result=%s\n", sane_strstatus(status)); return status; }
static SANE_Status st400_read10( int fd, SANE_Byte *buf, size_t *lenP ) { struct { SANE_Byte cmd, lun, res[4], tr_len[3], ctrl; } scsi_cmd; SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_READ10; set24(scsi_cmd.tr_len, *lenP); DBG(DSCSI, "SCSI: sending READ10 (%lu bytes)\n", (u_long)(*lenP)); status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), buf, lenP); DBG(DSCSI, "SCSI: result=%s (%lu bytes)\n", sane_strstatus(status), (u_long)(*lenP)); return status; }
SANE_Status usb_dev_open (struct device *dev) { SANE_Status status; DBG (3, "%s: open %p\n", __FUNCTION__, (void *)dev); status = sanei_usb_open (dev->sane.name, &dev->dn); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: sanei_usb_open(%s): %s\n", __FUNCTION__, dev->sane.name, sane_strstatus (status)); dev->dn = -1; return status; } sanei_usb_clear_halt (dev->dn); return SANE_STATUS_GOOD; }
/* Open the device. */ static SANE_Status sanei_umaxusb_open (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg) { SANE_Status status; handler = handler; /* silence gcc */ handler_arg = handler_arg; /* silence gcc */ status = sanei_usb_open (dev, fdp); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_umaxusb_open: open of `%s' failed: %s\n", dev, sane_strstatus(status)); return status; } else { SANE_Word vendor; SANE_Word product; /* We have openned the device. Check that it is a USB scanner. */ if (sanei_usb_get_vendor_product (*fdp, &vendor, &product) != SANE_STATUS_GOOD) { /* This is not a USB scanner, or SANE or the OS doesn't support it. */ sanei_usb_close(*fdp); *fdp = -1; return SANE_STATUS_UNSUPPORTED; } /* So it's a scanner. Does this backend support it? * Only the UMAX 2200 USB is currently supported. */ if ((vendor != 0x1606) || (product != 0x0230)) { sanei_usb_close(*fdp); *fdp = -1; return SANE_STATUS_UNSUPPORTED; } /* It's a good scanner. Initialize it. * * Note: pv8630_init_umaxusb_scanner() is for the UMAX * 2200. Other UMAX scanner might need a different * initialization routine. */ pv8630_init_umaxusb_scanner(*fdp); } return(SANE_STATUS_GOOD); }
void sane_menu(Widget menu) { Widget submenu; int rc; if (SANE_STATUS_GOOD != (rc = sane_init(NULL,NULL))) { fprintf(stderr,"sane_init: %s\n",sane_strstatus(rc)); goto done; } submenu = XmCreatePulldownMenu(menu,"scanM",NULL,0); XtVaCreateManagedWidget("scan",xmCascadeButtonWidgetClass,menu, XmNsubMenuId,submenu,NULL); XtAddCallback(submenu, XmNmapCallback, build_menu, NULL); done: sane_exit(); }
static SANE_Status list_one_device (SANE_String_Const devname) { struct device *dev; SANE_Status status; transport *tr; DBG (4, "%s: %s\n", __FUNCTION__, devname); for (dev = devices_head; dev; dev = dev->next) { if (strcmp (dev->sane.name, devname) == 0) return SANE_STATUS_GOOD; } tr = tr_from_devname(devname); dev = calloc (1, sizeof (struct device)); if (dev == NULL) return SANE_STATUS_NO_MEM; dev->sane.name = strdup (devname); dev->io = tr; status = tr->dev_open (dev); if (status != SANE_STATUS_GOOD) { dev_free (dev); return status; } /* status = dev_cmd (dev, CMD_ABORT);*/ status = dev_inquiry (dev); tr->dev_close (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: dev_inquiry(%s): %s\n", __FUNCTION__, dev->sane.name, sane_strstatus (status)); dev_free (dev); return status; } /* good device, add it to list */ dev->next = devices_head; devices_head = dev; return SANE_STATUS_GOOD; }
static SANE_Status wait_ready (int fd) { #define MAX_WAITING_TIME 60 /* one minute, at most */ struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); while (1) { DBG (USER_MESSAGE, "wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (ERROR_MESSAGE, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (ERROR_MESSAGE, "wait_ready: timed out after %ld seconds\n", (long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; }
/*! \brief Modify selected commands in the \a cmd specification * * This function caters to quirks in the command level specification * reported by the device. Especially commands for hardware options * may be affected. * * \return \c true if commands have been modified, \c false otherwise */ bool model_info_customise_commands (const void *self, EpsonCmd cmd) { bool customised = false; _model_info_t *self_ = NULL; require (self); /* ?FIXME? check if in _cache? */ if (!cmd) { err_minor ("%s", sane_strstatus (SANE_STATUS_INVAL)); return customised; } self_ = (_model_info_t *) self; customised |= _model_info_set_cmd (self_, &cmd->set_focus_position, FOCUS); customised |= _model_info_set_cmd (self_, &cmd->feed, FEED); customised |= _model_info_set_cmd (self_, &cmd->eject, EJECT); return customised; }
/* * take a bunch of pointers, send commands to scanner */ static SANE_Status do_cmd(struct scanner *s, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { /* sanei_usb overwrites the transfer size, so make some local copies */ size_t loc_cmdLen = cmdLen; size_t loc_outLen = outLen; size_t loc_inLen = *inLen; int cmdTime = USB_COMMAND_TIME; int outTime = USB_DATA_TIME; int inTime = USB_DATA_TIME; int ret = 0; DBG (10, "do_cmd: start\n"); if(shortTime){ cmdTime /= 20; outTime /= 20; inTime /= 20; } /* change timeout */ sanei_usb_set_timeout(cmdTime); /* write the command out */ DBG(25, "cmd: writing %ld bytes, timeout %d\n", (long)cmdLen, cmdTime); hexdump(30, "cmd: >>", cmdBuff, cmdLen); ret = sanei_usb_write_bulk(s->fd, cmdBuff, &cmdLen); DBG(25, "cmd: wrote %ld bytes, retVal %d\n", (long)cmdLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"cmd: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_cmdLen != cmdLen){ DBG(5,"cmd: wrong size %ld/%ld\n", (long)loc_cmdLen, (long)cmdLen); return SANE_STATUS_IO_ERROR; } /* this command has a write component, and a place to get it */ if(outBuff && outLen && outTime){ /* change timeout */ sanei_usb_set_timeout(outTime); DBG(25, "out: writing %ld bytes, timeout %d\n", (long)outLen, outTime); hexdump(30, "out: >>", outBuff, outLen); ret = sanei_usb_write_bulk(s->fd, outBuff, &outLen); DBG(25, "out: wrote %ld bytes, retVal %d\n", (long)outLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"out: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"out: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_outLen != outLen){ DBG(5,"out: wrong size %ld/%ld\n", (long)loc_outLen, (long)outLen); return SANE_STATUS_IO_ERROR; } } /* this command has a read component, and a place to put it */ if(inBuff && inLen && inTime){ memset(inBuff,0,*inLen); /* change timeout */ sanei_usb_set_timeout(inTime); DBG(25, "in: reading %ld bytes, timeout %d\n", (long)*inLen, inTime); ret = sanei_usb_read_bulk(s->fd, inBuff, inLen); DBG(25, "in: retVal %d\n", ret); if(ret == SANE_STATUS_EOF){ DBG(5,"in: got EOF, continuing\n"); } else if(ret != SANE_STATUS_GOOD){ DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); return ret; } DBG(25, "in: read %ld bytes\n", (long)*inLen); if(*inLen){ hexdump(30, "in: <<", inBuff, *inLen); } if(loc_inLen != *inLen){ ret = SANE_STATUS_EOF; DBG(5,"in: short read %ld/%ld\n", (long)loc_inLen, (long)*inLen); } } DBG (10, "do_cmd: finish\n"); return ret; }
bool KSaneWidget::openDevice(const QString &deviceName) { int i = 0; const SANE_Option_Descriptor *optDesc; SANE_Status status; SANE_Word numSaneOptions; SANE_Int res; KPasswordDialog *dlg; KWallet::Wallet *saneWallet; QString myFolderName = QStringLiteral("ksane"); QMap<QString, QString> wallet_entry; if (d->m_saneHandle != 0) { // this KSaneWidget already has an open device return false; } // don't bother trying to open if the device string is empty if (deviceName.isEmpty()) { return false; } // save the device name d->m_devName = deviceName; // Try to open the device status = sane_open(deviceName.toLatin1().constData(), &d->m_saneHandle); bool password_dialog_ok = true; // prepare wallet for authentication and create password dialog if (status == SANE_STATUS_ACCESS_DENIED) { saneWallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), winId()); if (saneWallet) { dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine | KPasswordDialog::ShowKeepPassword); if (!saneWallet->hasFolder(myFolderName)) { saneWallet->createFolder(myFolderName); } saneWallet->setFolder(myFolderName); saneWallet->readMap(deviceName, wallet_entry); if (!wallet_entry.empty() || true) { dlg->setUsername(wallet_entry[QStringLiteral("username")]); dlg->setPassword(wallet_entry[QStringLiteral("password")]); dlg->setKeepPassword(true); } } else { dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine); } dlg->setPrompt(i18n("Authentication required for resource: %1", deviceName)); } // sane_open failed due to insufficient authorization // retry opening device with user provided data assisted with kwallet records while (status == SANE_STATUS_ACCESS_DENIED) { password_dialog_ok = dlg->exec(); if (!password_dialog_ok) { delete dlg; d->m_devName.clear(); return false; //the user canceled } // add/update the device user-name and password for authentication d->m_auth->setDeviceAuth(d->m_devName, dlg->username(), dlg->password()); status = sane_open(deviceName.toLatin1().constData(), &d->m_saneHandle); // store password in wallet on successful authentication if (dlg->keepPassword() && status != SANE_STATUS_ACCESS_DENIED) { QMap<QString, QString> entry; entry[QStringLiteral("username")] = dlg->username(); entry[QStringLiteral("password")] = dlg->password(); if (saneWallet) { saneWallet->writeMap(deviceName, entry); } } } if (status != SANE_STATUS_GOOD) { qDebug() << "sane_open(\"" << deviceName << "\", &handle) failed! status = " << sane_strstatus(status); d->m_auth->clearDeviceAuth(d->m_devName); d->m_devName.clear(); return false; } // update the device list if needed to get the vendor and model info if (d->m_findDevThread->devicesList().size() == 0) { d->m_findDevThread->start(); } else { // use the "old" existing list d->devListUpdated(); // if m_vendor is not updated it means that the list needs to be updated. if (d->m_vendor.isEmpty()) { d->m_findDevThread->start(); } } // Read the options (start with option 0 the number of parameters) optDesc = sane_get_option_descriptor(d->m_saneHandle, 0); if (optDesc == 0) { d->m_auth->clearDeviceAuth(d->m_devName); d->m_devName.clear(); return false; } QVarLengthArray<char> data(optDesc->size); status = sane_control_option(d->m_saneHandle, 0, SANE_ACTION_GET_VALUE, data.data(), &res); if (status != SANE_STATUS_GOOD) { d->m_auth->clearDeviceAuth(d->m_devName); d->m_devName.clear(); return false; } numSaneOptions = *reinterpret_cast<SANE_Word *>(data.data()); // read the rest of the options for (i = 1; i < numSaneOptions; ++i) { switch (KSaneOption::optionType(sane_get_option_descriptor(d->m_saneHandle, i))) { case KSaneOption::TYPE_DETECT_FAIL: d->m_optList.append(new KSaneOption(d->m_saneHandle, i)); break; case KSaneOption::TYPE_CHECKBOX: d->m_optList.append(new KSaneOptCheckBox(d->m_saneHandle, i)); break; case KSaneOption::TYPE_SLIDER: d->m_optList.append(new KSaneOptSlider(d->m_saneHandle, i)); break; case KSaneOption::TYPE_F_SLIDER: d->m_optList.append(new KSaneOptFSlider(d->m_saneHandle, i)); break; case KSaneOption::TYPE_COMBO: d->m_optList.append(new KSaneOptCombo(d->m_saneHandle, i)); break; case KSaneOption::TYPE_ENTRY: d->m_optList.append(new KSaneOptEntry(d->m_saneHandle, i)); break; case KSaneOption::TYPE_GAMMA: d->m_optList.append(new KSaneOptGamma(d->m_saneHandle, i)); break; case KSaneOption::TYPE_BUTTON: d->m_optList.append(new KSaneOptButton(d->m_saneHandle, i)); break; } } // do the connections of the option parameters for (i = 1; i < d->m_optList.size(); ++i) { //qDebug() << d->m_optList.at(i)->name(); connect(d->m_optList.at(i), SIGNAL(optsNeedReload()), d, SLOT(optReload())); connect(d->m_optList.at(i), SIGNAL(valsNeedReload()), d, SLOT(scheduleValReload())); if (d->m_optList.at(i)->needsPolling()) { //qDebug() << d->m_optList.at(i)->name() << " needs polling"; d->m_pollList.append(d->m_optList.at(i)); KSaneOptCheckBox *buttonOption = qobject_cast<KSaneOptCheckBox *>(d->m_optList.at(i)); if (buttonOption) { connect(buttonOption, SIGNAL(buttonPressed(QString,QString,bool)), this, SIGNAL(buttonPressed(QString,QString,bool))); } } }
SANE_Status sane_start (SANE_Handle handle) { char *mode_str; Ibm_Scanner *s = handle; SANE_Status status; struct ibm_window_data wbuf; struct measurements_units_page mup; DBG (11, ">> sane_start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return (status); } mode_str = s->val[OPT_MODE].s; s->xres = s->val[OPT_X_RESOLUTION].w; s->yres = s->val[OPT_Y_RESOLUTION].w; s->ulx = s->val[OPT_TL_X].w; s->uly = s->val[OPT_TL_Y].w; s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; s->brightness = s->val[OPT_BRIGHTNESS].w; s->contrast = s->val[OPT_CONTRAST].w; s->bpp = s->params.depth; if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->image_composition = IBM_BINARY_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->image_composition = IBM_DITHERED_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->image_composition = IBM_GRAYSCALE; } memset (&wbuf, 0, sizeof (wbuf)); /* next line commented out by mf */ /* _lto2b(sizeof(wbuf) - 8, wbuf.len); */ /* next line by mf */ _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */ _lto2b(s->xres, wbuf.x_res); _lto2b(s->yres, wbuf.y_res); _lto4b(s->ulx, wbuf.x_org); _lto4b(s->uly, wbuf.y_org); _lto4b(s->width, wbuf.width); _lto4b(s->length, wbuf.length); wbuf.image_comp = s->image_composition; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { if (wbuf.image_comp == IBM_GRAYSCALE) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */ if (wbuf.image_comp == IBM_DITHERED_MONOCHROME) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10; wbuf.brightness = 256 - (SANE_Byte) s->brightness; /* if (is50) wbuf.contrast = (SANE_Byte) s->contrast; else */ wbuf.contrast = 256 - (SANE_Byte) s->contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00; wbuf.brightness = (SANE_Byte) s->brightness; wbuf.contrast = (SANE_Byte) s->contrast; } wbuf.threshold = 0; wbuf.bits_per_pixel = s->bpp; wbuf.halftone_code = 2; /* diithering */ wbuf.halftone_id = 0x0A; /* 8x8 Bayer pattenr */ wbuf.pad_type = 3; wbuf.bit_ordering[0] = 0; wbuf.bit_ordering[1] = 7; /* modified by mf (it was 3) */ DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending SET WINDOW\n"); status = set_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (11, "sane_start: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending MODE SELECT\n"); memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); /* next lines by mf */ mup.adf_page_code = 0x26; mup.adf_parameter_length = 6; if (s->adf_state == ADF_ARMED) mup.adf_control = 1; else mup.adf_control = 0; /* end lines by mf */ status = mode_select (s->fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); return (SANE_STATUS_INVAL); } status = trigger_scan (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); /* next line introduced not to freeze xscanimage */ do_cancel(s); return status; } /* Wait for scanner to become ready to transmit data */ status = ibm_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; DBG (11, "<< sane_start\n"); return (SANE_STATUS_GOOD); }
static SANE_Status attach (const char *devnam, Ibm_Device ** devp) { SANE_Status status; Ibm_Device *dev; int fd; struct inquiry_data ibuf; struct measurements_units_page mup; struct ibm_window_data wbuf; size_t buf_size; char *str; DBG (11, ">> attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "attach: sending INQUIRY\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof(ibuf); /* next line by mf */ ibuf.byte2 = 2; status = inquiry (fd, &ibuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (ibuf.devtype != 6) { DBG (1, "attach: device \"%s\" is not a scanner\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } if (!( (strncmp ((char *)ibuf.vendor, "IBM", 3) ==0 && strncmp ((char *)ibuf.product, "2456", 4) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS420", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS410", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS430", 5) == 0) )) { DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } /* * Causes a problem with RICOH IS420 * Ignore this function ... seems to work ok * Suggested to George Murphy [email protected] by henning */ if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0 && strncmp((char *)ibuf.product, "IS420", 5) != 0) { DBG (3, "attach: sending OBJECT POSITION\n"); status = object_position (fd, OBJECT_POSITION_UNLOAD); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: OBJECT POSTITION failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } } memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); #if 0 DBG (3, "attach: sending MODE SELECT\n"); status = mode_select (fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif #if 0 DBG (3, "attach: sending MODE SENSE\n"); memset (&mup, 0, sizeof (mup)); status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif DBG (3, "attach: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET_WINDOW failed %d\n", status); sanei_scsi_close (fd); DBG (11, "<< attach\n"); return (SANE_STATUS_INVAL); } sanei_scsi_close (fd); dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "IBM"; str = malloc (16 + 1); memset (str, 0, sizeof (str)); strncpy (str, (char *)ibuf.product, sizeof(ibuf.product)); strncpy (str + sizeof(ibuf.revision), (char *)ibuf.revision, sizeof(ibuf.revision)); str[sizeof(ibuf.product) + sizeof(ibuf.revision)] = '\0'; dev->sane.model = str; dev->sane.type = "flatbed scanner"; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); dev->info.xres_default = _2btol(wbuf.x_res); dev->info.yres_default = _2btol(wbuf.y_res); dev->info.image_mode_default = wbuf.image_comp; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ /* I should make this into an option */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { dev->info.brightness_default = 256 - wbuf.brightness; /* if (is50) dev->info.contrast_default = wbuf.contrast; else */ dev->info.contrast_default = 256 - wbuf.contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { dev->info.brightness_default = wbuf.brightness; dev->info.contrast_default = wbuf.contrast; } /* da rivedere dev->info.adf_default = wbuf.adf_state; */ dev->info.adf_default = ADF_UNUSED; dev->info.adf_default = IBM_PAPER_USER_DEFINED; #if 1 dev->info.bmu = mup.bmu; dev->info.mud = _2btol(mup.mud); if (dev->info.mud == 0) { /* The Ricoh says it uses points as default Basic Measurement Unit */ /* but gives a Measurement Unit Divisor of zero */ /* So, we set it to the default (SCSI-standard) of 1200 */ /* with BMU in inches, i.e. 1200 points equal 1 inch */ dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; } #else dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; #endif DBG (5, "xres_default=%d\n", dev->info.xres_default); DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); DBG (5, "yres_default=%d\n", dev->info.yres_default); DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); DBG (5, "x_range.max=%d\n", dev->info.x_range.max); DBG (5, "y_range.max=%d\n", dev->info.y_range.max); DBG (5, "image_mode=%d\n", dev->info.image_mode_default); DBG (5, "brightness=%d\n", dev->info.brightness_default); DBG (5, "contrast=%d\n", dev->info.contrast_default); DBG (5, "adf_state=%d\n", dev->info.adf_default); DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (11, "<< attach\n"); return (SANE_STATUS_GOOD); }
/** Function Configs_Modify * @brief oyCMMapi8_s SANE scanner manipulation * * @version Oyranos: 0.1.10 * @since 2009/01/19 (Oyranos: 0.1.10) * @date 2009/08/21 * * \todo { Test } */ int Configs_Modify(oyConfigs_s * devices, oyOptions_s * options) { oyOption_s *version_opt = NULL; oyOption_s *version_opt_dev = NULL; oyConfig_s *device = NULL; int num_devices, g_error = 0; int call_sane_exit = 0; const char *command_list = NULL, *command_properties = NULL; oyAlloc_f allocateFunc = malloc; printf(PRFX "Entering %s(). Options:\n%s", __func__, oyOptions_GetText(options, oyNAME_NICK)); /* "error handling" section */ if (!devices || !oyConfigs_Count(devices)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n " "No devices given! Options:\n%s", _DBG_ARGS_, oyOptions_GetText(options, oyNAME_NICK) ); return 1; } /* "help" call section */ if (oyOptions_FindString(options, "command", "help") || !options || !oyOptions_Count(options)) { /** oyMSG_WARN should make shure our message is visible. */ ConfigsFromPatternUsage((oyStruct_s *) options); return 0; } num_devices = oyConfigs_Count(devices); command_list = oyOptions_FindString(options, "command", "list"); command_properties = oyOptions_FindString(options, "command", "properties"); /* Now we get some options [IN], and we already have some devices with * possibly already assigned options. Those provided through the input * oyOptions_s should take presedence over ::data & ::backend_core ones. * OTOH, all device_* options have a 1-1 relationship meaning if * one changes, probably all other should. So the simplest [naive] approach * would be to ignore all device_* options [IN] that are already in device. * Except from driver_version which has a special meaning. */ /* Handle "driver_version" option [IN] */ /* Check the first device to see if a positive driver_version is provided. */ /* If not, consult the input options */ device = oyConfigs_Get(devices, 0); version_opt_dev = oyConfig_Find(device, "driver_version"); if (version_opt_dev && oyOption_GetValueInt(version_opt_dev, 0) > 0) call_sane_exit = 0; else check_driver_version(options, &version_opt, &call_sane_exit); oyConfig_Release(&device); oyOption_Release(&version_opt_dev); if (command_list) { /* "list" call section */ int i; for (i = 0; i < num_devices; ++i) { const SANE_Device *device_context = NULL; SANE_Status status = SANE_STATUS_INVAL; oyOption_s *name_opt_dev = NULL, *handle_opt_dev = NULL, *context_opt_dev = NULL; const char *sane_name = NULL, *sane_model = NULL; int error = 0; device = oyConfigs_Get(devices, i); if(oyOptions_Count(*oyConfig_GetOptions(device,"backend_core"))) printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK)); if(oyOptions_Count(*oyConfig_GetOptions(device,"data"))) printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK)); /*Ignore device without a device_name*/ if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_name\" is missing from config object!"); oyConfig_Release(&device); g_error++; continue; } /*Handle "driver_version" option [OUT] */ version_opt_dev = oyConfig_Find(device, "driver_version"); if (!version_opt_dev && version_opt) oyOptions_MoveIn(*oyConfig_GetOptions(device,"backend_core"), &version_opt, -1); oyOption_Release(&version_opt_dev); /*Handle "device_context" option */ /*This is always provided by Configs_FromPattern() * [or should be alternatively by the user]. * Configs_Modify() will not scan for SANE devices * because it takes too long*/ context_opt_dev = oyConfig_Find(device, "device_context"); if (!context_opt_dev) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" option is missing!"); error = g_error = 1; } if (!error) { device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc); sane_name = device_context->name; sane_model = device_context->model; } /*Handle "oyNAME_NAME" option */ name_opt_dev = oyConfig_Find(device, "oyNAME_NAME"); if (!error && !name_opt_dev && oyOptions_Find(options, "oyNAME_NAME", oyNAME_PATTERN)) oyOptions_SetFromString(oyConfig_GetOptions(device,"backend_core"), CMM_BASE_REG OY_SLASH "oyNAME_NAME", sane_model, OY_CREATE_NEW); /*Handle "device_handle" option */ handle_opt_dev = oyConfig_Find(device, "device_handle"); if (!error && !handle_opt_dev) { oyPointer_s *handle_ptr = NULL; SANE_Handle h; status = sane_open(sane_name, &h); if (status == SANE_STATUS_GOOD) { handle_ptr = oyPointer_New(0); oyPointer_Set(handle_ptr, "SANE", "handle", (oyPointer)h, "sane_release_handle", sane_release_handle); oyOptions_MoveInStruct(oyConfig_GetOptions(device,"data"), CMM_BASE_REG OY_SLASH "device_handle", (oyStruct_s **) &handle_ptr, OY_CREATE_NEW); } else printf(PRFX "Unable to open sane device \"%s\": %s\n", sane_name, sane_strstatus(status)); } /*Create static rank_map, if not already there*/ if (!oyConfig_GetRankMap( device)) oyConfig_SetRankMap( device, _api8.rank_map ); /*Cleanup*/ oyConfig_Release(&device); oyOption_Release(&context_opt_dev); oyOption_Release(&name_opt_dev); oyOption_Release(&handle_opt_dev); } } else if (command_properties) { /* "properties" call section */ int i; /*Return a full list of scanner H/W & * SANE driver S/W color options * with the according rank map */ for (i = 0; i < num_devices; ++i) { SANE_Device *device_context = NULL; SANE_Status status = SANE_STATUS_INVAL; SANE_Handle device_handle; oyOption_s *name_opt_dev = NULL, *handle_opt_dev = NULL, *context_opt_dev = NULL; oyConfig_s *device_new = NULL; char *device_name = NULL; /* All previous device properties are considered obsolete * and a new device is created. Basic options are moved from * the old to new device */ device = oyConfigs_Get(devices, i); device_new = oyConfig_FromRegistration(CMM_BASE_REG, 0); printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK)); printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK)); /*Ignore device without a device_name*/ if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_name\" is NULL, or missing from config object!"); oyConfig_Release(&device); oyConfig_Release(&device_new); g_error++; continue; } /*Handle "driver_version" option [OUT] */ if (version_opt) { oyOption_s *tmp = oyOption_Copy(version_opt, 0); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &tmp, -1); } /* 1. Get the "device_name" from old device */ name_opt_dev = oyConfig_Find(device, "device_name"); device_name = oyOption_GetValueText(name_opt_dev, allocateFunc); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &name_opt_dev, -1); /* 2. Get the "device_context" from old device */ /* It should be there, see "list" call above */ context_opt_dev = oyConfig_Find(device, "device_context"); if (context_opt_dev) { device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc); if (device_context) { oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &context_opt_dev, -1); } else { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" is NULL!"); oyOption_Release(&context_opt_dev); g_error++; } } else { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" option is missing!"); g_error++; } /* 3. Get the scanner H/W properties from old device */ /* FIXME: we only recompute them, just in case they are not in old device */ if (device_context) { DeviceInfoFromContext_(device_context, oyConfig_GetOptions(device_new,"backend_core")); } /* 4. Get the "device_handle" from old device */ /* If not there, get one from SANE */ handle_opt_dev = oyConfig_Find(device, "device_handle"); if (handle_opt_dev) { oyPointer_s * oy_struct = (oyPointer_s*)oyOption_GetStruct( handle_opt_dev, oyOBJECT_POINTER_S ); device_handle = (SANE_Handle)oyPointer_GetPointer(oy_struct); oyPointer_Release( &oy_struct ); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &handle_opt_dev, -1); } else { printf(PRFX "Opening sane device \"%s\"..", device_name); fflush(NULL); status = sane_open( device_name, &device_handle ); if (status != SANE_STATUS_GOOD) printf("[FAIL: %s]\n", sane_strstatus(status)); else printf("[OK]\n"); } if (handle_opt_dev || status == SANE_STATUS_GOOD) { /* Use the device_handle to get the device color options */ ColorInfoFromHandle(device_handle, oyConfig_GetOptions(device_new,"backend_core")); /*5. Set the rank map*/ oyConfig_SetRankMap( device_new, _api8.rank_map ); } /*Cleanup*/ /* Remove old, add new device */ oyConfig_Release(&device); oyConfigs_ReleaseAt(devices, i); oyConfigs_MoveIn(devices, &device_new, -1); /*If we had to open a SANE device, we'll have to close it*/ if (status == SANE_STATUS_GOOD) { printf(PRFX "sane_close(%s)\n", device_name); sane_close(device_handle); } free(device_context); free(device_name); } } else { /*unsupported, wrong or no command */ SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n " "No supported commands in options:\n%s", _DBG_ARGS_, oyOptions_GetText(options, oyNAME_NICK) ); ConfigsFromPatternUsage((oyStruct_s *) options); g_error = 1; } /*Cleanup*/ if (call_sane_exit) { printf(PRFX "sane_exit()\n"); sane_exit(); } oyOption_Release(&version_opt); printf(PRFX "Leaving %s\n", __func__); return g_error; }