Esempio n. 1
0
/* Open device, return the device handle */
SANE_Status
sane_open (SANE_String_Const devname, SANE_Handle * handle)
{
  unsigned i, j, id = 0;
  struct scanner *s;
  SANE_Int h, bus;
  SANE_Status st = SANE_STATUS_GOOD;
  if (!devlist)
    {
      st = sane_get_devices (NULL, 0);
      if (st)
	return st;
    }
  for (i = 0; devlist[i]; i++)
    {
      if (!strcmp (devlist[i]->name, devname))
	break;
    }
  if (!devlist[i])
    return SANE_STATUS_INVAL;
  for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++)
    {
      if (!strcmp (devlist[i]->model, known_devices[j].scanner.model))
	{
	  id = known_devices[j].id;
	  break;
	}
    }

  st = sanei_usb_open (devname, &h);

  if (st == SANE_STATUS_ACCESS_DENIED)
    return st;
  if (st)
    {
      st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL);
      if (st)
	{
	  return st;
	}
      bus = SCSI;
    }
  else
    {
      bus = USB;
      st = sanei_usb_claim_interface (h, 0);
      if (st)
	{
	  sanei_usb_close (h);
	  return st;
	}
    }

  s = malloc (sizeof (struct scanner));
  if (!s)
    return SANE_STATUS_NO_MEM;
  memset (s, 0, sizeof (struct scanner));
  s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE);
  if (!s->buffer)
    return SANE_STATUS_NO_MEM;

  s->file = h;
  s->bus = bus;
  s->id = id;
  strcpy (s->name, devname);
  *handle = s;
  for (i = 0; i < 3; i++)
    {
      st = kvs40xx_test_unit_ready (s);
      if (st)
	{
	  if (s->bus == SCSI)
	    {
	      sanei_scsi_close (s->file);
	      st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL);
	      if (st)
		return st;
	    }
	  else
	    {
	      sanei_usb_release_interface (s->file, 0);
	      sanei_usb_close (s->file);
	      st = sanei_usb_open (devname, &h);
	      if (st)
		return st;
	      st = sanei_usb_claim_interface (h, 0);
	      if (st)
		{
		  sanei_usb_close (h);
		  return st;
		}
	    }
	  s->file = h;
	}
      else
	break;
    }
  if (i == 3)
    return SANE_STATUS_DEVICE_BUSY;

  if (id == KV_S4085C || id == KV_S4065C)
    {
      char str[16];
      st = inquiry (s, str);
      if (st)
	goto err;
      if (id == KV_S4085C)
	s->id = !strcmp (str, "KV-S4085CL") ? KV_S4085CL : KV_S4085CW;
      else
	s->id = !strcmp (str, "KV-S4065CL") ? KV_S4065CL : KV_S4065CW;
    }
  kvs40xx_init_options (s);
  st = kvs40xx_set_timeout (s, s->val[FEED_TIMEOUT].w);
  if (st)
    goto err;

  return SANE_STATUS_GOOD;
err:
  sane_close (s);
  return st;
}
Esempio n. 2
0
/* Control option */
SANE_Status
sane_control_option (SANE_Handle handle, SANE_Int option,
		     SANE_Action action, void *val, SANE_Int * info)
{
  int i;
  SANE_Status status;
  SANE_Word cap;
  struct scanner *s = (struct scanner *) handle;

  if (info)
    *info = 0;

  if (option < 0 || option >= NUM_OPTIONS)
    return SANE_STATUS_UNSUPPORTED;

  cap = s->opt[option].cap;
  if (!SANE_OPTION_IS_ACTIVE (cap))
    return SANE_STATUS_UNSUPPORTED;

  if (action == SANE_ACTION_GET_VALUE)
    {
      if (s->opt[option].type == SANE_TYPE_STRING)
	{
	  DBG (DBG_INFO,
	       "sane_control_option: reading opt[%d] =  %s\n",
	       option, s->val[option].s);
	  strcpy (val, s->val[option].s);
	}
      else
	{
	  *(SANE_Word *) val = s->val[option].w;
	  DBG (DBG_INFO,
	       "sane_control_option: reading opt[%d] =  %d\n",
	       option, s->val[option].w);
	}
      return SANE_STATUS_GOOD;

    }
  else if (action == SANE_ACTION_SET_VALUE)
    {
      if (!SANE_OPTION_IS_SETTABLE (cap))
	return SANE_STATUS_INVAL;

      status = sanei_constrain_value (s->opt + option, val, info);
      if (status != SANE_STATUS_GOOD)
	return status;

      if (s->opt[option].type == SANE_TYPE_STRING)
	{
	  if (!strcmp (val, s->val[option].s))
	    return SANE_STATUS_GOOD;
	  DBG (DBG_INFO,
	       "sane_control_option: writing opt[%d] =  %s\n",
	       option, (SANE_String_Const) val);
	}
      else
	{
	  if (*(SANE_Word *) val == s->val[option].w)
	    return SANE_STATUS_GOOD;
	  DBG (DBG_INFO,
	       "sane_control_option: writing opt[%d] =  %d\n",
	       option, *(SANE_Word *) val);
	}

      switch (option)
	{
	  /* Side-effect options */
	case RESOLUTION:
	  s->val[option].w = *(SANE_Word *) val;
	  if (info)
	    *info |= SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;

	case TL_Y:
	  if ((*(SANE_Word *) val) + MIN_LENGTH <=
	      s->val[BR_Y].w &&
	      !check_area (s, s->val[TL_X].w, *(SANE_Word *) val,
			   s->val[BR_X].w, s->val[BR_Y].w))
	    {
	      s->val[option].w = *(SANE_Word *) val;
	      if (info)
		*info |= SANE_INFO_RELOAD_PARAMS;
	    }
	  else if (info)
	    *info |= SANE_INFO_INEXACT |
	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;
	case BR_Y:
	  if ((*(SANE_Word *) val) >=
	      s->val[TL_Y].w + MIN_LENGTH
	      && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
			      s->val[BR_X].w, *(SANE_Word *) val))
	    {
	      s->val[option].w = *(SANE_Word *) val;
	      if (info)
		*info |= SANE_INFO_RELOAD_PARAMS;
	    }
	  else if (info)
	    *info |= SANE_INFO_INEXACT |
	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;

	case TL_X:
	  if ((*(SANE_Word *) val) + MIN_WIDTH <=
	      s->val[BR_X].w &&
	      !check_area (s, *(SANE_Word *) val, s->val[TL_Y].w,
			   s->val[BR_X].w, s->val[BR_Y].w))
	    {
	      s->val[option].w = *(SANE_Word *) val;
	      if (info)
		*info |= SANE_INFO_RELOAD_PARAMS;
	    }
	  else if (info)
	    *info |= SANE_INFO_INEXACT |
	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;

	case BR_X:
	  if (*(SANE_Word *) val >=
	      s->val[TL_X].w + MIN_WIDTH
	      && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
			      *(SANE_Word *) val, s->val[BR_Y].w))
	    {
	      s->val[option].w = *(SANE_Word *) val;
	      if (info)
		*info |= SANE_INFO_RELOAD_PARAMS;
	    }
	  else if (info)
	    *info |= SANE_INFO_INEXACT |
	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;

	case LANDSCAPE:
	  s->val[option].w = *(SANE_Word *) val;
	  if (info)
	    *info |= SANE_INFO_RELOAD_PARAMS;
	  return SANE_STATUS_GOOD;

	  /* Side-effect free options */
	case CONTRAST:
	case BRIGHTNESS:
	case DUPLEX:
	case LENGTHCTL:
	case LONG_PAPER:
	case FIT_TO_PAGE:
	case THRESHOLD:
	case INVERSE:
	case COMPRESSION_PAR:
	case DFSTOP:
	case DFEED_L:
	case DFEED_C:
	case DFEED_R:
	case STOP_SKEW:
	case DESKEW:
	case MIRROR:
	case CROP:
	case TOPPOS:
	case BTMPOS:
	case RED_CHROMA:
	case BLUE_CHROMA:
	  s->val[option].w = *(SANE_Word *) val;
	  return SANE_STATUS_GOOD;

	case FEED_TIMEOUT:
	  s->val[option].w = *(SANE_Word *) val;
	  return kvs40xx_set_timeout (s, s->val[option].w);

	  /* String mode */
	case IMAGE_EMPHASIS:
	case GAMMA_CORRECTION:
	case LAMP:
	case HALFTONE_PATTERN:
	case DFEED_SENCE:
	case AUTOMATIC_THRESHOLD:
	case WHITE_LEVEL:
	case NOISE_REDUCTION:
	  strcpy (s->val[option].s, val);
	  return SANE_STATUS_GOOD;

	case SOURCE:
	  strcpy (s->val[option].s, val);
	  if (strcmp (s->val[option].s, SANE_I18N ("adf")))
	    {
	      strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
	      strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
	      s->val[DUPLEX].w = SANE_FALSE;
	      s->val[DBLFEED].w = SANE_FALSE;
	      s->val[BTMPOS].w = SANE_FALSE;
	      s->val[TOPPOS].w = SANE_FALSE;
	      s->val[STOP_SKEW].w = SANE_FALSE;
	      s->val[LENGTHCTL].w = SANE_FALSE;
	      s->val[LONG_PAPER].w = SANE_FALSE;
	      s->opt[FEEDER_MODE].cap |= SANE_CAP_INACTIVE;
	      s->opt[MANUALFEED].cap |= SANE_CAP_INACTIVE;
	      s->opt[DUPLEX].cap |= SANE_CAP_INACTIVE;
	      s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
	      s->opt[BTMPOS].cap |= SANE_CAP_INACTIVE;
	      s->opt[TOPPOS].cap |= SANE_CAP_INACTIVE;
	      s->opt[STOP_SKEW].cap |= SANE_CAP_INACTIVE;
	      s->opt[LENGTHCTL].cap |= SANE_CAP_INACTIVE;
	      s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[FEEDER_MODE].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[MANUALFEED].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DUPLEX].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[BTMPOS].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[TOPPOS].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[STOP_SKEW].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[LENGTHCTL].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;

	case FEEDER_MODE:
	  strcpy (s->val[option].s, val);
	  if (strcmp (s->val[option].s, SANE_I18N ("continuous")))
	    {
	      s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;

	case MODE:
	  strcpy (s->val[option].s, val);
	  if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART))
	    {
	      s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
	      s->opt[COMPRESSION].cap |= SANE_CAP_INACTIVE;
	      s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
	      s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;

	      s->opt[AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[RED_CHROMA].cap |= SANE_CAP_INACTIVE;
	      s->opt[BLUE_CHROMA].cap |= SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[COMPRESSION].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;

	      s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE;
	      s->opt[INVERSE].cap |= SANE_CAP_INACTIVE;
	      s->opt[HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;

	      s->opt[AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE;
	      s->opt[WHITE_LEVEL].cap |= SANE_CAP_INACTIVE;
	      s->opt[NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE;
	      s->opt[RED_CHROMA].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[BLUE_CHROMA].cap &= ~SANE_CAP_INACTIVE;
	    }

	  if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY))
	    {
	      s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;

	      s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
	    }

	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;

	  return SANE_STATUS_GOOD;

	case MANUALFEED:
	  strcpy (s->val[option].s, val);
	  if (strcmp (s->val[option].s, manual_feed_list[0]) == 0)	/* off */
	    s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
	  else
	    s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE;
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;

	case STAPELED_DOC:
	  strcpy (s->val[option].s, val);
	  if (strcmp (s->val[option].s, stapeled_list[0]) == 0)
	    {
	      s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;

	case DBLFEED:
	  s->val[option].w = *(SANE_Word *) val;
	  if (!s->val[option].b)
	    {
	      s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
	      s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;

	case PAPER_SIZE:
	  strcpy (s->val[option].s, val);
	  i = str_index (paper_list, s->val[option].s);
	  if (i == 0)
	    {			/*user def */
	      s->opt[TL_X].cap &=
		s->opt[TL_Y].cap &=
		s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE;
	      s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
	      s->val[LANDSCAPE].w = 0;
	    }
	  else
	    {
	      s->opt[TL_X].cap |=
		s->opt[TL_Y].cap |=
		s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE;
	      if ( /*i == 4 || */ i == 5 || i == 6 /*XXX*/
		  || i == 10 || i == 11)
		{		/*A4, A5, A6, B5, B6 */
		  if ((s->id == KV_S4085CL || s->id == KV_S4065CL)
		      && i == 4 && i == 10)
		    {		/*A4, B5 */
		      s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
		      s->val[LANDSCAPE].w = 0;
		    }
		  else
		    s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE;
		}
	      else
		{
		  s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
		  s->val[LANDSCAPE].w = 0;
		}
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;

	  return SANE_STATUS_GOOD;

	case COMPRESSION:
	  s->val[option].w = *(SANE_Word *) val;
	  if (!s->val[option].b)
	    {
	      s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
	    }
	  else
	    {
	      s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;
	    }
	  if (info)
	    *info |= SANE_INFO_RELOAD_OPTIONS;

	  return SANE_STATUS_GOOD;
	}
    }


  return SANE_STATUS_UNSUPPORTED;
}