1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 1997 Geoffrey T. Dairiki
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci   This file is part of a SANE backend for HP Scanners supporting
40141cc406Sopenharmony_ci   HP Scanner Control Language (SCL).
41141cc406Sopenharmony_ci*/
42141cc406Sopenharmony_ci
43141cc406Sopenharmony_ci/*#define STUBS
44141cc406Sopenharmony_ciextern int sanei_debug_hp;*/
45141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY
46141cc406Sopenharmony_ci#include "../include/sane/config.h"
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci#include <stdlib.h>
49141cc406Sopenharmony_ci#include <string.h>
50141cc406Sopenharmony_ci#include "../include/lassert.h"
51141cc406Sopenharmony_ci#include "hp-device.h"
52141cc406Sopenharmony_ci#include "hp-accessor.h"
53141cc406Sopenharmony_ci#include "hp-option.h"
54141cc406Sopenharmony_ci#include "hp-scsi.h"
55141cc406Sopenharmony_ci#include "hp-scl.h"
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ci/* Mark an scl-command to be simulated */
58141cc406Sopenharmony_ciSANE_Status
59141cc406Sopenharmony_cisanei_hp_device_simulate_set (const char *devname, HpScl scl, int flag)
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_ci{HpDeviceInfo *info;
62141cc406Sopenharmony_ci int inqid;
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( devname );
65141cc406Sopenharmony_ci if (!info) return SANE_STATUS_INVAL;
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN;
68141cc406Sopenharmony_ci info->simulate.sclsimulate[inqid] = flag;
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci DBG(3, "hp_device_simulate_set: %d set to %ssimulated\n",
71141cc406Sopenharmony_ci     inqid+HP_SCL_INQID_MIN, flag ? "" : "not ");
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_ci return SANE_STATUS_GOOD;
74141cc406Sopenharmony_ci}
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci/* Clear all simulation flags */
77141cc406Sopenharmony_civoid
78141cc406Sopenharmony_cisanei_hp_device_simulate_clear (const char *devname)
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_ci{HpDeviceInfo *info;
81141cc406Sopenharmony_ci
82141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( devname );
83141cc406Sopenharmony_ci if (!info) return;
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_ci memset (&(info->simulate.sclsimulate[0]), 0,
86141cc406Sopenharmony_ci         sizeof (info->simulate.sclsimulate));
87141cc406Sopenharmony_ci
88141cc406Sopenharmony_ci info->simulate.gamma_simulate = 0;
89141cc406Sopenharmony_ci}
90141cc406Sopenharmony_ci
91141cc406Sopenharmony_ci/* Get simulate flag for an scl-command */
92141cc406Sopenharmony_cihp_bool_t
93141cc406Sopenharmony_cisanei_hp_device_simulate_get (const char *devname, HpScl scl)
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_ci{HpDeviceInfo *info;
96141cc406Sopenharmony_ci int inqid;
97141cc406Sopenharmony_ci
98141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( devname );
99141cc406Sopenharmony_ci if (!info) return 0;
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN;
102141cc406Sopenharmony_ci return info->simulate.sclsimulate[inqid];
103141cc406Sopenharmony_ci}
104141cc406Sopenharmony_ci
105141cc406Sopenharmony_ciSANE_Status
106141cc406Sopenharmony_cisanei_hp_device_support_get (const char *devname, HpScl scl,
107141cc406Sopenharmony_ci                             int *minval, int *maxval)
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci{HpDeviceInfo *info;
110141cc406Sopenharmony_ci HpSclSupport *sclsupport;
111141cc406Sopenharmony_ci int inqid;
112141cc406Sopenharmony_ci
113141cc406Sopenharmony_ci/* #define HP_TEST_SIMULATE */
114141cc406Sopenharmony_ci#ifdef HP_TEST_SIMULATE
115141cc406Sopenharmony_ci  if (scl == SCL_BRIGHTNESS) return SANE_STATUS_UNSUPPORTED;
116141cc406Sopenharmony_ci  if (scl == SCL_CONTRAST) return SANE_STATUS_UNSUPPORTED;
117141cc406Sopenharmony_ci  if (scl == SCL_DOWNLOAD_TYPE)
118141cc406Sopenharmony_ci  {
119141cc406Sopenharmony_ci     *minval = 2; *maxval = 14;
120141cc406Sopenharmony_ci     return SANE_STATUS_GOOD;
121141cc406Sopenharmony_ci  }
122141cc406Sopenharmony_ci#endif
123141cc406Sopenharmony_ci
124141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( devname );
125141cc406Sopenharmony_ci if (!info) return SANE_STATUS_INVAL;
126141cc406Sopenharmony_ci
127141cc406Sopenharmony_ci inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN;
128141cc406Sopenharmony_ci sclsupport = &(info->sclsupport[inqid]);
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_ci if ( !(sclsupport->checked) ) return SANE_STATUS_INVAL;
131141cc406Sopenharmony_ci if ( !(sclsupport->is_supported) ) return SANE_STATUS_UNSUPPORTED;
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_ci if (minval) *minval = sclsupport->minval;
134141cc406Sopenharmony_ci if (maxval) *maxval = sclsupport->maxval;
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_ci return SANE_STATUS_GOOD;
137141cc406Sopenharmony_ci}
138141cc406Sopenharmony_ci
139141cc406Sopenharmony_ci/* Update the list of supported commands */
140141cc406Sopenharmony_ciSANE_Status
141141cc406Sopenharmony_cisanei_hp_device_support_probe (HpScsi scsi)
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_ci{HpDeviceInfo *info;
144141cc406Sopenharmony_ci HpSclSupport *sclsupport;
145141cc406Sopenharmony_ci SANE_Status status;
146141cc406Sopenharmony_ci int k, val, inqid;
147141cc406Sopenharmony_ci static HpScl sclprobe[] =  /* The commands that should be probed */
148141cc406Sopenharmony_ci {
149141cc406Sopenharmony_ci   SCL_AUTO_BKGRND,
150141cc406Sopenharmony_ci   SCL_COMPRESSION,
151141cc406Sopenharmony_ci   SCL_DOWNLOAD_TYPE,
152141cc406Sopenharmony_ci   SCL_X_SCALE,
153141cc406Sopenharmony_ci   SCL_Y_SCALE,
154141cc406Sopenharmony_ci   SCL_DATA_WIDTH,
155141cc406Sopenharmony_ci   SCL_INVERSE_IMAGE,
156141cc406Sopenharmony_ci   SCL_BW_DITHER,
157141cc406Sopenharmony_ci   SCL_CONTRAST,
158141cc406Sopenharmony_ci   SCL_BRIGHTNESS,
159141cc406Sopenharmony_ci#ifdef SCL_SHARPENING
160141cc406Sopenharmony_ci   SCL_SHARPENING,
161141cc406Sopenharmony_ci#endif
162141cc406Sopenharmony_ci   SCL_MIRROR_IMAGE,
163141cc406Sopenharmony_ci   SCL_X_RESOLUTION,
164141cc406Sopenharmony_ci   SCL_Y_RESOLUTION,
165141cc406Sopenharmony_ci   SCL_OUTPUT_DATA_TYPE,
166141cc406Sopenharmony_ci   SCL_PRELOAD_ADF,
167141cc406Sopenharmony_ci   SCL_MEDIA,
168141cc406Sopenharmony_ci   SCL_X_EXTENT,
169141cc406Sopenharmony_ci   SCL_Y_EXTENT,
170141cc406Sopenharmony_ci   SCL_X_POS,
171141cc406Sopenharmony_ci   SCL_Y_POS,
172141cc406Sopenharmony_ci   SCL_SPEED,
173141cc406Sopenharmony_ci   SCL_FILTER,
174141cc406Sopenharmony_ci   SCL_TONE_MAP,
175141cc406Sopenharmony_ci   SCL_MATRIX,
176141cc406Sopenharmony_ci   SCL_UNLOAD,
177141cc406Sopenharmony_ci   SCL_CHANGE_DOC,
178141cc406Sopenharmony_ci   SCL_ADF_BFEED
179141cc406Sopenharmony_ci };
180141cc406Sopenharmony_ci enum hp_device_compat_e compat;
181141cc406Sopenharmony_ci
182141cc406Sopenharmony_ci DBG(1, "hp_device_support_probe: Check supported commands for %s\n",
183141cc406Sopenharmony_ci     sanei_hp_scsi_devicename (scsi) );
184141cc406Sopenharmony_ci
185141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) );
186141cc406Sopenharmony_ci assert (info);
187141cc406Sopenharmony_ci
188141cc406Sopenharmony_ci memset (&(info->sclsupport[0]), 0, sizeof (info->sclsupport));
189141cc406Sopenharmony_ci
190141cc406Sopenharmony_ci for (k = 0; k < (int)(sizeof (sclprobe) / sizeof (sclprobe[0])); k++)
191141cc406Sopenharmony_ci {
192141cc406Sopenharmony_ci   inqid = SCL_INQ_ID(sclprobe[k])-HP_SCL_INQID_MIN;
193141cc406Sopenharmony_ci   sclsupport = &(info->sclsupport[inqid]);
194141cc406Sopenharmony_ci   status = sanei_hp_scl_inquire (scsi, sclprobe[k], &val,
195141cc406Sopenharmony_ci                                  &(sclsupport->minval),
196141cc406Sopenharmony_ci                                  &(sclsupport->maxval));
197141cc406Sopenharmony_ci   sclsupport->is_supported = (status == SANE_STATUS_GOOD);
198141cc406Sopenharmony_ci   sclsupport->checked = 1;
199141cc406Sopenharmony_ci
200141cc406Sopenharmony_ci   /* The OfficeJets seem to ignore brightness and contrast settings,
201141cc406Sopenharmony_ci    * so we'll pretend they're not supported at all. */
202141cc406Sopenharmony_ci   if (((sclprobe[k]==SCL_BRIGHTNESS) || (sclprobe[k]==SCL_CONTRAST)) &&
203141cc406Sopenharmony_ci       (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) &&
204141cc406Sopenharmony_ci       (compat & HP_COMPAT_OJ_1150C)) {
205141cc406Sopenharmony_ci	 sclsupport->is_supported=0;
206141cc406Sopenharmony_ci   }
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_ci   if (sclsupport->is_supported)
209141cc406Sopenharmony_ci   {
210141cc406Sopenharmony_ci     DBG(1, "hp_device_support_probe: %d supported (%d..%d, %d)\n",
211141cc406Sopenharmony_ci         inqid+HP_SCL_INQID_MIN, sclsupport->minval, sclsupport->maxval, val);
212141cc406Sopenharmony_ci   }
213141cc406Sopenharmony_ci   else
214141cc406Sopenharmony_ci   {
215141cc406Sopenharmony_ci     DBG(1, "hp_device_support_probe: %d not supported\n",
216141cc406Sopenharmony_ci         inqid+HP_SCL_INQID_MIN);
217141cc406Sopenharmony_ci   }
218141cc406Sopenharmony_ci }
219141cc406Sopenharmony_ci
220141cc406Sopenharmony_ci return SANE_STATUS_GOOD;
221141cc406Sopenharmony_ci}
222141cc406Sopenharmony_ci
223141cc406Sopenharmony_ciSANE_Status
224141cc406Sopenharmony_cisanei_hp_device_probe_model (enum hp_device_compat_e *compat, HpScsi scsi,
225141cc406Sopenharmony_ci                             int *model_num, const char **model_name)
226141cc406Sopenharmony_ci{
227141cc406Sopenharmony_ci  static struct {
228141cc406Sopenharmony_ci      HpScl		cmd;
229141cc406Sopenharmony_ci      int               model_num;
230141cc406Sopenharmony_ci      const char *	model;
231141cc406Sopenharmony_ci      enum hp_device_compat_e	flag;
232141cc406Sopenharmony_ci  }	probes[] = {
233141cc406Sopenharmony_ci      { SCL_HP_MODEL_1, 1, "ScanJet Plus",             HP_COMPAT_PLUS },
234141cc406Sopenharmony_ci      { SCL_HP_MODEL_2, 2, "ScanJet IIc",              HP_COMPAT_2C },
235141cc406Sopenharmony_ci      { SCL_HP_MODEL_3, 3, "ScanJet IIp",              HP_COMPAT_2P },
236141cc406Sopenharmony_ci      { SCL_HP_MODEL_4, 4, "ScanJet IIcx",             HP_COMPAT_2CX },
237141cc406Sopenharmony_ci      { SCL_HP_MODEL_5, 5, "ScanJet 3c/4c/6100C",      HP_COMPAT_4C },
238141cc406Sopenharmony_ci      { SCL_HP_MODEL_6, 6, "ScanJet 3p",               HP_COMPAT_3P },
239141cc406Sopenharmony_ci      { SCL_HP_MODEL_8, 8, "ScanJet 4p",               HP_COMPAT_4P },
240141cc406Sopenharmony_ci      { SCL_HP_MODEL_9, 9, "ScanJet 5p/4100C/5100C",   HP_COMPAT_5P },
241141cc406Sopenharmony_ci      { SCL_HP_MODEL_10,10,"PhotoSmart Photo Scanner", HP_COMPAT_PS },
242141cc406Sopenharmony_ci      { SCL_HP_MODEL_11,11,"OfficeJet 1150C",          HP_COMPAT_OJ_1150C },
243141cc406Sopenharmony_ci      { SCL_HP_MODEL_12,12,"OfficeJet 1170C or later", HP_COMPAT_OJ_1170C },
244141cc406Sopenharmony_ci      { SCL_HP_MODEL_14,14,"ScanJet 62x0C",            HP_COMPAT_6200C },
245141cc406Sopenharmony_ci      { SCL_HP_MODEL_16,15,"ScanJet 5200C",            HP_COMPAT_5200C },
246141cc406Sopenharmony_ci      { SCL_HP_MODEL_17,17,"ScanJet 63x0C",            HP_COMPAT_6300C }
247141cc406Sopenharmony_ci  };
248141cc406Sopenharmony_ci  int		i;
249141cc406Sopenharmony_ci  char		buf[8];
250141cc406Sopenharmony_ci  SANE_Status	status;
251141cc406Sopenharmony_ci  static char	*last_device = NULL;
252141cc406Sopenharmony_ci  static enum hp_device_compat_e last_compat;
253141cc406Sopenharmony_ci  static int    last_model_num = -1;
254141cc406Sopenharmony_ci  static const char *last_model_name = "Model Unknown";
255141cc406Sopenharmony_ci
256141cc406Sopenharmony_ci  assert(scsi);
257141cc406Sopenharmony_ci  DBG(1, "probe_scanner: Probing %s\n", sanei_hp_scsi_devicename (scsi));
258141cc406Sopenharmony_ci
259141cc406Sopenharmony_ci  if (last_device != NULL)  /* Look if we already probed the device */
260141cc406Sopenharmony_ci  {
261141cc406Sopenharmony_ci    if (strcmp (last_device, sanei_hp_scsi_devicename (scsi)) == 0)
262141cc406Sopenharmony_ci    {
263141cc406Sopenharmony_ci      DBG(3, "probe_scanner: use cached compatibility flags\n");
264141cc406Sopenharmony_ci      *compat = last_compat;
265141cc406Sopenharmony_ci      if (model_num) *model_num = last_model_num;
266141cc406Sopenharmony_ci      if (model_name) *model_name = last_model_name;
267141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
268141cc406Sopenharmony_ci    }
269141cc406Sopenharmony_ci    sanei_hp_free (last_device);
270141cc406Sopenharmony_ci    last_device = NULL;
271141cc406Sopenharmony_ci  }
272141cc406Sopenharmony_ci  *compat = 0;
273141cc406Sopenharmony_ci  last_model_num = -1;
274141cc406Sopenharmony_ci  last_model_name = "Model Unknown";
275141cc406Sopenharmony_ci  for (i = 0; i < (int)(sizeof(probes)/sizeof(probes[0])); i++)
276141cc406Sopenharmony_ci    {
277141cc406Sopenharmony_ci      DBG(1,"probing %s\n",probes[i].model);
278141cc406Sopenharmony_ci
279141cc406Sopenharmony_ci      if (!FAILED( status = sanei_hp_scl_upload(scsi, probes[i].cmd,
280141cc406Sopenharmony_ci					  buf, sizeof(buf)) ))
281141cc406Sopenharmony_ci	{
282141cc406Sopenharmony_ci	  DBG(1, "probe_scanner: %s compatible (%5s)\n", probes[i].model, buf);
283141cc406Sopenharmony_ci          last_model_name = probes[i].model;
284141cc406Sopenharmony_ci          /* Some scanners have different responses */
285141cc406Sopenharmony_ci          if (probes[i].model_num == 9)
286141cc406Sopenharmony_ci          {
287141cc406Sopenharmony_ci            if (strncmp (buf, "5110A", 5) == 0)
288141cc406Sopenharmony_ci              last_model_name = "ScanJet 5p";
289141cc406Sopenharmony_ci            else if (strncmp (buf, "5190A", 5) == 0)
290141cc406Sopenharmony_ci              last_model_name = "ScanJet 5100C";
291141cc406Sopenharmony_ci            else if (strncmp (buf, "6290A", 5) == 0)
292141cc406Sopenharmony_ci              last_model_name = "ScanJet 4100C";
293141cc406Sopenharmony_ci          }
294141cc406Sopenharmony_ci	  *compat |= probes[i].flag;
295141cc406Sopenharmony_ci          last_model_num = probes[i].model_num;
296141cc406Sopenharmony_ci	}
297141cc406Sopenharmony_ci      else if (!UNSUPPORTED( status ))
298141cc406Sopenharmony_ci	  return status;	/* SCL inquiry failed */
299141cc406Sopenharmony_ci    }
300141cc406Sopenharmony_ci  /* Save values for next call */
301141cc406Sopenharmony_ci  last_device = sanei_hp_strdup (sanei_hp_scsi_devicename (scsi));
302141cc406Sopenharmony_ci  last_compat = *compat;
303141cc406Sopenharmony_ci  if (model_num) *model_num = last_model_num;
304141cc406Sopenharmony_ci  if (model_name) *model_name = last_model_name;
305141cc406Sopenharmony_ci
306141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
307141cc406Sopenharmony_ci}
308141cc406Sopenharmony_ci
309141cc406Sopenharmony_ciSANE_Status
310141cc406Sopenharmony_cisanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi)
311141cc406Sopenharmony_ci{
312141cc406Sopenharmony_ci  return sanei_hp_device_probe_model (compat, scsi, 0, 0);
313141cc406Sopenharmony_ci}
314141cc406Sopenharmony_ci
315141cc406Sopenharmony_cihp_bool_t
316141cc406Sopenharmony_cisanei_hp_device_compat (HpDevice this, enum hp_device_compat_e which)
317141cc406Sopenharmony_ci{
318141cc406Sopenharmony_ci  return (this->compat & which) != 0;
319141cc406Sopenharmony_ci}
320141cc406Sopenharmony_ci
321141cc406Sopenharmony_cistatic SANE_Status
322141cc406Sopenharmony_cihp_nonscsi_device_new (HpDevice * newp, const char * devname, HpConnect connect)
323141cc406Sopenharmony_ci{
324141cc406Sopenharmony_ci  HpDevice	this;
325141cc406Sopenharmony_ci  HpScsi	scsi;
326141cc406Sopenharmony_ci  SANE_Status	status;
327141cc406Sopenharmony_ci  const char *  model_name = "ScanJet";
328141cc406Sopenharmony_ci
329141cc406Sopenharmony_ci  if (FAILED( sanei_hp_nonscsi_new(&scsi, devname, connect) ))
330141cc406Sopenharmony_ci  {
331141cc406Sopenharmony_ci    DBG(1, "%s: Can't open nonscsi device\n", devname);
332141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Can't open device */
333141cc406Sopenharmony_ci  }
334141cc406Sopenharmony_ci
335141cc406Sopenharmony_ci  /* reset scanner; returns all parameters to defaults */
336141cc406Sopenharmony_ci  if (FAILED( sanei_hp_scl_reset(scsi) ))
337141cc406Sopenharmony_ci    {
338141cc406Sopenharmony_ci      DBG(1, "hp_nonscsi_device_new: SCL reset failed\n");
339141cc406Sopenharmony_ci      sanei_hp_scsi_destroy(scsi,1);
340141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
341141cc406Sopenharmony_ci    }
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_ci  /* Things seem okay, allocate new device */
344141cc406Sopenharmony_ci  this = sanei_hp_allocz(sizeof(*this));
345141cc406Sopenharmony_ci  this->data = sanei_hp_data_new();
346141cc406Sopenharmony_ci
347141cc406Sopenharmony_ci  if (!this || !this->data)
348141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
349141cc406Sopenharmony_ci
350141cc406Sopenharmony_ci  this->sanedev.name = sanei_hp_strdup(devname);
351141cc406Sopenharmony_ci  if (!this->sanedev.name)
352141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
353141cc406Sopenharmony_ci  this->sanedev.vendor = "Hewlett-Packard";
354141cc406Sopenharmony_ci  this->sanedev.type   = "flatbed scanner";
355141cc406Sopenharmony_ci
356141cc406Sopenharmony_ci  status = sanei_hp_device_probe_model (&(this->compat), scsi, 0, &model_name);
357141cc406Sopenharmony_ci  if (!FAILED(status))
358141cc406Sopenharmony_ci  {
359141cc406Sopenharmony_ci      sanei_hp_device_support_probe (scsi);
360141cc406Sopenharmony_ci      status = sanei_hp_optset_new(&(this->options), scsi, this);
361141cc406Sopenharmony_ci  }
362141cc406Sopenharmony_ci  sanei_hp_scsi_destroy(scsi,1);
363141cc406Sopenharmony_ci
364141cc406Sopenharmony_ci  if (!model_name) model_name = "ScanJet";
365141cc406Sopenharmony_ci  this->sanedev.model = sanei_hp_strdup (model_name);
366141cc406Sopenharmony_ci  if (!this->sanedev.model)
367141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
368141cc406Sopenharmony_ci
369141cc406Sopenharmony_ci  if (FAILED(status))
370141cc406Sopenharmony_ci    {
371141cc406Sopenharmony_ci      DBG(1, "hp_nonscsi_device_new: %s: probe failed (%s)\n",
372141cc406Sopenharmony_ci	  devname, sane_strstatus(status));
373141cc406Sopenharmony_ci      sanei_hp_data_destroy(this->data);
374141cc406Sopenharmony_ci      sanei_hp_free((void *)this->sanedev.name);
375141cc406Sopenharmony_ci      sanei_hp_free((void *)this->sanedev.model);
376141cc406Sopenharmony_ci      sanei_hp_free(this);
377141cc406Sopenharmony_ci      return status;
378141cc406Sopenharmony_ci    }
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_ci  DBG(1, "hp_nonscsi_device_new: %s: found HP ScanJet model %s\n",
381141cc406Sopenharmony_ci      devname, this->sanedev.model);
382141cc406Sopenharmony_ci
383141cc406Sopenharmony_ci  *newp = this;
384141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
385141cc406Sopenharmony_ci}
386141cc406Sopenharmony_ci
387141cc406Sopenharmony_ciSANE_Status
388141cc406Sopenharmony_cisanei_hp_device_new (HpDevice * newp, const char * devname)
389141cc406Sopenharmony_ci{
390141cc406Sopenharmony_ci  HpDevice	this;
391141cc406Sopenharmony_ci  HpScsi	scsi;
392141cc406Sopenharmony_ci  HpConnect     connect;
393141cc406Sopenharmony_ci  SANE_Status	status;
394141cc406Sopenharmony_ci  char *	str;
395141cc406Sopenharmony_ci
396141cc406Sopenharmony_ci  DBG(3, "sanei_hp_device_new: %s\n", devname);
397141cc406Sopenharmony_ci
398141cc406Sopenharmony_ci  connect = sanei_hp_get_connect (devname);
399141cc406Sopenharmony_ci  if ( connect != HP_CONNECT_SCSI )
400141cc406Sopenharmony_ci    return hp_nonscsi_device_new (newp, devname, connect);
401141cc406Sopenharmony_ci
402141cc406Sopenharmony_ci  if (FAILED( sanei_hp_scsi_new(&scsi, devname) ))
403141cc406Sopenharmony_ci    {
404141cc406Sopenharmony_ci      DBG(1, "%s: Can't open scsi device\n", devname);
405141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;	/* Can't open device */
406141cc406Sopenharmony_ci    }
407141cc406Sopenharmony_ci
408141cc406Sopenharmony_ci  if (sanei_hp_scsi_inq(scsi)[0] != 0x03
409141cc406Sopenharmony_ci      || memcmp(sanei_hp_scsi_vendor(scsi), "HP      ", 8) != 0)
410141cc406Sopenharmony_ci    {
411141cc406Sopenharmony_ci      DBG(1, "%s: does not seem to be an HP scanner\n", devname);
412141cc406Sopenharmony_ci      sanei_hp_scsi_destroy(scsi,1);
413141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
414141cc406Sopenharmony_ci    }
415141cc406Sopenharmony_ci
416141cc406Sopenharmony_ci  /* reset scanner; returns all parameters to defaults */
417141cc406Sopenharmony_ci  if (FAILED( sanei_hp_scl_reset(scsi) ))
418141cc406Sopenharmony_ci    {
419141cc406Sopenharmony_ci      DBG(1, "sanei_hp_device_new: SCL reset failed\n");
420141cc406Sopenharmony_ci      sanei_hp_scsi_destroy(scsi,1);
421141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
422141cc406Sopenharmony_ci    }
423141cc406Sopenharmony_ci
424141cc406Sopenharmony_ci  /* Things seem okay, allocate new device */
425141cc406Sopenharmony_ci  this = sanei_hp_allocz(sizeof(*this));
426141cc406Sopenharmony_ci  this->data = sanei_hp_data_new();
427141cc406Sopenharmony_ci
428141cc406Sopenharmony_ci  if (!this || !this->data)
429141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
430141cc406Sopenharmony_ci
431141cc406Sopenharmony_ci  this->sanedev.name = sanei_hp_strdup(devname);
432141cc406Sopenharmony_ci  str = sanei_hp_strdup(sanei_hp_scsi_model(scsi));
433141cc406Sopenharmony_ci  if (!this->sanedev.name || !str)
434141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
435141cc406Sopenharmony_ci  this->sanedev.model = str;
436141cc406Sopenharmony_ci  if ((str = strchr(str, ' ')) != 0)
437141cc406Sopenharmony_ci      *str = '\0';
438141cc406Sopenharmony_ci  this->sanedev.vendor = "Hewlett-Packard";
439141cc406Sopenharmony_ci  this->sanedev.type   = "flatbed scanner";
440141cc406Sopenharmony_ci
441141cc406Sopenharmony_ci  status = sanei_hp_device_probe(&(this->compat), scsi);
442141cc406Sopenharmony_ci  if (!FAILED(status))
443141cc406Sopenharmony_ci  {
444141cc406Sopenharmony_ci      sanei_hp_device_support_probe (scsi);
445141cc406Sopenharmony_ci      status = sanei_hp_optset_new(&this->options, scsi, this);
446141cc406Sopenharmony_ci  }
447141cc406Sopenharmony_ci  sanei_hp_scsi_destroy(scsi,1);
448141cc406Sopenharmony_ci
449141cc406Sopenharmony_ci  if (FAILED(status))
450141cc406Sopenharmony_ci    {
451141cc406Sopenharmony_ci      DBG(1, "sanei_hp_device_new: %s: probe failed (%s)\n",
452141cc406Sopenharmony_ci	  devname, sane_strstatus(status));
453141cc406Sopenharmony_ci      sanei_hp_data_destroy(this->data);
454141cc406Sopenharmony_ci      sanei_hp_free((void *)this->sanedev.name);
455141cc406Sopenharmony_ci      sanei_hp_free((void *)this->sanedev.model);
456141cc406Sopenharmony_ci      sanei_hp_free(this);
457141cc406Sopenharmony_ci      return status;
458141cc406Sopenharmony_ci    }
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_ci  DBG(1, "sanei_hp_device_new: %s: found HP ScanJet model %s\n",
461141cc406Sopenharmony_ci      devname, this->sanedev.model);
462141cc406Sopenharmony_ci
463141cc406Sopenharmony_ci  *newp = this;
464141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
465141cc406Sopenharmony_ci}
466141cc406Sopenharmony_ci
467141cc406Sopenharmony_ciconst SANE_Device *
468141cc406Sopenharmony_cisanei_hp_device_sanedevice (HpDevice this)
469141cc406Sopenharmony_ci{
470141cc406Sopenharmony_ci  return &this->sanedev;
471141cc406Sopenharmony_ci}
472