1141cc406Sopenharmony_ci/** @file u12-if.c 2141cc406Sopenharmony_ci * @brief The interface functions to the U12 backend stuff. 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Copyright (c) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de> 5141cc406Sopenharmony_ci * 6141cc406Sopenharmony_ci * History: 7141cc406Sopenharmony_ci * - 0.01 - initial version 8141cc406Sopenharmony_ci * - 0.02 - added model tweaking 9141cc406Sopenharmony_ci * - fixed autodetection bug 10141cc406Sopenharmony_ci * - added line-scaling stuff 11141cc406Sopenharmony_ci * - removed u12if_setScanEnv() 12141cc406Sopenharmony_ci * . 13141cc406Sopenharmony_ci * <hr> 14141cc406Sopenharmony_ci * This file is part of the SANE package. 15141cc406Sopenharmony_ci * 16141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 17141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 18141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the 19141cc406Sopenharmony_ci * License, or (at your option) any later version. 20141cc406Sopenharmony_ci * 21141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 22141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 23141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24141cc406Sopenharmony_ci * General Public License for more details. 25141cc406Sopenharmony_ci * 26141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License 27141cc406Sopenharmony_ci * along with this program. If not, see <https://www.gnu.org/licenses/>. 28141cc406Sopenharmony_ci * 29141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for 30141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE. 31141cc406Sopenharmony_ci * 32141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files 33141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the 34141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public 35141cc406Sopenharmony_ci * License. Your use of that executable is in no way restricted on 36141cc406Sopenharmony_ci * account of linking the SANE library code into it. 37141cc406Sopenharmony_ci * 38141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why 39141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public 40141cc406Sopenharmony_ci * License. 41141cc406Sopenharmony_ci * 42141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in 43141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that 44141cc406Sopenharmony_ci * those changes may be distributed with this exception intact. 45141cc406Sopenharmony_ci * 46141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice 47141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications. 48141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice. 49141cc406Sopenharmony_ci * <hr> 50141cc406Sopenharmony_ci */ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#define _DEF_BRIGHTEST_SKIP 3 53141cc406Sopenharmony_ci#define _DEF_DARKEST_SKIP 5 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci/** useful for description tables 56141cc406Sopenharmony_ci */ 57141cc406Sopenharmony_citypedef struct { 58141cc406Sopenharmony_ci int id; 59141cc406Sopenharmony_ci char *desc; 60141cc406Sopenharmony_ci} TabDef; 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_citypedef struct { 63141cc406Sopenharmony_ci char *vp; 64141cc406Sopenharmony_ci char *name; 65141cc406Sopenharmony_ci} DevDesc; 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#define _PLUSTEK_VENID 0x07B3 68141cc406Sopenharmony_ci#define _KYE_VENID 0x0458 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci/** to allow different vendors... 71141cc406Sopenharmony_ci */ 72141cc406Sopenharmony_cistatic TabDef u12Vendors[] = { 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci { _PLUSTEK_VENID, "Plustek" }, 75141cc406Sopenharmony_ci { _KYE_VENID, "KYE/Genius" }, 76141cc406Sopenharmony_ci { 0xFFFF, NULL } 77141cc406Sopenharmony_ci}; 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci/** list of supported devices 80141cc406Sopenharmony_ci */ 81141cc406Sopenharmony_cistatic DevDesc u12Devices[] = { 82141cc406Sopenharmony_ci { "0x07B3-0x0001", "1212U/U12" }, 83141cc406Sopenharmony_ci { "0x0458-0x2004", "Colorpage HR6" }, 84141cc406Sopenharmony_ci { NULL, NULL } 85141cc406Sopenharmony_ci}; 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci/** for autodetection */ 88141cc406Sopenharmony_cistatic SANE_Char USB_devname[1024]; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci/********************** the USB scanner interface ****************************/ 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci/** 93141cc406Sopenharmony_ci */ 94141cc406Sopenharmony_cistatic SANE_Status u12_initDev( U12_Device *dev, int handle, int vendor ) 95141cc406Sopenharmony_ci{ 96141cc406Sopenharmony_ci int i; 97141cc406Sopenharmony_ci SANE_Status res; 98141cc406Sopenharmony_ci TimerDef timer; 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_ci /* well now we patch the vendor string... 101141cc406Sopenharmony_ci * if not found, the default vendor will be Plustek 102141cc406Sopenharmony_ci */ 103141cc406Sopenharmony_ci for( i = 0; u12Vendors[i].desc != NULL; i++ ) { 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci if( u12Vendors[i].id == vendor ) { 106141cc406Sopenharmony_ci dev->sane.vendor = u12Vendors[i].desc; 107141cc406Sopenharmony_ci DBG( _DBG_INFO, "Vendor adjusted to: >%s<\n", dev->sane.vendor ); 108141cc406Sopenharmony_ci break; 109141cc406Sopenharmony_ci } 110141cc406Sopenharmony_ci } 111141cc406Sopenharmony_ci dev->fd = handle; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci dev->adj.upNormal = 0; 114141cc406Sopenharmony_ci dev->adj.upNegative = 20; 115141cc406Sopenharmony_ci dev->adj.upPositive = -30; 116141cc406Sopenharmony_ci dev->adj.leftNormal = 51; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci res = SANE_STATUS_IO_ERROR; 119141cc406Sopenharmony_ci if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_ci u12motor_PositionModuleToHome( dev ); 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci u12io_StartTimer( &timer, _SECOND * 20); 124141cc406Sopenharmony_ci do { 125141cc406Sopenharmony_ci if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER) { 126141cc406Sopenharmony_ci res = SANE_STATUS_GOOD; 127141cc406Sopenharmony_ci break; 128141cc406Sopenharmony_ci } 129141cc406Sopenharmony_ci } while( !u12io_CheckTimer( &timer )); 130141cc406Sopenharmony_ci } else { 131141cc406Sopenharmony_ci res = u12hw_InitAsic( dev, SANE_FALSE ); 132141cc406Sopenharmony_ci } 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci if( res == SANE_STATUS_GOOD ) 135141cc406Sopenharmony_ci u12hw_PutToIdleMode( dev ); 136141cc406Sopenharmony_ci return res; 137141cc406Sopenharmony_ci} 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci/** will be called upon sane_exit 140141cc406Sopenharmony_ci */ 141141cc406Sopenharmony_cistatic void u12if_shutdown( U12_Device *dev ) 142141cc406Sopenharmony_ci{ 143141cc406Sopenharmony_ci SANE_Int handle; 144141cc406Sopenharmony_ci TimerDef timer; 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci DBG( _DBG_INFO, "Shutdown called (dev->fd=%d, %s)\n", 147141cc406Sopenharmony_ci dev->fd, dev->sane.name ); 148141cc406Sopenharmony_ci if( SANE_STATUS_GOOD == sanei_usb_open( dev->sane.name, &handle )) { 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci dev->fd = handle; 151141cc406Sopenharmony_ci u12io_OpenScanPath( dev ); 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci u12hw_PutToIdleMode( dev ); 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_ci if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci u12motor_PositionModuleToHome( dev ); 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci u12io_StartTimer( &timer, _SECOND * 20); 160141cc406Sopenharmony_ci do { 161141cc406Sopenharmony_ci if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER) { 162141cc406Sopenharmony_ci break; 163141cc406Sopenharmony_ci } 164141cc406Sopenharmony_ci } while( !u12io_CheckTimer( &timer )); 165141cc406Sopenharmony_ci } 166141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Home position reached.\n" ); 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci if( 0 != dev->adj.lampOffOnEnd ) { 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Switching lamp off...\n" ); 171141cc406Sopenharmony_ci dev->regs.RD_ScanControl &= ~_SCAN_LAMPS_ON; 172141cc406Sopenharmony_ci u12io_DataToRegister(dev,REG_SCANCONTROL, dev->regs.RD_ScanControl ); 173141cc406Sopenharmony_ci } 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci u12io_CloseScanPath( dev ); 176141cc406Sopenharmony_ci dev->fd = -1; 177141cc406Sopenharmony_ci sanei_usb_close( handle ); 178141cc406Sopenharmony_ci } 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci#if 0 181141cc406Sopenharmony_ci usb_StopLampTimer( dev ); 182141cc406Sopenharmony_ci#endif 183141cc406Sopenharmony_ci DBG( _DBG_INFO, "Shutdown done.\n" ); 184141cc406Sopenharmony_ci} 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_ci/** This function checks whether a device, described by a given 187141cc406Sopenharmony_ci * string(vendor and product ID), is supported by this backend or not 188141cc406Sopenharmony_ci * 189141cc406Sopenharmony_ci * @param usbIdStr - string consisting out of product and vendor ID 190141cc406Sopenharmony_ci * format: "0xVVVV-0xPPPP" VVVV = Vendor ID, PPP = Product ID 191141cc406Sopenharmony_ci * @returns; SANE_TRUE if supported, SANE_FALSE if not 192141cc406Sopenharmony_ci */ 193141cc406Sopenharmony_cistatic SANE_Bool u12if_IsDeviceSupported( U12_Device *dev ) 194141cc406Sopenharmony_ci{ 195141cc406Sopenharmony_ci int i; 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci for( i = 0; NULL != u12Devices[i].name; i++ ) { 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci if( !strcmp( dev->usbId, u12Devices[i].vp )) { 200141cc406Sopenharmony_ci dev->sane.model = u12Devices[i].name; 201141cc406Sopenharmony_ci return SANE_TRUE; 202141cc406Sopenharmony_ci } 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci return SANE_FALSE; 206141cc406Sopenharmony_ci} 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci/** 209141cc406Sopenharmony_ci */ 210141cc406Sopenharmony_cistatic SANE_Status u12if_usbattach( SANE_String_Const dev_name ) 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci if( USB_devname[0] == '\0' ) { 213141cc406Sopenharmony_ci DBG( _DBG_INFO, "Found device at >%s<\n", dev_name ); 214141cc406Sopenharmony_ci strncpy( USB_devname, dev_name, 1023 ); 215141cc406Sopenharmony_ci USB_devname[1023] = '\0'; 216141cc406Sopenharmony_ci } else { 217141cc406Sopenharmony_ci DBG( _DBG_INFO, "Device >%s< ignoring\n", dev_name ); 218141cc406Sopenharmony_ci } 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 221141cc406Sopenharmony_ci} 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ci#ifndef _FAKE_DEVICE 224141cc406Sopenharmony_ci/** here we roam through our list of supported devices and 225141cc406Sopenharmony_ci * cross check with the ones the system reports... 226141cc406Sopenharmony_ci * @param vendor - pointer to receive vendor ID 227141cc406Sopenharmony_ci * @param product - pointer to receive product ID 228141cc406Sopenharmony_ci * @return SANE_TRUE if a matching device has been found or 229141cc406Sopenharmony_ci * SANE_FALSE if nothing supported found... 230141cc406Sopenharmony_ci */ 231141cc406Sopenharmony_cistatic SANE_Bool usbDev_autodetect( SANE_Word *vendor, SANE_Word *product ) 232141cc406Sopenharmony_ci{ 233141cc406Sopenharmony_ci int i; 234141cc406Sopenharmony_ci SANE_Word p, v; 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci DBG( _DBG_INFO, "Autodetection...\n" ); 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci for( i = 0; NULL != u12Devices[i].name; i++ ) { 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci v = strtol( &(u12Devices[i].vp)[0], 0, 0 ); 241141cc406Sopenharmony_ci p = strtol( &(u12Devices[i].vp)[7], 0, 0 ); 242141cc406Sopenharmony_ci DBG( _DBG_INFO, "* checking for 0x%04x-0x%04x\n", v, p ); 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_ci sanei_usb_find_devices( v, p, u12if_usbattach ); 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_ci if( USB_devname[0] != '\0' ) { 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci *vendor = v; 249141cc406Sopenharmony_ci *product = p; 250141cc406Sopenharmony_ci DBG( _DBG_INFO, "* using device >%s<\n", USB_devname ); 251141cc406Sopenharmony_ci return SANE_TRUE; 252141cc406Sopenharmony_ci } 253141cc406Sopenharmony_ci } 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci return SANE_FALSE; 256141cc406Sopenharmony_ci} 257141cc406Sopenharmony_ci#endif 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci/** 260141cc406Sopenharmony_ci */ 261141cc406Sopenharmony_cistatic int u12if_open( U12_Device *dev ) 262141cc406Sopenharmony_ci{ 263141cc406Sopenharmony_ci char devStr[50]; 264141cc406Sopenharmony_ci int result; 265141cc406Sopenharmony_ci SANE_Int handle; 266141cc406Sopenharmony_ci SANE_Word vendor, product; 267141cc406Sopenharmony_ci SANE_Bool was_empty; 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_open(%s,%s)\n", dev->name, dev->usbId ); 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci USB_devname[0] = '\0'; 272141cc406Sopenharmony_ci 273141cc406Sopenharmony_ci#ifdef _FAKE_DEVICE 274141cc406Sopenharmony_ci dev->name = strdup( "auto" ); 275141cc406Sopenharmony_ci dev->sane.name = dev->name; 276141cc406Sopenharmony_ci was_empty = SANE_FALSE; 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci result = SANE_STATUS_UNSUPPORTED; 279141cc406Sopenharmony_ci#else 280141cc406Sopenharmony_ci if( !strcmp( dev->name, "auto" )) { 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci if( dev->usbId[0] == '\0' ) { 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci if( !usbDev_autodetect( &vendor, &product )) { 285141cc406Sopenharmony_ci DBG( _DBG_ERROR, "No supported device found!\n" ); 286141cc406Sopenharmony_ci return -1; 287141cc406Sopenharmony_ci } 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci } else { 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci vendor = strtol( &dev->usbId[0], 0, 0 ); 292141cc406Sopenharmony_ci product = strtol( &dev->usbId[7], 0, 0 ); 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci sanei_usb_find_devices( vendor, product, u12if_usbattach ); 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci if( USB_devname[0] == '\0' ) { 297141cc406Sopenharmony_ci DBG( _DBG_ERROR, "No matching device found!\n" ); 298141cc406Sopenharmony_ci return -1; 299141cc406Sopenharmony_ci } 300141cc406Sopenharmony_ci } 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != sanei_usb_open( USB_devname, &handle )) { 303141cc406Sopenharmony_ci return -1; 304141cc406Sopenharmony_ci } 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci /* replace the old devname, so we are able to have multiple 307141cc406Sopenharmony_ci * auto-detected devices 308141cc406Sopenharmony_ci */ 309141cc406Sopenharmony_ci free( dev->name ); 310141cc406Sopenharmony_ci dev->name = strdup( USB_devname ); 311141cc406Sopenharmony_ci dev->sane.name = dev->name; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci } else { 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != sanei_usb_open( dev->name, &handle )) 316141cc406Sopenharmony_ci return -1; 317141cc406Sopenharmony_ci } 318141cc406Sopenharmony_ci was_empty = SANE_FALSE; 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci result = sanei_usb_get_vendor_product( handle, &vendor, &product ); 321141cc406Sopenharmony_ci#endif 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci if( SANE_STATUS_GOOD == result ) { 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci sprintf( devStr, "0x%04X-0x%04X", vendor, product ); 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci DBG(_DBG_INFO,"Vendor ID=0x%04X, Product ID=0x%04X\n",vendor,product); 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci if( dev->usbId[0] != '\0' ) { 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci if( 0 != strcmp( dev->usbId, devStr )) { 332141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Specified Vendor and Product ID " 333141cc406Sopenharmony_ci "doesn't match with the ones\n" 334141cc406Sopenharmony_ci "in the config file\n" ); 335141cc406Sopenharmony_ci sanei_usb_close( handle ); 336141cc406Sopenharmony_ci return -1; 337141cc406Sopenharmony_ci } 338141cc406Sopenharmony_ci } else { 339141cc406Sopenharmony_ci sprintf( dev->usbId, "0x%04X-0x%04X", vendor, product ); 340141cc406Sopenharmony_ci was_empty = SANE_TRUE; 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci } else { 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci DBG( _DBG_INFO, "Can't get vendor & product ID from driver...\n" ); 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci /* if the ioctl stuff is not supported by the kernel and we have 348141cc406Sopenharmony_ci * nothing specified, we have to give up... 349141cc406Sopenharmony_ci */ 350141cc406Sopenharmony_ci if( dev->usbId[0] == '\0' ) { 351141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Cannot autodetect Vendor an Product ID, " 352141cc406Sopenharmony_ci "please specify in config file.\n" ); 353141cc406Sopenharmony_ci sanei_usb_close( handle ); 354141cc406Sopenharmony_ci return -1; 355141cc406Sopenharmony_ci } 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci vendor = strtol( &dev->usbId[0], 0, 0 ); 358141cc406Sopenharmony_ci product = strtol( &dev->usbId[7], 0, 0 ); 359141cc406Sopenharmony_ci DBG( _DBG_INFO, "... using the specified: " 360141cc406Sopenharmony_ci "0x%04X-0x%04X\n", vendor, product ); 361141cc406Sopenharmony_ci } 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci /* before accessing the scanner, check if supported! 364141cc406Sopenharmony_ci */ 365141cc406Sopenharmony_ci if( !u12if_IsDeviceSupported( dev )) { 366141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Device >%s<, is not supported!\n", dev->usbId ); 367141cc406Sopenharmony_ci sanei_usb_close( handle ); 368141cc406Sopenharmony_ci return -1; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci dev->mode = _PP_MODE_SPP; 372141cc406Sopenharmony_ci dev->fd = handle; 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci /* is it accessible ? */ 375141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != u12hw_CheckDevice( dev )) { 376141cc406Sopenharmony_ci dev->fd = -1; 377141cc406Sopenharmony_ci sanei_usb_close( handle ); 378141cc406Sopenharmony_ci return -1; 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci DBG( _DBG_INFO, "Detected vendor & product ID: " 382141cc406Sopenharmony_ci "0x%04X-0x%04X\n", vendor, product ); 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci if( was_empty ) 385141cc406Sopenharmony_ci dev->usbId[0] = '\0'; 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci /* now initialize the device */ 388141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != u12_initDev( dev, handle, vendor )) { 389141cc406Sopenharmony_ci dev->fd = -1; 390141cc406Sopenharmony_ci sanei_usb_close( handle ); 391141cc406Sopenharmony_ci return -1; 392141cc406Sopenharmony_ci } 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci if( _PLUSTEK_VENID == vendor ) { 395141cc406Sopenharmony_ci if( dev->Tpa ) 396141cc406Sopenharmony_ci dev->sane.model = "UT12"; 397141cc406Sopenharmony_ci } 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci dev->initialized = SANE_TRUE; 400141cc406Sopenharmony_ci return handle; 401141cc406Sopenharmony_ci} 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci/** 404141cc406Sopenharmony_ci */ 405141cc406Sopenharmony_cistatic int u12if_close( U12_Device *dev ) 406141cc406Sopenharmony_ci{ 407141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_close()\n" ); 408141cc406Sopenharmony_ci u12io_CloseScanPath( dev ); 409141cc406Sopenharmony_ci sanei_usb_close( dev->fd ); 410141cc406Sopenharmony_ci dev->fd = -1; 411141cc406Sopenharmony_ci return 0; 412141cc406Sopenharmony_ci} 413141cc406Sopenharmony_ci 414141cc406Sopenharmony_ci/** 415141cc406Sopenharmony_ci */ 416141cc406Sopenharmony_cistatic SANE_Status u12if_getCaps( U12_Device *dev ) 417141cc406Sopenharmony_ci{ 418141cc406Sopenharmony_ci int cntr; 419141cc406Sopenharmony_ci int res_x = 600 ; /*dev->caps.OpticDpi.x */ 420141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_getCaps()\n" ); 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci/* FIXME: set dpi_range.max, max_x & max_y on a per model base */ 423141cc406Sopenharmony_ci dev->dpi_max_x = 600; 424141cc406Sopenharmony_ci dev->dpi_max_y = 1200; 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci /* A4 devices */ 427141cc406Sopenharmony_ci dev->max_x = 8.5 * (double)_MM_PER_INCH; 428141cc406Sopenharmony_ci dev->max_y = 11.6934 * (double)_MM_PER_INCH; 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci /* limit the range */ 431141cc406Sopenharmony_ci dev->dpi_range.min = _DEF_DPI; 432141cc406Sopenharmony_ci dev->dpi_range.max = dev->dpi_max_y; 433141cc406Sopenharmony_ci dev->dpi_range.quant = 0; 434141cc406Sopenharmony_ci dev->x_range.min = 0; 435141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX(dev->max_x); 436141cc406Sopenharmony_ci dev->x_range.quant = 0; 437141cc406Sopenharmony_ci dev->y_range.min = 0; 438141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX(dev->max_y); 439141cc406Sopenharmony_ci dev->y_range.quant = 0; 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci /* calculate the size of the resolution list + 442141cc406Sopenharmony_ci * one more to avoid a buffer overflow, then allocate it... 443141cc406Sopenharmony_ci */ 444141cc406Sopenharmony_ci dev->res_list = (SANE_Int *) 445141cc406Sopenharmony_ci calloc((((res_x * 16)-_DEF_DPI)/25+1), 446141cc406Sopenharmony_ci sizeof (SANE_Int)); 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci if (NULL == dev->res_list) { 449141cc406Sopenharmony_ci DBG( _DBG_ERROR, "alloc fail, resolution problem\n" ); 450141cc406Sopenharmony_ci u12if_close(dev); 451141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 452141cc406Sopenharmony_ci } 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci /* build up the resolution table */ 455141cc406Sopenharmony_ci dev->res_list_size = 0; 456141cc406Sopenharmony_ci for( cntr = _DEF_DPI; cntr <= (res_x*16); cntr += 25 ) { 457141cc406Sopenharmony_ci dev->res_list_size++; 458141cc406Sopenharmony_ci dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; 459141cc406Sopenharmony_ci } 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 462141cc406Sopenharmony_ci} 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci/** 465141cc406Sopenharmony_ci */ 466141cc406Sopenharmony_cistatic SANE_Status u12if_startScan( U12_Device *dev ) 467141cc406Sopenharmony_ci{ 468141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_startScan()\n" ); 469141cc406Sopenharmony_ci u12hw_StopLampTimer( dev ); 470141cc406Sopenharmony_ci u12hw_SetGeneralRegister( dev ); 471141cc406Sopenharmony_ci u12hw_ControlLampOnOff( dev ); 472141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 473141cc406Sopenharmony_ci} 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci/** 476141cc406Sopenharmony_ci */ 477141cc406Sopenharmony_cistatic SANE_Status u12if_stopScan( U12_Device *dev ) 478141cc406Sopenharmony_ci{ 479141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_stopScan()\n" ); 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci#if 0 482141cc406Sopenharmony_ci u12motor_ToHomePosition( dev, SANE_FALSE ); 483141cc406Sopenharmony_ci#else 484141cc406Sopenharmony_ci#if 0 485141cc406Sopenharmony_ci u12motor_ToHomePosition( dev, SANE_TRUE ); 486141cc406Sopenharmony_ci u12io_SoftwareReset( dev ); 487141cc406Sopenharmony_ci#endif 488141cc406Sopenharmony_ci u12hw_CancelSequence( dev ); 489141cc406Sopenharmony_ci#endif 490141cc406Sopenharmony_ci u12hw_StartLampTimer( dev ); 491141cc406Sopenharmony_ci dev->DataInf.dwAppLinesPerArea = 0; 492141cc406Sopenharmony_ci dev->DataInf.dwScanFlag &= ~_SCANDEF_SCANNING; 493141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 494141cc406Sopenharmony_ci} 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci/** 497141cc406Sopenharmony_ci */ 498141cc406Sopenharmony_cistatic SANE_Status u12if_prepare( U12_Device *dev ) 499141cc406Sopenharmony_ci{ 500141cc406Sopenharmony_ci SANE_Status res; 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_prepare()\n" ); 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci u12motor_ToHomePosition( dev, SANE_TRUE ); 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci res = u12hw_WarmupLamp( dev ); 507141cc406Sopenharmony_ci if( res != SANE_STATUS_GOOD ) 508141cc406Sopenharmony_ci return res; 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci res = u12shading_DoCalibration( dev ); 511141cc406Sopenharmony_ci if( res != SANE_STATUS_GOOD ) 512141cc406Sopenharmony_ci return res; 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci u12image_PrepareScaling( dev ); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci u12motor_ForceToLeaveHomePos( dev ); 517141cc406Sopenharmony_ci if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) 518141cc406Sopenharmony_ci u12hw_SetupPreviewCondition( dev ); 519141cc406Sopenharmony_ci else 520141cc406Sopenharmony_ci u12hw_SetupScanningCondition( dev ); 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci res = u12motor_WaitForPositionY( dev ); 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci _DODELAY(100); 525141cc406Sopenharmony_ci u12io_ResetFifoLen(); 526141cc406Sopenharmony_ci u12io_GetFifoLength(dev); 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci dev->scan.bModuleState = _MotorAdvancing; 529141cc406Sopenharmony_ci dev->scan.oldScanState = u12io_GetScanState( dev ); 530141cc406Sopenharmony_ci dev->scan.oldScanState &= _SCANSTATE_MASK; 531141cc406Sopenharmony_ci dev->DataInf.dwScanFlag |= _SCANDEF_SCANNING; 532141cc406Sopenharmony_ci DBG( _DBG_INFO, "* oldScanState = %u\n", dev->scan.oldScanState ); 533141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_prepare() done.\n" ); 534141cc406Sopenharmony_ci return res; 535141cc406Sopenharmony_ci} 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci/** 538141cc406Sopenharmony_ci */ 539141cc406Sopenharmony_cistatic SANE_Status u12if_readLine( U12_Device *dev, SANE_Byte *line_buffer ) 540141cc406Sopenharmony_ci{ 541141cc406Sopenharmony_ci SANE_Status res; 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci DBG( _DBG_READ, "u12if_readLine()\n" ); 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_ci if( u12io_IsEscPressed()) { 546141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_readLine() - cancel detected!\n" ); 547141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 548141cc406Sopenharmony_ci } 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci if( dev->scaleBuf != NULL ) { 551141cc406Sopenharmony_ci res = u12image_ReadOneImageLine( dev, dev->scaleBuf ); 552141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != res ) 553141cc406Sopenharmony_ci return res; 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci u12image_ScaleX( dev, dev->scaleBuf, line_buffer ); 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci } else { 558141cc406Sopenharmony_ci res = u12image_ReadOneImageLine( dev, line_buffer ); 559141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != res ) 560141cc406Sopenharmony_ci return res; 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 563141cc406Sopenharmony_ci} 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_ci/** 566141cc406Sopenharmony_ci */ 567141cc406Sopenharmony_cistatic SANE_Status u12if_SetupBuffer( U12_Device *dev ) 568141cc406Sopenharmony_ci{ 569141cc406Sopenharmony_ci void *buffer; 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci DBG( _DBG_INFO, "u12if_SetupBuffer()\n" ); 572141cc406Sopenharmony_ci buffer = malloc(_SIZE_TOTAL_BUF_TPA); 573141cc406Sopenharmony_ci if( buffer == NULL ) 574141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci dev->shade.pHilight = NULL; 577141cc406Sopenharmony_ci dev->bufs.b1.pReadBuf = buffer; 578141cc406Sopenharmony_ci dev->bufs.b2.pSumBuf = dev->bufs.b1.pReadBuf + _SIZE_DATA_BUF; 579141cc406Sopenharmony_ci dev->bufs.TpaBuf.pb = &((SANE_Byte*)dev->bufs.b2.pSumBuf)[_SIZE_SHADING_SUM_BUF]; 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci/* CHECK: We might should play around with these values... */ 582141cc406Sopenharmony_ci dev->shade.skipHilight = _DEF_BRIGHTEST_SKIP; 583141cc406Sopenharmony_ci dev->shade.skipShadow = _DEF_DARKEST_SKIP; 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci if( dev->shade.skipHilight && dev->shade.skipShadow ) { 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci u_long skipSize; 588141cc406Sopenharmony_ci 589141cc406Sopenharmony_ci skipSize = (u_long)((dev->shade.skipHilight + dev->shade.skipShadow) 590141cc406Sopenharmony_ci * _SIZE_DATA_BUF * 3); 591141cc406Sopenharmony_ci dev->shade.pHilight = (RGBUShortDef*)malloc( skipSize ); 592141cc406Sopenharmony_ci if( NULL != dev->shade.pHilight ) { 593141cc406Sopenharmony_ci dev->shade.dwDiv = (u_long)(32UL - dev->shade.skipHilight - 594141cc406Sopenharmony_ci dev->shade.skipShadow); 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci } 597141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 598141cc406Sopenharmony_ci} 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci/* END U12-IF.C .............................................................*/ 601