[sane-devel] Plans for an updated avision backend (HP7400+HP5300+Minolta Scan Dual II+???)

Martin Jelínek mates@sirrah.troja.mff.cuni.cz
Wed, 14 Nov 2001 15:05:20 +0100


--5vNYLRcllDrimb99
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Oh no!

Once more, now with attachment.

m.

Martin Jelínek, Wed Nov 14, 2001 at 02:58:
> I attach a attach.c source with parsed output at debug level 3, raw bytes
> moved to debug level 5.
> 
> mates
> 
> Jose Paulo Moitinho de Almeida, Wed Nov 14, 2001 at 11:20:
> > On Tuesday 13 November 2001 20:49, you wrote:
> > 
> > > > Hi all friends of avision!
> > >
> > > So, I applied changes, the hp7400 is in lowercase -> a little modification,
> > > otherwise, the inquiry result is (partially parsed) attached.
> > >
> > > The basic resolution of scanner is reported to be 1200, Ex res. is reported
> > > 2400.
> > >
> > 
> > Hello
> > 
> > I liked your parsed output! We can add a vector with (at least) the comments 
> > for each byte, and put it front of the formated numbers!
> > 
> > Regarding bytes 77 to 88 I had the idea that pixels should be used as units, 
> > ie where the specs say (units: inches*300) we must read (units: 
> > inches*max_res).  You got the right dimensions. Did you change the code?
> > 
> > Regards
> > 
> > Ze Paulo
> _______________________________________________
> Sane-devel mailing list
> Sane-devel@www.mostang.com
> http://www.mostang.com/mailman/listinfo/sane-devel

--5vNYLRcllDrimb99
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="attach-parsed.c"

static SANE_Status
attach (const char* devname, Avision_Device** devp)
{
  unsigned char result [INQ_LEN];
  int fd;
  Avision_Device* dev;
  SANE_Status status;
  size_t size;

  char mfg[9];
  char model[17];
  char rev[5];
  
  int i;

  double x_range;
  double y_range;
  
  DBG (3, "attach\n");

  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;
  
  /* copy string information - and build zero terminated c-strings */
  memcpy (&mfg, result + 8, 8);
  mfg [8] = 0;
  memcpy (&model, result + 16, 16);
  model [16] = 0;
  memcpy (&rev, result + 32, 4);
  rev [4] = 0;
  
  // shorten strings ( -1 for last index; -1 for last 0; >0 becasue one char at least))
  for (i = sizeof (mfg) - 2; i > 0; i--) {
    if (mfg[i] == 0x20)
      mfg[i] = 0;
    else
      break;
  }
  for (i = sizeof (model) - 2; i > 0; i--) {
    if (model[i] == 0x20)
      model[i] = 0;
    else
      break;
  }
  
  DBG (1, "attach: Inquiry gives mfg=%s, model=%s, product revision=%s.\n", &mfg, &model, &rev);
  
  if (strcmp (mfg, "AVISION") != 0 &&
      strcmp (mfg, "HP") != 0 &&
      strcmp (mfg, "hp") != 0 &&
      strcmp (mfg, "MINOLTA") != 0)
    {
      DBG (1, "attach: device doesn't look like an AVISION (or OEM) scanner!\n");
      return SANE_STATUS_INVAL;
    }
  
  if (strcmp (model, "AV630CS") != 0 &&
      strcmp (model, "AV620CS") != 0 &&
      strcmp (model, "ScanJet 5370C") != 0 &&
      strcmp (model, "scanjet 7400c") != 0 &&
      strcmp (model, "FS-V1") != 0)
    {
      DBG (1, "attach: model is not in the list of supported model!\n");
      DBG (1, "attach  You might want to report this output.\n");
      return SANE_STATUS_INVAL;
    }
  
  dev = malloc (sizeof (*dev));
  if (!dev)
    return SANE_STATUS_NO_MEM;
  
  memset (dev, 0x0, sizeof (*dev));

  dev->sane.name   = strdup (devname);
  dev->sane.vendor = strdup (mfg);
  dev->sane.model  = strdup (model);
  if (strcmp (model, "FS-V1") != 0)
    {
      dev->sane.type   = "flatbed scanner";
    }
  else
    {
      /* The coolscan backend says "slide scanner", the canon says "film scanner"
         deciding on a name would be useful? */
      dev->sane.type   = "slide scanner";
    }

# define BIT(n, p)  ((n & ( 1 << p))?1:0)
  for (i=0; i<sizeof(result); i++) {
    DBG (6, "result[%3d] %1d%1d%1d%1d%1d%1d%1d%1db %3oo %3dd %2xx\n", i, BIT(result[i],7), 
         BIT(result[i],6), BIT(result[i],5), BIT(result[i],4), BIT(result[i],3), BIT(result[i],2),
         BIT(result[i],1), BIT(result[i],0), result[i], result[i], result[i]);
  }
  
  DBG (3, "attach: [8-15]  Vendor id.:    \"%8.8s\"\n", result+8);
  DBG (3, "attach: [16-31] Product id.:   \"%8.8s\"\n", result+16);
  DBG (3, "attach: [32-35] Product rev.:  \"%4.4s\"\n", result+32);
// [36]
  DBG (3, "attach: [37]    Optical res.:    %d00dpi\n", result[37]);
  DBG (3, "attach: [38]    Maximum res.:    %d00dpi\n", result[38]);
// [39]  
  DBG (3, "attach: [40-41] X res. in gray:  %ddpi\n", (result[40]<<8)+result[41]);
  DBG (3, "attach: [42-43] Y res. in gray:  %ddpi\n", (result[42]<<8)+result[43]);
  DBG (3, "attach: [44-45] X res. in color: %ddpi\n", (result[44]<<8)+result[45]);
  DBG (3, "attach: [46-47] Y res. in color: %ddpi\n", (result[46]<<8)+result[47]);
  DBG (3, "attach: [48-49] USB max read:    %d\n", (result[48]<<8)+result[49]);

  DBG (3, "attach: [50]    ESA1:%s%s%s%s%s%s%s%s\n",
  	BIT(result[50],7)?" LIGHT":"",
  	BIT(result[50],6)?" BUTTON":"",
  	BIT(result[50],5)?" NEED_SW_COLORPACK":"",
  	BIT(result[50],4)?" SW_CALIB":"",
  	BIT(result[50],3)?" NEED_SW_GAMMA":"",
  	BIT(result[50],2)?" KEEPS_GAMMA":"",
  	BIT(result[50],1)?" KEEPS_WINDOW_CMD":"",
  	BIT(result[50],0)?" XYRES_DIFFERENT":"");
  DBG (3, "attach: [51]    ESA2:%s%s%s%s%s%s%s%s\n",
  	BIT(result[51],7)?" EXPOSURE_CTRL":"",
  	BIT(result[51],6)?" NEED_SW_TRIGGER_CAL":"",
  	BIT(result[51],5)?" NEED_WHITE_PAPER":"",
  	BIT(result[51],4)?" SUPP_QUALITY_SPEED_CAL":"",
  	BIT(result[51],3)?" NEED_TRANSP_CAL":"",
  	BIT(result[51],2)?" HAS_PUSH_BUTTON":"",
  	BIT(result[51],1)?" NEW_CAL_METHOD":"",
  	BIT(result[51],0)?" ADF_MIRRORS":"");
  DBG (3, "attach: [52]    ESA3:%s%s%s%s%s%s%s\n",
  	BIT(result[52],7)?" GRAY_WHITE":"",
  	BIT(result[52],5)?" TET":"",
  	BIT(result[52],4)?" 3x3COL_TABLE":"",
  	BIT(result[52],3)?" 1x3FILTER":"",
  	BIT(result[52],2)?" INDEX_COLOR":"",
  	BIT(result[52],1)?" POWER_SAVING_TIMER":"",
  	BIT(result[52],0)?" NVM_DATA_REC":"");
   
  /* print some more scanner features/params */
  DBG (3, "attach: [53]    line difference (software color pack): %d\n", result[53]);
  DBG (3, "attach: [54]    color mode pixel boundary: %d\n", result[54]);
  DBG (3, "attach: [55]    grey mode pixel boundary: %d\n", result[55]);
  
  DBG (3, "attach: [60]    channels per pixel:%s%s\n",
  	BIT(result[60],7)?" 1":"",
  	BIT(result[60],6)?" 3":"");
  DBG (3, "attach: [61]    bits per channel:%s%s%s%s%s%s%s\n", 
  	BIT(result[61],7)?" 1":"",
  	BIT(result[61],6)?" 4":"",
  	BIT(result[61],5)?" 6":"",
  	BIT(result[61],4)?" 8":"",
  	BIT(result[61],3)?" 10":"",
  	BIT(result[61],2)?" 12":"",
  	BIT(result[61],1)?" 16":"");
  DBG (3, "attach: [89-90] Res. in Ex. mode: %ddpi\n", (result[89]<<8)+result[90]);
  
  /* Get max X and max Y ...*/
  /* Instead of dividing by 300 I would divide by  
     ( optical_resolution = ((unsigned int)result[89] << 8) + (unsigned int)result[90] )
     I would assume that the document is not correct.
     For my scanner optical_resolution is (11<<8+4)=2820
     Is this correct for other scanners? The 7400 does 2400dpi I think. What values are reported?
  */
  x_range = ( ( ( (unsigned int)result[81] << 8) + (unsigned int)result[82] ) / 300 ) * MM_PER_INCH;
  y_range = ( ( ( (unsigned int)result[83] << 8) + (unsigned int)result[84] ) / 300 ) * MM_PER_INCH;
  dev->x_range.max = SANE_FIX (x_range);
  dev->y_range.max = SANE_FIX (y_range);
  
  dev->x_range.quant = 0;
  dev->y_range.quant = 0;
  
  dev->dpi_range.min = 50;
  dev->dpi_range.quant = 1;
  dev->dpi_range.max = 1200; /* Change as above? */

  DBG (3, "attach: found AVISION scanner model %s (%s)\n", dev->sane.model, dev->sane.type);
  DBG (3, "        X-Range: %fmm, Y-Range: %fmm (Raw-Range: %d, %d, %d, %d)\n",
       SANE_UNFIX (dev->x_range.max),
       SANE_UNFIX (dev->y_range.max),
       (int)result[81], (int)result[82], (int)result[83], (int)result[84]);
  
  DBG (5, "RAW.Result:\n");
  for (i = 0; i < sizeof (result); i++)
    {
      DBG (5, "[%d]:%x->""%c""\n", i, (unsigned char) result[i], result[i]);
    }
  
  /* check if x/y range is vaild :-((( */

  /* These checks are very  dangerous for a negative (24x36 mm!!) 
     What is the best approach? Use dev->sane.type or a variable? 
     Then use a large if that controls this ? */

  if (dev->x_range.max == 0 || dev->y_range.max == 0)
    {
      DBG (1, "Inquiry x/y-range is invaild! Using defauld %fx%finch (ISO A4).\n", MAX_X_RANGE, MAX_Y_RANGE);
      dev->x_range.max = SANE_FIX (MAX_X_RANGE * MM_PER_INCH);
      dev->y_range.max = SANE_FIX (MAX_Y_RANGE * MM_PER_INCH);
    }
  else
    DBG (3, "Inquiry x/y-range is vaild?!?\n");
  
  if (force_a4)
    {
      DBG (1, "option: \"force_a4\" found! Using defauld %fx%finch (ISO A4).\n",
	   MAX_X_RANGE, MAX_Y_RANGE);
      dev->x_range.max = SANE_FIX (MAX_X_RANGE * MM_PER_INCH);
      dev->y_range.max = SANE_FIX (MAX_Y_RANGE * MM_PER_INCH);
    }
  
  ++num_devices;
  dev->next = first_dev;
  first_dev = dev;

  if (devp)
    *devp = dev;
  return SANE_STATUS_GOOD;
}



--5vNYLRcllDrimb99--