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