Ejemplo n.º 1
0
static SANE_Status
get_image_status (Tamarack_Scanner *s)
{
  uint8_t result[12];
  SANE_Status status;
  size_t len;
  int busy;

#if 1
  do
    {
      len = sizeof (result);
      status = sanei_scsi_cmd (s->fd, get_status, sizeof (get_status),
			    result, &len);
      if ((status != SANE_STATUS_GOOD) && (status != SANE_STATUS_DEVICE_BUSY))
	return status;

      busy = (result[2] != 8) || (status == SANE_STATUS_DEVICE_BUSY);
      if (busy)
	usleep (100000);

      if (!s->scanning)
	return do_cancel (s);
    }
  while (busy);
#else
  /* XXX Test if this works one day... */
  wait_ready (s);
#endif

  len = sizeof (result);
  status = sanei_scsi_cmd (s->fd, get_status, sizeof (get_status),
			   result, &len);
  if ((status != SANE_STATUS_GOOD) && (status != SANE_STATUS_DEVICE_BUSY))
    return status;
  
  s->params.bytes_per_line = 
    result[ 8] | (result[ 7] << 8) | (result[6] << 16);
  s->params.lines = 
    result[11] | (result[10] << 8) | (result[9] << 16);

  switch (s->mode) {
  case DITHERED:
  case THRESHOLDED:
    s->params.pixels_per_line = 8 * s->params.bytes_per_line;
    break;
  case GREYSCALE:
  case TRUECOLOR:
    s->params.pixels_per_line =     s->params.bytes_per_line;
    break;
  }


  DBG(1, "get_image_status: bytes_per_line=%d, lines=%d\n",
      s->params.bytes_per_line, s->params.lines);
  return SANE_STATUS_GOOD;
}
Ejemplo n.º 2
0
static SANE_Status
send_command (struct scanner * s, struct cmd * c)
{
  SANE_Status st = SANE_STATUS_GOOD;
  if (s->bus == USB)
    {
      struct response r;
      memset (&r, 0, sizeof (r));
      st = usb_send_command (s, c, &r, s->buffer);
      if (st)
	return st;
      if (r.status)
	{
	  u8 b[sizeof (struct bulk_header) + RESPONSE_SIZE];
	  struct cmd c2 = {
            {0},
	    6,
            0,
	    RESPONSE_SIZE,
	    CMD_IN
	  };
	  c2.cmd[0] = REQUEST_SENSE;
	  c2.cmd[4] = RESPONSE_SIZE;
	  st = usb_send_command (s, &c2, &r, b);
	  if (st)
	    return st;
	  st = kvs20xx_sense_handler (0, b + sizeof (struct bulk_header), NULL);
	}
    }
  else
    {
      if (c->dir == CMD_OUT)
	{
	  memcpy (s->buffer, c->cmd, c->cmd_size);
	  memcpy (s->buffer + c->cmd_size, c->data, c->data_size);
	  st = sanei_scsi_cmd (s->file, s->buffer, c->cmd_size + c->data_size,
			       NULL, NULL);
	}
      else if (c->dir == CMD_IN)
	{
	  c->data = s->buffer;
	  st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size,
			       c->data, (size_t *) & c->data_size);
	}
      else
	{
	  st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, NULL, NULL);
	}
    }
  return st;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
static SANE_Status
read_data (Tamarack_Scanner *s, SANE_Byte *buf, int lines, int bpl)
{
  struct command_header_10 cmd;
  size_t nbytes;
  SANE_Status status;
#ifdef DEBUG
  int dt;
  struct timeval tv_start,tv_end;
#endif

  nbytes = bpl * lines;
  memset (&cmd,'\0',sizeof (cmd));
  cmd.opc = 0x28;
  set_triple (cmd.len,nbytes);

#ifdef DEBUG
  if (verbose) DBG (1, "Doing read_data... \n");
  gettimeofday (&tv_start,NULL);
#endif

  status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, &nbytes);

#ifdef DEBUG
  gettimeofday (&tv_end,NULL);
  dt =  tv_end.tv_usec - tv_start.tv_usec +
       (tv_end.tv_sec  - tv_start.tv_sec) * 1000000;
  if (verbose) DBG(1, "Read took %d.%06d seconds.",
		   dt/1000000,dt%1000000);
  dt = 1000000 * nbytes / dt;
  if (verbose) DBG(1, "which is %d.%03d bytes per second.\n",dt,0);
#endif
  return status;
}
Ejemplo n.º 5
0
static SANE_Status
mode_select (Tamarack_Scanner *s)
{
  struct  {
    struct command_header cmd;
    struct page_header hdr;
    struct tamarack_page page;
  } c;

  memset (&c, '\0', sizeof (c));  
  c.cmd.opc = TAMARACK_SCSI_MODE_SELECT;
  c.cmd.pad0[0] = 0x10;    /* Suddenly the pad bytes are no long pad... */
  c.cmd.pad0[1] = 0;
  c.cmd.len = sizeof (struct page_header) + sizeof (struct tamarack_page);
  c.hdr.code = 0;
  c.hdr.length = 6;
  c.page.gamma = 2;
  c.page.thresh = 0x80;    /* XXX Option? */
  switch (s->mode) {
  case THRESHOLDED:
  case DITHERED:
  case GREYSCALE:
    c.page.masks = 0x80;   
    break;
  case TRUECOLOR:
    c.page.masks = 0x40 >> s->pass;
    break;
  }
  c.page.delay = 0x10;      /* XXX Option? */
  c.page.features = (s->val[OPT_TRANS].w ? TAM_TRANS_ON:0) | 1;
  return sanei_scsi_cmd (s->fd, &c, sizeof (c), 0, 0);
}
Ejemplo n.º 6
0
static SANE_Status
stop_scan (Tamarack_Scanner *s)
{ 
  /* XXX I don't think a TAMARACK can stop in mid-scan. Just stop
     sending it requests for data.... 
   */
  return sanei_scsi_cmd (s->fd, stop, sizeof (stop), 0, 0);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
static SANE_Status
start_scan (Tamarack_Scanner *s)
{
  struct  {
    struct command_header cmd;
    unsigned char winid[1];
  } c;
  
  memset (&c,'\0',sizeof (c));
  c.cmd.opc = TAMARACK_SCSI_START_STOP;
  c.cmd.len = sizeof (c.winid);
  c.winid[0] = WINID;
  return sanei_scsi_cmd (s->fd, &c, sizeof (c), 0, 0);
}
Ejemplo n.º 9
0
static SANE_Status
start_scan (Abaton_Scanner * s)
{
  SANE_Status status;
  uint8_t start[7];


  memset (start, 0, sizeof (start));
  start[0] = START_STOP;
  start[4] = 1;

  status = sanei_scsi_cmd (s->fd, start, sizeof (start), 0, 0);
  return status;
}
Ejemplo n.º 10
0
SANE_Status
sanei_epson_scsi_inquiry (int fd, int page_code, void *buf, size_t * buf_size)
{
  u_char cmd[6];
  int status;

  memset (cmd, 0, 6);
  cmd[0] = INQUIRY_COMMAND;
  cmd[2] = page_code;
  cmd[4] = *buf_size > 255 ? 255 : *buf_size;
  status = sanei_scsi_cmd (fd, cmd, sizeof cmd, buf, buf_size);

  return status;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
static SANE_Status
request_sense (Abaton_Scanner * s)
{
  uint8_t cmd[6];
  uint8_t result[22];
  size_t size = sizeof (result);
  SANE_Status status;

  memset (cmd, 0, sizeof (cmd));
  memset (result, 0, sizeof (result));

  cmd[0] = REQUEST_SENSE;
  STORE8 (cmd + 4, sizeof (result));
  sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), result, &size);

  if (result[7] != 14)
    {
      DBG (ERROR_MESSAGE, "Additional Length %u\n", (unsigned int) result[7]);
      status = SANE_STATUS_IO_ERROR;
    }


  status = sense_handler (s->fd, result, NULL);
  if (status == SANE_STATUS_IO_ERROR)
    {

      /* Since I haven't figured out the vendor unique error codes on
	 this thing, I'll just handle the normal ones for now */

      if (result[18] & 0x80)
	DBG (ERROR_MESSAGE, "Sense: Dim Light (output of lamp below 70%%).\n");

      if (result[18] & 0x40)
	DBG (ERROR_MESSAGE, "Sense: No Light at all.\n");

      if (result[18] & 0x20)
	DBG (ERROR_MESSAGE, "Sense: No Home.\n");

      if (result[18] & 0x10)
	DBG (ERROR_MESSAGE, "Sense: No Limit. Tried to scan out of range.\n");
    }

  DBG (USER_MESSAGE, "Sense: Optical gain %u.\n", (unsigned int) result[20]);
  return status;
}
Ejemplo n.º 14
0
int
sanei_epson_scsi_read (int fd, void *buf, size_t buf_size,
		       SANE_Status * status)
{
  u_char cmd[6];

  memset (cmd, 0, 6);
  cmd[0] = READ_6_COMMAND;
  cmd[2] = buf_size >> 16;
  cmd[3] = buf_size >> 8;
  cmd[4] = buf_size;

  if (SANE_STATUS_GOOD ==
      (*status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, &buf_size)))
    return buf_size;

  return 0;
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
SANE_Status
sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
	   SANE_Int * len)
{
  Abaton_Scanner *s = handle;
  SANE_Status status;

  uint8_t get_data_status[10];
  uint8_t read[10];

  uint8_t result[12];
  size_t size;
  SANE_Int data_av = 0;
  SANE_Int data_length = 0;
  SANE_Int offset = 0;
  SANE_Int rread = 0;
  SANE_Bool Pseudo8bit = SANE_FALSE;


  *len = 0;

  /* don't let bogus read requests reach the scanner */
  /* this is a sub-optimal way of doing this, I'm sure */
  if (!s->scanning)
    return SANE_STATUS_EOF;
  
  if (!strcmp (s->val[OPT_MODE].s, "Gray16"))
    Pseudo8bit = SANE_TRUE;

  memset (get_data_status, 0, sizeof (get_data_status));
  get_data_status[0] = GET_DATA_STATUS;
  /* This means "block" for Apple scanners, it seems to be the same
     for Abaton.  The scanner will do non-blocking I/O, but I don't
     want to go there right now. */
  get_data_status[1] = 1;
  STORE8 (get_data_status + 8, sizeof (result));

  memset (read, 0, sizeof (read));
  read[0] = READ_10;

  do
    {
      size = sizeof (result);
      /* this isn't necessary */
      /*  memset (result, 0, size); */
      status = sanei_scsi_cmd (s->fd, get_data_status,
			       sizeof (get_data_status), result, &size);

      if (status != SANE_STATUS_GOOD)
	return status;
      if (!size)
	{
	  DBG (ERROR_MESSAGE, "sane_read: cannot get_data_status.\n");
	  return SANE_STATUS_IO_ERROR;
	}

      /* this is not an accurate name, but oh well... */
      data_length = GET24 (result);
      data_av = GET24 (result + 9);

      /* don't check result[3] here, because that screws things up
	 somewhat */
      if (data_length) {
	DBG (IO_MESSAGE,
	     "sane_read: (status) Available in scanner buffer %u.\n",
	     data_av);

	if (Pseudo8bit)
	  {
	    if ((data_av * 2) + offset > max_len)
	      rread = (max_len - offset) / 2;
	    else
	      rread = data_av;
	  }
	else if (data_av + offset > max_len)
	  {
	    rread = max_len - offset;
	  }
	else
	  {
	    rread = data_av;
	  }
	
	DBG (IO_MESSAGE,
	     "sane_read: (action) Actual read request for %u bytes.\n",
	     rread);

	size = rread;
      
	STORE24 (read + 6, rread);

	status = sanei_scsi_cmd (s->fd, read, sizeof (read),
				 buf + offset, &size);

	if (Pseudo8bit)
	  {
	    SANE_Int byte;
	    SANE_Int pos = offset + (rread << 1) - 1;
	    SANE_Byte B;
	    for (byte = offset + rread - 1; byte >= offset; byte--)
	      {
		B = buf[byte];
		/* don't invert these! */
		buf[pos--] = B << 4;   /* low (right) nibble */
		buf[pos--] = B & 0xF0; /* high (left) nibble */
	      }
	    /* putting an end to bitop abuse here */
	    offset += size * 2;
	  }
	else
	  offset += size;

	DBG (IO_MESSAGE, "sane_read: Buffer %u of %u full %g%%\n",
	     offset, max_len, (double) (offset * 100. / max_len));
      }
    }
  while (offset < max_len && data_length != 0 && !s->AbortedByUser);

  if (s->AbortedByUser)
    {
      s->scanning = SANE_FALSE;

      if (status != SANE_STATUS_GOOD)
	{
	  DBG (ERROR_MESSAGE, "sane_read: request_sense revealed error: %s\n",
	       sane_strstatus (status));
	  return status;
	}

      status = sanei_scsi_cmd (s->fd, test_unit_ready,
			       sizeof (test_unit_ready), 0, 0);
      if (status != SANE_STATUS_GOOD || status != SANE_STATUS_INVAL)
	return status;
      return SANE_STATUS_CANCELLED;
    }

  if (!data_length)
    {
      s->scanning = SANE_FALSE;
      DBG (IO_MESSAGE, "sane_read: (status) No more data...");
      if (!offset)
	{
	  /* this shouldn't happen */
	  *len = 0;
	  DBG (IO_MESSAGE, "EOF\n");
	  return SANE_STATUS_EOF;
	}
      else
	{
	  *len = offset;
	  DBG (IO_MESSAGE, "GOOD\n");
	  return SANE_STATUS_GOOD;
	}
    }


  DBG (FLOW_CONTROL,
       "sane_read: Normal Exiting, Aborted=%u, data_length=%u\n",
       s->AbortedByUser, data_av);
  *len = offset;

  return SANE_STATUS_GOOD;
}
Ejemplo n.º 17
0
static SANE_Status
set_window (Abaton_Scanner * s)
{
  uint8_t cmd[10 + 40];
  uint8_t *window = cmd + 10 + 8;
  int invert;
  
  memset (cmd, 0, sizeof (cmd));
  cmd[0] = SET_WINDOW;
  cmd[8] = 40;

  /* Just like the Apple scanners, we put the resolution here */
  STORE16 (window + 2, s->val[OPT_X_RESOLUTION].w);
  STORE16 (window + 4, s->val[OPT_Y_RESOLUTION].w);

  /* Unlike Apple scanners, these are pixel values */
  STORE16 (window + 6, s->ULx);
  STORE16 (window + 8, s->ULy);
  STORE16 (window + 10, s->Width);
  STORE16 (window + 12, s->Height);

  STORE8 (window + 14, s->val[OPT_BRIGHTNESS].w);
  STORE8 (window + 15, s->val[OPT_THRESHOLD].w);
  STORE8 (window + 16, s->val[OPT_CONTRAST].w);

  invert = s->val[OPT_NEGATIVE].w;

  if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART))
    {
      STORE8 (window + 17, 0);
    }
  else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE))
    {
      STORE8 (window + 17, 1);
    }
  else if (!strcmp (s->val[OPT_MODE].s, "Gray256")
	   || !strcmp (s->val[OPT_MODE].s, "Gray16"))
    {
      STORE8 (window + 17, 2);
      invert = !s->val[OPT_NEGATIVE].w;
    }
  else
    {
      DBG (ERROR_MESSAGE, "Can't match mode %s\n", s->val[OPT_MODE].s);
      return SANE_STATUS_INVAL;
    }

  STORE8 (window + 18, s->bpp);

  if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral"))
    {
      STORE8 (window + 20, 0);
    }
  else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer"))
    {
      STORE8 (window + 20, 1);
    }
  else
    {
      DBG (ERROR_MESSAGE, "Can't match haftone pattern %s\n",
	   s->val[OPT_HALFTONE_PATTERN].s);
      return SANE_STATUS_INVAL;
    }
  
  /* We have to invert these ones for some reason, so why not
     let the scanner do it for us... */
  STORE8 (window + 21, invert ? 0x80 : 0);
  
  STORE16 (window + 22, (s->val[OPT_MIRROR].w != 0));

  return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
}
Ejemplo n.º 18
0
static SANE_Status
attach (const char *devname, Abaton_Device ** devp, int may_wait)
{
  char result[INQ_LEN];
  const char *model_name = result + 44;
  int fd, abaton_scanner;
  Abaton_Device *dev;
  SANE_Status status;
  size_t size;

  for (dev = first_dev; dev; dev = dev->next)
    if (strcmp (dev->sane.name, devname) == 0)
      {
	if (devp)
	  *devp = dev;
	return SANE_STATUS_GOOD;
      }

  DBG (USER_MESSAGE, "attach: opening %s\n", devname);
  status = sanei_scsi_open (devname, &fd, sense_handler, 0);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (ERROR_MESSAGE, "attach: open failed (%s)\n",
	   sane_strstatus (status));
      return SANE_STATUS_INVAL;
    }

  if (may_wait)
    wait_ready (fd);

  DBG (USER_MESSAGE, "attach: sending INQUIRY\n");
  size = sizeof (result);
  status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (ERROR_MESSAGE, "attach: inquiry failed (%s)\n",
	   sane_strstatus (status));
      sanei_scsi_close (fd);
      return status;
    }

  status = wait_ready (fd);
  sanei_scsi_close (fd);
  if (status != SANE_STATUS_GOOD)
    return status;

  /* check that we've got an Abaton */
  abaton_scanner = (strncmp (result + 8, "ABATON  ", 8) == 0);
  model_name = result + 16;

  /* make sure it's a scanner ;-) */
  abaton_scanner = abaton_scanner && (result[0] == 0x06);

  if (!abaton_scanner)
    {
      DBG (ERROR_MESSAGE, "attach: device doesn't look like an Abaton scanner "
	   "(result[0]=%#02x)\n", result[0]);
      return SANE_STATUS_INVAL;
    }

  dev = malloc (sizeof (*dev));
  if (!dev)
    return SANE_STATUS_NO_MEM;

  memset (dev, 0, sizeof (*dev));

  dev->sane.name = strdup (devname);
  dev->sane.vendor = "Abaton";
  dev->sane.model = strndup (model_name, 16);
  dev->sane.type = "flatbed scanner";

  if (!strncmp (model_name, "SCAN 300/GS", 11))
    {
      dev->ScannerModel = ABATON_300GS;
    }
  else if (!strncmp (model_name, "SCAN 300/S", 10))
    {
      dev->ScannerModel = ABATON_300S;
    }

  DBG (USER_MESSAGE, "attach: found Abaton scanner model %s (%s)\n",
       dev->sane.model, dev->sane.type);

  ++num_devices;
  dev->next = first_dev;
  first_dev = dev;

  if (devp)
    *devp = dev;

  return SANE_STATUS_GOOD;
}
Ejemplo n.º 19
0
static SANE_Status
st400_inquiry( int fd, ST400_Model **modelP )
{
	struct { SANE_Byte cmd, lun, reserved[2], tr_len, ctrl; } scsi_cmd;
/*
	struct {
		SANE_Byte devtype, devqual, version;
		SANE_Byte reserved1, additionallength;
		SANE_Byte reserved2[2], flags;
		SANE_Byte vendor[8], product[16], release[4];
		SANE_Byte reserved3[60];
	} inqdata;
*/
	struct { SANE_Byte bytes[96]; } inqdata;

	size_t inqlen;
	SANE_Status status;
	ST400_Model *model;

	inqlen = sizeof(inqdata);
	memset(&scsi_cmd, 0, sizeof(scsi_cmd));
	scsi_cmd.cmd = CMD_INQUIRY;
	scsi_cmd.tr_len = inqlen;

	DBG(DSCSI, "SCSI: sending INQUIRY (%lu bytes)\n", (u_long)inqlen);
	status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), &inqdata, &inqlen);
	DBG(DSCSI, "SCSI: result=%s (%lu bytes)\n", sane_strstatus(status), (u_long)inqlen);
	if( status != SANE_STATUS_GOOD )
		return status;

	if( st400_dump_data ) {
		const char *home = getenv ("HOME");
		char basename[] = "st400.dump";
		char *name;
		FILE *fp;

		if (home) {
			name = malloc (strlen (home) + sizeof (basename) + 1);
			sprintf (name, "%s/%s", home, basename);
		} else name = basename;

		fp = fopen(name, "ab");
		if( fp != NULL ) {
			fwrite(inqdata.bytes, 1, inqlen, fp);
			fclose(fp);
		}

		if (name != basename)
			free (name);
	}

	if( inqlen != sizeof(inqdata) )
		return SANE_STATUS_IO_ERROR;

	for( model = st400_models; model->inq_vendor; model++ ) {
		if( str_at_offset(model->inq_vendor, model->inq_voffset, inqdata.bytes) && str_at_offset(model->inq_model, model->inq_moffset, inqdata.bytes) ) {
			*modelP = model;
			DBG(DINFO, "found matching scanner model \"%s %s\" in list\n", model->sane_vendor, model->sane_model);
			return SANE_STATUS_GOOD;
		}
	}

	return SANE_STATUS_UNSUPPORTED;
}
Ejemplo n.º 20
0
static SANE_Status
attach (const char *devname, Tamarack_Device **devp)
{
  char result[INQ_LEN];
  int fd;
  Tamarack_Device *dev;
  SANE_Status status;
  size_t size;
  char *mfg, *model;
  char *p;

  for (dev = first_dev; dev; dev = dev->next)
    if (strcmp (dev->sane.name, devname) == 0) {
      if (devp)
	*devp = dev;
      return SANE_STATUS_GOOD;
    }

  DBG(3, "attach: opening %s\n", devname);
  status = sanei_scsi_open (devname, &fd, sense_handler, 0);
  if (status != SANE_STATUS_GOOD) {
    DBG(1, "attach: open failed (%s)\n", sane_strstatus (status));
    return SANE_STATUS_INVAL;
  }

  DBG(3, "attach: sending INQUIRY\n");
  size = sizeof (result);
  status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size);
  if (status != SANE_STATUS_GOOD || size != INQ_LEN) {
    DBG(1, "attach: inquiry failed (%s)\n", sane_strstatus (status));
    sanei_scsi_close (fd);
    return status;
  }

  status = wait_ready (fd);
  sanei_scsi_close (fd);
  if (status != SANE_STATUS_GOOD)
    return status;

  result[33]= '\0';
  p = strchr(result+16,' ');
  if (p) *p = '\0';
  model = strdup (result+16);

  result[16]= '\0';
  p = strchr(result+8,' ');
  if (p) *p = '\0';
  mfg = strdup (result+8);

  DBG(1, "attach: Inquiry gives mfg=%s, model=%s.\n", mfg, model);
  
  if (strcmp (mfg, "TAMARACK") != 0) {
    DBG(1, "attach: device doesn't look like a Tamarack scanner "
	   "(result[0]=%#02x)\n", result[0]);
    return SANE_STATUS_INVAL;
  }
  
  dev = malloc (sizeof (*dev));
  if (!dev)
    return SANE_STATUS_NO_MEM;
  
  memset (dev, 0, sizeof (*dev));

  dev->sane.name   = strdup (devname);
  dev->sane.vendor = "Tamarack";
  dev->sane.model  = model;
  dev->sane.type   = "flatbed scanner";

  dev->x_range.min = 0;
  dev->y_range.min = 0;
  dev->x_range.quant = 0;
  dev->y_range.quant = 0;
  dev->dpi_range.min = SANE_FIX (1);
  dev->dpi_range.quant = SANE_FIX (1);

  dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH);
  dev->y_range.max = SANE_FIX (11.0 * MM_PER_INCH);
  dev->dpi_range.max = SANE_FIX (600);

  DBG(3, "attach: found Tamarack scanner model %s (%s)\n",
      dev->sane.model, dev->sane.type);

  ++num_devices;
  dev->next = first_dev;
  first_dev = dev;

  if (devp)
    *devp = dev;
  return SANE_STATUS_GOOD;
}
Ejemplo n.º 21
0
static SANE_Status
scan_area_and_windows (Tamarack_Scanner *s)
{
  struct def_win_par dwp;

  memset (&dwp,'\0',sizeof (dwp));
  dwp.dwph.opc = TAMARACK_SCSI_AREA_AND_WINDOWS;
  set_triple (dwp.dwph.len,8 + sizeof (dwp.wdb)); 

  set_double (dwp.wdh.wpll, sizeof (dwp.wdb));

  dwp.wdb.winid = WINID;
  set_double (dwp.wdb.xres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w));
  set_double (dwp.wdb.yres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w));

  set_quad (dwp.wdb.ulx, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_X].w)));
  set_quad (dwp.wdb.uly, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_Y].w)));
  set_quad (dwp.wdb.width, 
     (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w)));
  set_quad (dwp.wdb.length,
     (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w)));

  dwp.wdb.brightness = sign_mag (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w));
  dwp.wdb.contrast   = sign_mag (SANE_UNFIX (s->val[OPT_CONTRAST].w));
  dwp.wdb.thresh     = 0x80;


  switch (s->mode) {
  case THRESHOLDED:
    dwp.wdb.bpp = 1;
    dwp.wdb.image_comp = 0;
    dwp.wdb.thresh     = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); 
    break;
  case DITHERED:
    dwp.wdb.bpp = 1;
    dwp.wdb.image_comp = 1;
    break;
  case GREYSCALE:
    dwp.wdb.bpp = 8;
    dwp.wdb.image_comp = 2;
    break;
  case TRUECOLOR:
    dwp.wdb.bpp = 8;
    dwp.wdb.image_comp = 2;
    break;
  default:
    DBG(1, "Invalid mode. %d\n", s->mode);
    return SANE_STATUS_INVAL;
  }
  DBG(1, "bright, thresh, contrast = %d(%5.1f), %d, %d(%5.1f)\n", 
      dwp.wdb.brightness, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w),
      dwp.wdb.thresh    ,
      dwp.wdb.contrast  , SANE_UNFIX (s->val[OPT_CONTRAST].w));

  set_double (dwp.wdb.halftone, 1); /* XXX What does this do again ? */
  dwp.wdb.pad_type   = 3;           /* This is the only usable pad-type. */
  dwp.wdb.exposure   = 0x6f;        /* XXX Option? */
  dwp.wdb.compr_type = 0;

  /* XXX Shouldn't this be sizeof (dwp) */
  return sanei_scsi_cmd (s->fd, &dwp, (10+8+38), 0, 0);
}