Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
 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);
 }
Пример #4
0
    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();
        }
    }
Пример #5
0
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*/
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
/** 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;
}
Пример #9
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));
}
Пример #10
0
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;
}
Пример #11
0
/* 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;
}
Пример #12
0
/**
 * 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);
}
Пример #13
0
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");
}
Пример #14
0
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();
}
Пример #15
0
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;
}
Пример #16
0
/*! \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);
}
Пример #17
0
/* 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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
/* 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);
}
Пример #22
0
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();
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
/*! \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;
}
Пример #26
0
/*
 * 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;
}
Пример #27
0
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)));
            }
        }
    }
Пример #28
0
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); 
}
Пример #29
0
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);
}
Пример #30
0
/** 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;
}