1141cc406Sopenharmony_ci/*............................................................................. 2141cc406Sopenharmony_ci * Project : SANE library for Plustek flatbed scanners. 3141cc406Sopenharmony_ci *............................................................................. 4141cc406Sopenharmony_ci */ 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci/** @file plustek-usb.c 7141cc406Sopenharmony_ci * @brief The interface functions to the USB driver stuff. 8141cc406Sopenharmony_ci * 9141cc406Sopenharmony_ci * Based on sources acquired from Plustek Inc.<br> 10141cc406Sopenharmony_ci * Copyright (C) 2001-2007 Gerhard Jaeger <gerhard@gjaeger.de> 11141cc406Sopenharmony_ci * 12141cc406Sopenharmony_ci * History: 13141cc406Sopenharmony_ci * - 0.40 - starting version of the USB support 14141cc406Sopenharmony_ci * - 0.41 - removed CHECK 15141cc406Sopenharmony_ci * - added Canon to the manufacturer list 16141cc406Sopenharmony_ci * - 0.42 - added warmup stuff 17141cc406Sopenharmony_ci * - added setmap function 18141cc406Sopenharmony_ci * - changed detection stuff, so we first check whether 19141cc406Sopenharmony_ci * - the vendor and product Ids match with the ones in our list 20141cc406Sopenharmony_ci * - 0.43 - cleanup 21141cc406Sopenharmony_ci * - 0.44 - changes to integration CIS based devices 22141cc406Sopenharmony_ci * - 0.45 - added skipFine assignment 23141cc406Sopenharmony_ci * - added auto device name detection if only product and vendor id<br> 24141cc406Sopenharmony_ci * has been specified 25141cc406Sopenharmony_ci * - made 16-bit gray mode work 26141cc406Sopenharmony_ci * - added special handling for Genius devices 27141cc406Sopenharmony_ci * - added TPA autodetection for EPSON Photo 28141cc406Sopenharmony_ci * - fixed bug that causes warmup each time autodetected<br> 29141cc406Sopenharmony_ci * TPA on EPSON is used 30141cc406Sopenharmony_ci * - removed Genius from PCB-Id check 31141cc406Sopenharmony_ci * - added Compaq to the list 32141cc406Sopenharmony_ci * - removed the scaler stuff for CIS devices 33141cc406Sopenharmony_ci * - removed homeing stuff from readline function 34141cc406Sopenharmony_ci * - fixed flag setting in usbDev_startScan() 35141cc406Sopenharmony_ci * - 0.46 - added additional branch to support alternate calibration 36141cc406Sopenharmony_ci * - 0.47 - added special handling with 0x400 vendor ID and model override 37141cc406Sopenharmony_ci * - removed PATH_MAX 38141cc406Sopenharmony_ci * - change usbDev_stopScan and usbDev_open prototype 39141cc406Sopenharmony_ci * - cleanup 40141cc406Sopenharmony_ci * - 0.48 - added function usb_CheckAndCopyAdjs() 41141cc406Sopenharmony_ci * - 0.49 - changed autodetection 42141cc406Sopenharmony_ci * - added support for LiDE25 (pid 0x2220) 43141cc406Sopenharmony_ci * - 0.50 - minor fix for startup reset 44141cc406Sopenharmony_ci * removed unnecessary calls to usbio_ResetLM983x() 45141cc406Sopenharmony_ci * 1200DPI CIS devices don't use GrayFromColor any longer 46141cc406Sopenharmony_ci * - 0.51 - added Syscan to the vendor list 47141cc406Sopenharmony_ci * - added SCANFLAG_Calibration handling 48141cc406Sopenharmony_ci * - 0.52 - added _WAF_LOFF_ON_START and _WAF_INC_DARKTGT 49141cc406Sopenharmony_ci * handling in usbDev_startScan() 50141cc406Sopenharmony_ci * added Visioneer 51141cc406Sopenharmony_ci * . 52141cc406Sopenharmony_ci * <hr> 53141cc406Sopenharmony_ci * This file is part of the SANE package. 54141cc406Sopenharmony_ci * 55141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 56141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 57141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the 58141cc406Sopenharmony_ci * License, or (at your option) any later version. 59141cc406Sopenharmony_ci * 60141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 61141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 62141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 63141cc406Sopenharmony_ci * General Public License for more details. 64141cc406Sopenharmony_ci * 65141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License 66141cc406Sopenharmony_ci * along with this program. If not, see <https://www.gnu.org/licenses/>. 67141cc406Sopenharmony_ci * 68141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for 69141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE. 70141cc406Sopenharmony_ci * 71141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files 72141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the 73141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public 74141cc406Sopenharmony_ci * License. Your use of that executable is in no way restricted on 75141cc406Sopenharmony_ci * account of linking the SANE library code into it. 76141cc406Sopenharmony_ci * 77141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why 78141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public 79141cc406Sopenharmony_ci * License. 80141cc406Sopenharmony_ci * 81141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in 82141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that 83141cc406Sopenharmony_ci * those changes may be distributed with this exception intact. 84141cc406Sopenharmony_ci * 85141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice 86141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications. 87141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice. 88141cc406Sopenharmony_ci * <hr> 89141cc406Sopenharmony_ci */ 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci/** useful for description tables 92141cc406Sopenharmony_ci */ 93141cc406Sopenharmony_citypedef struct { 94141cc406Sopenharmony_ci int id; 95141cc406Sopenharmony_ci char *desc; 96141cc406Sopenharmony_ci char *desc_alt; 97141cc406Sopenharmony_ci} TabDef, *pTabDef; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/** to allow different vendors... 100141cc406Sopenharmony_ci */ 101141cc406Sopenharmony_cistatic TabDef usbVendors[] = { 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci { 0x07B3, "Plustek", NULL }, 104141cc406Sopenharmony_ci { 0x0400, "NSC", "Mustek" }, 105141cc406Sopenharmony_ci { 0x0458, "KYE/Genius", NULL }, 106141cc406Sopenharmony_ci { 0x03F0, "Hewlett-Packard", NULL }, 107141cc406Sopenharmony_ci { 0x04B8, "Epson", NULL }, 108141cc406Sopenharmony_ci { 0x04A7, "Visioneer", NULL }, 109141cc406Sopenharmony_ci { 0x04A9, "Canon", NULL }, 110141cc406Sopenharmony_ci { 0x1606, "UMAX", NULL }, 111141cc406Sopenharmony_ci { 0x049F, "Compaq", NULL }, 112141cc406Sopenharmony_ci { 0x0A82, "Syscan", NULL }, 113141cc406Sopenharmony_ci { 0x0A53, "PandP Co., Ltd.", NULL }, 114141cc406Sopenharmony_ci { 0xFFFF, NULL, NULL } 115141cc406Sopenharmony_ci}; 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci/** we use at least 8 megs for scanning... */ 118141cc406Sopenharmony_ci#define _SCANBUF_SIZE (8 * 1024 * 1024) 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci/********************** the USB scanner interface ****************************/ 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ci/** remove the slash out of the model-name to obtain a valid filename 123141cc406Sopenharmony_ci */ 124141cc406Sopenharmony_cistatic SANE_Bool usb_normFileName( char *fname, char* buffer, u_long max_len ) 125141cc406Sopenharmony_ci{ 126141cc406Sopenharmony_ci char *src, *dst; 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ci if( NULL == fname ) 129141cc406Sopenharmony_ci return SANE_FALSE; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci if( strlen( fname ) >= max_len ) 132141cc406Sopenharmony_ci return SANE_FALSE; 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci src = fname; 135141cc406Sopenharmony_ci dst = buffer; 136141cc406Sopenharmony_ci while( *src != '\0' ) { 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci if((*src == '/') || isspace(*src) || ispunct(*src)) 139141cc406Sopenharmony_ci *dst = '_'; 140141cc406Sopenharmony_ci else 141141cc406Sopenharmony_ci *dst = *src; 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_ci dst++; 144141cc406Sopenharmony_ci src++; 145141cc406Sopenharmony_ci } 146141cc406Sopenharmony_ci *dst = '\0'; 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci return SANE_TRUE; 149141cc406Sopenharmony_ci} 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci/** do some range checking and copy the adjustment values from the 152141cc406Sopenharmony_ci * frontend to our internal structures, so that the backend can take 153141cc406Sopenharmony_ci * care of them. 154141cc406Sopenharmony_ci */ 155141cc406Sopenharmony_cistatic void usb_CheckAndCopyAdjs( Plustek_Device *dev ) 156141cc406Sopenharmony_ci{ 157141cc406Sopenharmony_ci if( dev->adj.lampOff >= 0 ) 158141cc406Sopenharmony_ci dev->usbDev.dwLampOnPeriod = dev->adj.lampOff; 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci if( dev->adj.lampOffOnEnd >= 0 ) 161141cc406Sopenharmony_ci dev->usbDev.bLampOffOnEnd = dev->adj.lampOffOnEnd; 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci if( dev->adj.skipCalibration > 0 ) 164141cc406Sopenharmony_ci dev->usbDev.Caps.workaroundFlag |= _WAF_BYPASS_CALIBRATION; 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_ci if( dev->adj.skipFine > 0 ) 167141cc406Sopenharmony_ci dev->usbDev.Caps.workaroundFlag |= _WAF_SKIP_FINE; 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci if( dev->adj.skipFineWhite > 0 ) 170141cc406Sopenharmony_ci dev->usbDev.Caps.workaroundFlag |= _WAF_SKIP_WHITEFINE; 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_ci if( dev->adj.incDarkTgt > 0 ) 173141cc406Sopenharmony_ci dev->usbDev.Caps.workaroundFlag |= _WAF_INC_DARKTGT; 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci if( dev->adj.skipDarkStrip > 0 ) 176141cc406Sopenharmony_ci dev->usbDev.Caps.Normal.DarkShadOrgY = -1; 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci if( dev->adj.invertNegatives > 0 ) 179141cc406Sopenharmony_ci dev->usbDev.Caps.workaroundFlag |= _WAF_INV_NEGATIVE_MAP; 180141cc406Sopenharmony_ci} 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci/** 183141cc406Sopenharmony_ci * assign the values to the structures used by the currently found scanner 184141cc406Sopenharmony_ci */ 185141cc406Sopenharmony_cistatic void 186141cc406Sopenharmony_ciusb_initDev( Plustek_Device *dev, int idx, int handle, int vendor ) 187141cc406Sopenharmony_ci{ 188141cc406Sopenharmony_ci char *ptr; 189141cc406Sopenharmony_ci char tmp_str1[PATH_MAX]; 190141cc406Sopenharmony_ci char tmp_str2[PATH_MAX]; 191141cc406Sopenharmony_ci int i; 192141cc406Sopenharmony_ci ScanParam sParam; 193141cc406Sopenharmony_ci u_short tmp = 0; 194141cc406Sopenharmony_ci int ret = 0; 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci DBG( _DBG_INFO, "usb_initDev(%d,0x%04x,%i)\n", 197141cc406Sopenharmony_ci idx, vendor, dev->initialized ); 198141cc406Sopenharmony_ci /* save capability flags... */ 199141cc406Sopenharmony_ci if( dev->initialized >= 0 ) { 200141cc406Sopenharmony_ci tmp = DEVCAPSFLAG_TPA; 201141cc406Sopenharmony_ci } 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci /* copy the original values... */ 204141cc406Sopenharmony_ci memcpy( &dev->usbDev.Caps, Settings[idx].pDevCaps, sizeof(DCapsDef)); 205141cc406Sopenharmony_ci memcpy( &dev->usbDev.HwSetting, Settings[idx].pHwDef, sizeof(HWDef)); 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci /* restore capability flags... */ 208141cc406Sopenharmony_ci if( dev->initialized >= 0 ) { 209141cc406Sopenharmony_ci dev->usbDev.Caps.wFlags |= tmp; 210141cc406Sopenharmony_ci } 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci usb_CheckAndCopyAdjs( dev ); 213141cc406Sopenharmony_ci DBG( _DBG_INFO, "Device WAF : 0x%08lx\n", dev->usbDev.Caps.workaroundFlag ); 214141cc406Sopenharmony_ci DBG( _DBG_INFO, "Transferrate: %lu Bytes/s\n", dev->transferRate ); 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci /* adjust data origin 217141cc406Sopenharmony_ci */ 218141cc406Sopenharmony_ci dev->usbDev.Caps.Positive.DataOrigin.x -= dev->adj.tpa.x; 219141cc406Sopenharmony_ci dev->usbDev.Caps.Positive.DataOrigin.y -= dev->adj.tpa.y; 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci dev->usbDev.Caps.Negative.DataOrigin.x -= dev->adj.neg.x; 222141cc406Sopenharmony_ci dev->usbDev.Caps.Negative.DataOrigin.y -= dev->adj.neg.y; 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_ci dev->usbDev.Caps.Normal.DataOrigin.x -= dev->adj.pos.x; 225141cc406Sopenharmony_ci dev->usbDev.Caps.Normal.DataOrigin.y -= dev->adj.pos.y; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci /** adjust shading position 228141cc406Sopenharmony_ci */ 229141cc406Sopenharmony_ci if( dev->adj.posShadingY >= 0 ) 230141cc406Sopenharmony_ci dev->usbDev.Caps.Normal.ShadingOriginY = dev->adj.posShadingY; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci if( dev->adj.tpaShadingY >= 0 ) 233141cc406Sopenharmony_ci dev->usbDev.Caps.Positive.ShadingOriginY = dev->adj.tpaShadingY; 234141cc406Sopenharmony_ci 235141cc406Sopenharmony_ci if( dev->adj.negShadingY >= 0 ) 236141cc406Sopenharmony_ci dev->usbDev.Caps.Negative.ShadingOriginY = dev->adj.negShadingY; 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci /* adjust the gamma settings... */ 239141cc406Sopenharmony_ci if( dev->adj.rgamma == 1.0 ) 240141cc406Sopenharmony_ci dev->adj.rgamma = dev->usbDev.HwSetting.gamma; 241141cc406Sopenharmony_ci if( dev->adj.ggamma == 1.0 ) 242141cc406Sopenharmony_ci dev->adj.ggamma = dev->usbDev.HwSetting.gamma; 243141cc406Sopenharmony_ci if( dev->adj.bgamma == 1.0 ) 244141cc406Sopenharmony_ci dev->adj.bgamma = dev->usbDev.HwSetting.gamma; 245141cc406Sopenharmony_ci if( dev->adj.graygamma == 1.0 ) 246141cc406Sopenharmony_ci dev->adj.graygamma = dev->usbDev.HwSetting.gamma; 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci /* the following you normally get from the registry... 249141cc406Sopenharmony_ci */ 250141cc406Sopenharmony_ci bMaxITA = 0; /* Maximum integration time adjust */ 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci dev->usbDev.ModelStr = Settings[idx].pModelString; 253141cc406Sopenharmony_ci 254141cc406Sopenharmony_ci dev->fd = handle; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci if( dev->initialized < 0 ) { 257141cc406Sopenharmony_ci if( usb_HasTPA( dev )) 258141cc406Sopenharmony_ci dev->usbDev.Caps.wFlags |= DEVCAPSFLAG_TPA; 259141cc406Sopenharmony_ci } 260141cc406Sopenharmony_ci DBG( _DBG_INFO, "Device Flags: 0x%08x\n", dev->usbDev.Caps.wFlags ); 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci /* well now we patch the vendor string... 263141cc406Sopenharmony_ci * if not found, the default vendor will be Plustek 264141cc406Sopenharmony_ci */ 265141cc406Sopenharmony_ci for( i = 0; usbVendors[i].desc != NULL; i++ ) { 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci if( usbVendors[i].id == vendor ) { 268141cc406Sopenharmony_ci dev->sane.vendor = usbVendors[i].desc; 269141cc406Sopenharmony_ci if (dev->usbDev.Caps.workaroundFlag & _WAF_USE_ALT_DESC ) 270141cc406Sopenharmony_ci if (usbVendors[i].desc_alt ) 271141cc406Sopenharmony_ci dev->sane.vendor = usbVendors[i].desc_alt; 272141cc406Sopenharmony_ci DBG( _DBG_INFO, "Vendor adjusted to: >%s<\n", dev->sane.vendor ); 273141cc406Sopenharmony_ci break; 274141cc406Sopenharmony_ci } 275141cc406Sopenharmony_ci } 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci dev->usbDev.dwTicksLampOn = 0; 278141cc406Sopenharmony_ci dev->usbDev.currentLamp = usb_GetLampStatus( dev ); 279141cc406Sopenharmony_ci usb_ResetRegisters( dev ); 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci if( dev->initialized >= 0 ) 282141cc406Sopenharmony_ci return; 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci usb_IsScannerReady( dev ); 285141cc406Sopenharmony_ci 286141cc406Sopenharmony_ci sParam.bBitDepth = 8; 287141cc406Sopenharmony_ci sParam.bCalibration = PARAM_Scan; 288141cc406Sopenharmony_ci sParam.bChannels = 3; 289141cc406Sopenharmony_ci sParam.bDataType = SCANDATATYPE_Color; 290141cc406Sopenharmony_ci sParam.bSource = SOURCE_Reflection; 291141cc406Sopenharmony_ci sParam.Origin.x = 0; 292141cc406Sopenharmony_ci sParam.Origin.y = 0; 293141cc406Sopenharmony_ci sParam.UserDpi.x = 150; 294141cc406Sopenharmony_ci sParam.UserDpi.y = 150; 295141cc406Sopenharmony_ci sParam.dMCLK = 4; 296141cc406Sopenharmony_ci sParam.Size.dwPixels = 0; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci /* create calibration-filename */ 299141cc406Sopenharmony_ci sprintf( tmp_str2, "%s-%s", 300141cc406Sopenharmony_ci dev->sane.vendor, dev->usbDev.ModelStr ); 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci if( !usb_normFileName( tmp_str2, tmp_str1, PATH_MAX )) { 303141cc406Sopenharmony_ci strcpy( tmp_str1, "plustek-default" ); 304141cc406Sopenharmony_ci } 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci ptr = getenv ("HOME"); 307141cc406Sopenharmony_ci ret = ( NULL == ptr )? 308141cc406Sopenharmony_ci snprintf( tmp_str2, sizeof(tmp_str2), "/tmp/%s", tmp_str1 ): 309141cc406Sopenharmony_ci snprintf( tmp_str2, sizeof(tmp_str2), "%s/.sane/%s", ptr, tmp_str1 ); 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci if ((ret < 0) || (ret > (int)sizeof(tmp_str2))) { 312141cc406Sopenharmony_ci DBG( _DBG_WARNING, 313141cc406Sopenharmony_ci "Failed to generate calibration file path. Default substituted.\n" ); 314141cc406Sopenharmony_ci snprintf(tmp_str2, sizeof(tmp_str2), "/tmp/plustek-default"); 315141cc406Sopenharmony_ci } 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_ci dev->calFile = strdup( tmp_str2 ); 318141cc406Sopenharmony_ci DBG( _DBG_INFO, "Calibration file-names set to:\n" ); 319141cc406Sopenharmony_ci DBG( _DBG_INFO, ">%s-coarse.cal<\n", dev->calFile ); 320141cc406Sopenharmony_ci DBG( _DBG_INFO, ">%s-fine.cal<\n", dev->calFile ); 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci /* initialize the ASIC registers */ 323141cc406Sopenharmony_ci usb_SetScanParameters( dev, &sParam ); 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci /* check and move sensor to its home position */ 326141cc406Sopenharmony_ci usb_ModuleToHome( dev, SANE_FALSE ); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci /* set the global flag, that we are initialized so far */ 329141cc406Sopenharmony_ci dev->initialized = idx; 330141cc406Sopenharmony_ci} 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci/** 333141cc406Sopenharmony_ci * will be used for retrieving a Plustek device 334141cc406Sopenharmony_ci */ 335141cc406Sopenharmony_cistatic int usb_CheckForPlustekDevice( int handle, Plustek_Device *dev ) 336141cc406Sopenharmony_ci{ 337141cc406Sopenharmony_ci char tmp[50]; 338141cc406Sopenharmony_ci char pcbStr[10]; 339141cc406Sopenharmony_ci u_char reg59[3], reg59s[3], pcbID; 340141cc406Sopenharmony_ci int i, result; 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci /* 343141cc406Sopenharmony_ci * Plustek uses the misc IO 12 to get the PCB ID 344141cc406Sopenharmony_ci * (PCB = printed circuit board), so it's possible to have one 345141cc406Sopenharmony_ci * product ID and up to 7 different devices... 346141cc406Sopenharmony_ci */ 347141cc406Sopenharmony_ci DBG( _DBG_INFO, "Trying to get the pcbID of a Plustek device...\n" ); 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci /* get the PCB-ID */ 350141cc406Sopenharmony_ci result = sanei_lm983x_read( handle, 0x59, reg59s, 3, SANE_TRUE ); 351141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != result ) { 352141cc406Sopenharmony_ci sanei_usb_close( handle ); 353141cc406Sopenharmony_ci return -1; 354141cc406Sopenharmony_ci } 355141cc406Sopenharmony_ci 356141cc406Sopenharmony_ci reg59[0] = 0x22; /* PIO1: Input, PIO2: Input */ 357141cc406Sopenharmony_ci reg59[1] = 0x02; /* PIO3: Input, PIO4: Output as low */ 358141cc406Sopenharmony_ci reg59[2] = 0x03; 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci result = sanei_lm983x_write( handle, 0x59, reg59, 3, SANE_TRUE ); 361141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != result ) { 362141cc406Sopenharmony_ci sanei_usb_close( handle ); 363141cc406Sopenharmony_ci return -1; 364141cc406Sopenharmony_ci } 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci result = sanei_lm983x_read ( handle, 0x02, &pcbID, 1, SANE_TRUE ); 367141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != result ) { 368141cc406Sopenharmony_ci sanei_usb_close( handle ); 369141cc406Sopenharmony_ci return -1; 370141cc406Sopenharmony_ci } 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci pcbID = (u_char)((pcbID >> 2) & 0x07); 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci result = sanei_lm983x_read( handle, 0x59, reg59s, 3, SANE_TRUE ); 375141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != result ) { 376141cc406Sopenharmony_ci sanei_usb_close( handle ); 377141cc406Sopenharmony_ci return -1; 378141cc406Sopenharmony_ci } 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci DBG( _DBG_INFO, "pcbID=0x%02x\n", pcbID ); 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci /* now roam through the setting list... */ 383141cc406Sopenharmony_ci strncpy( tmp, dev->usbId, 13 ); 384141cc406Sopenharmony_ci tmp[13] = '\0'; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci sprintf( pcbStr, "-%u", pcbID ); 387141cc406Sopenharmony_ci strcat ( tmp, pcbStr ); 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci DBG( _DBG_INFO, "Checking for device >%s<\n", tmp ); 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci for( i = 0; NULL != Settings[i].pIDString; i++ ) { 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci if( 0 == strcmp( Settings[i].pIDString, tmp )) { 394141cc406Sopenharmony_ci DBG(_DBG_INFO, "Device description for >%s< found.\n", tmp ); 395141cc406Sopenharmony_ci usb_initDev( dev, i, handle, dev->usbDev.vendor ); 396141cc406Sopenharmony_ci return handle; 397141cc406Sopenharmony_ci } 398141cc406Sopenharmony_ci } 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci return -1; 401141cc406Sopenharmony_ci} 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci/** 404141cc406Sopenharmony_ci * will be called upon sane_exit 405141cc406Sopenharmony_ci */ 406141cc406Sopenharmony_cistatic void usbDev_shutdown( Plustek_Device *dev ) 407141cc406Sopenharmony_ci{ 408141cc406Sopenharmony_ci SANE_Int handle; 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci DBG( _DBG_INFO, "Shutdown called (dev->fd=%d, %s)\n", 411141cc406Sopenharmony_ci dev->fd, dev->sane.name ); 412141cc406Sopenharmony_ci if( NULL == dev->usbDev.ModelStr ) { 413141cc406Sopenharmony_ci DBG( _DBG_INFO, "Function ignored!\n" ); 414141cc406Sopenharmony_ci return; 415141cc406Sopenharmony_ci } 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci if( SANE_STATUS_GOOD == sanei_usb_open( dev->sane.name, &handle )) { 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci dev->fd = handle; 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci DBG( _DBG_INFO, "Waiting for scanner-ready...\n" ); 422141cc406Sopenharmony_ci usb_IsScannerReady( dev ); 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci if( 0 != dev->usbDev.bLampOffOnEnd ) { 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci DBG( _DBG_INFO, "Switching lamp off...\n" ); 427141cc406Sopenharmony_ci usb_LampOn( dev, SANE_FALSE, SANE_FALSE ); 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci dev->fd = -1; 430141cc406Sopenharmony_ci sanei_usb_close( handle ); 431141cc406Sopenharmony_ci } 432141cc406Sopenharmony_ci usb_StopLampTimer( dev ); 433141cc406Sopenharmony_ci} 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci/** 436141cc406Sopenharmony_ci * This function checks whether a device, described by a given 437141cc406Sopenharmony_ci * string(vendor and product ID), is support by this backend or not 438141cc406Sopenharmony_ci * 439141cc406Sopenharmony_ci * @param usbIdStr - string consisting out of product and vendor ID 440141cc406Sopenharmony_ci * format: "0xVVVVx0xPPPP" VVVV = Vendor ID, PPP = Product ID 441141cc406Sopenharmony_ci * @returns; SANE_TRUE if supported, SANE_FALSE if not 442141cc406Sopenharmony_ci */ 443141cc406Sopenharmony_cistatic SANE_Bool usb_IsDeviceInList( char *usbIdStr ) 444141cc406Sopenharmony_ci{ 445141cc406Sopenharmony_ci int i; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci for( i = 0; NULL != Settings[i].pIDString; i++ ) { 448141cc406Sopenharmony_ci 449141cc406Sopenharmony_ci if( 0 == strncmp( Settings[i].pIDString, usbIdStr, 13 )) 450141cc406Sopenharmony_ci return SANE_TRUE; 451141cc406Sopenharmony_ci } 452141cc406Sopenharmony_ci return SANE_FALSE; 453141cc406Sopenharmony_ci} 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci/** get last valid entry of a list 456141cc406Sopenharmony_ci */ 457141cc406Sopenharmony_cistatic DevList* 458141cc406Sopenharmony_cigetLast( DevList *l ) 459141cc406Sopenharmony_ci{ 460141cc406Sopenharmony_ci if( l == NULL ) 461141cc406Sopenharmony_ci return NULL; 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci while( l->next != NULL ) 464141cc406Sopenharmony_ci l = l->next; 465141cc406Sopenharmony_ci return l; 466141cc406Sopenharmony_ci} 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci/** add a new entry to our internal device list, when a device is detected 469141cc406Sopenharmony_ci */ 470141cc406Sopenharmony_cistatic SANE_Status usb_attach( SANE_String_Const dev_name ) 471141cc406Sopenharmony_ci{ 472141cc406Sopenharmony_ci int len; 473141cc406Sopenharmony_ci DevList *tmp, *last; 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci /* get some memory for the entry... */ 476141cc406Sopenharmony_ci len = sizeof(DevList) + strlen(dev_name) + 1; 477141cc406Sopenharmony_ci tmp = (DevList*)malloc(len); 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_ci /* initialize and set the values */ 480141cc406Sopenharmony_ci memset(tmp, 0, len ); 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci /* the device name is part of our structure space */ 483141cc406Sopenharmony_ci tmp->dev_name = &((char*)tmp)[sizeof(DevList)]; 484141cc406Sopenharmony_ci strcpy( tmp->dev_name, dev_name ); 485141cc406Sopenharmony_ci tmp->attached = SANE_FALSE; 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci /* root set ? */ 488141cc406Sopenharmony_ci if( usbDevs == NULL ) { 489141cc406Sopenharmony_ci usbDevs = tmp; 490141cc406Sopenharmony_ci } else { 491141cc406Sopenharmony_ci last = getLast(usbDevs); /* append... */ 492141cc406Sopenharmony_ci last->next = tmp; 493141cc406Sopenharmony_ci } 494141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 495141cc406Sopenharmony_ci} 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci/** 498141cc406Sopenharmony_ci */ 499141cc406Sopenharmony_cistatic void 500141cc406Sopenharmony_ciusbGetList( DevList **devs ) 501141cc406Sopenharmony_ci{ 502141cc406Sopenharmony_ci int i; 503141cc406Sopenharmony_ci SANE_Bool il; 504141cc406Sopenharmony_ci SANE_Word v, p; 505141cc406Sopenharmony_ci DevList *tmp; 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci DBG( _DBG_INFO, "Retrieving all supported and conntected devices\n" ); 508141cc406Sopenharmony_ci for( i = 0; NULL != Settings[i].pIDString; i++ ) { 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci v = strtol( &(Settings[i].pIDString)[0], 0, 0 ); 511141cc406Sopenharmony_ci p = strtol( &(Settings[i].pIDString)[7], 0, 0 ); 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci /* check if this vendor- and product-ID has already been added, needed 514141cc406Sopenharmony_ci * for Plustek devices - here one product-ID is used for more than one 515141cc406Sopenharmony_ci * device type... 516141cc406Sopenharmony_ci */ 517141cc406Sopenharmony_ci il = SANE_FALSE; 518141cc406Sopenharmony_ci for( tmp = *devs; tmp ; tmp = tmp->next ) { 519141cc406Sopenharmony_ci if( tmp->device_id == p && tmp->vendor_id == v ) { 520141cc406Sopenharmony_ci il = SANE_TRUE; 521141cc406Sopenharmony_ci break; 522141cc406Sopenharmony_ci } 523141cc406Sopenharmony_ci } 524141cc406Sopenharmony_ci if( il ) { 525141cc406Sopenharmony_ci DBG( _DBG_INFO2, "Already in list: 0x%04x-0x%04x\n", v, p ); 526141cc406Sopenharmony_ci continue; 527141cc406Sopenharmony_ci } 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci /* get the last entry... */ 530141cc406Sopenharmony_ci tmp = getLast(*devs); 531141cc406Sopenharmony_ci DBG( _DBG_INFO2, "Checking for 0x%04x-0x%04x\n", v, p ); 532141cc406Sopenharmony_ci sanei_usb_find_devices( v, p, usb_attach ); 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci if( getLast(*devs) != tmp ) { 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci if( tmp == NULL ) 537141cc406Sopenharmony_ci tmp = *devs; 538141cc406Sopenharmony_ci else 539141cc406Sopenharmony_ci tmp = tmp->next; 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci while( tmp != NULL ) { 542141cc406Sopenharmony_ci tmp->vendor_id = v; 543141cc406Sopenharmony_ci tmp->device_id = p; 544141cc406Sopenharmony_ci tmp = tmp->next; 545141cc406Sopenharmony_ci } 546141cc406Sopenharmony_ci } 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci DBG( _DBG_INFO, "Available and supported devices:\n" ); 550141cc406Sopenharmony_ci if( *devs == NULL ) 551141cc406Sopenharmony_ci DBG( _DBG_INFO, "NONE.\n" ); 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci for( tmp = *devs; tmp; tmp = tmp->next ) { 554141cc406Sopenharmony_ci DBG( _DBG_INFO, "Device: >%s< - 0x%04xx0x%04x\n", 555141cc406Sopenharmony_ci tmp->dev_name, tmp->vendor_id, tmp->device_id ); 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci} 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci/** 560141cc406Sopenharmony_ci */ 561141cc406Sopenharmony_cistatic int usbDev_open( Plustek_Device *dev, DevList *devs, int keep_lock ) 562141cc406Sopenharmony_ci{ 563141cc406Sopenharmony_ci char dn[512]; 564141cc406Sopenharmony_ci char devStr[50]; 565141cc406Sopenharmony_ci int result; 566141cc406Sopenharmony_ci int i; 567141cc406Sopenharmony_ci int lc; 568141cc406Sopenharmony_ci SANE_Int handle; 569141cc406Sopenharmony_ci SANE_Byte version; 570141cc406Sopenharmony_ci SANE_Word vendor, product; 571141cc406Sopenharmony_ci SANE_Bool was_empty; 572141cc406Sopenharmony_ci SANE_Status status; 573141cc406Sopenharmony_ci DevList *tmp; 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_open(%s,%s) - %p\n", 576141cc406Sopenharmony_ci dev->name, dev->usbId, (void*)devs ); 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci /* preset our internal usb device structure */ 579141cc406Sopenharmony_ci memset( &dev->usbDev, 0, sizeof(DeviceDef)); 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci /* devs is NULL, when called from sane_start */ 582141cc406Sopenharmony_ci if( devs ) { 583141cc406Sopenharmony_ci 584141cc406Sopenharmony_ci dn[0] = '\0'; 585141cc406Sopenharmony_ci if( !strcmp( dev->name, "auto" )) { 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci /* use the first "unattached"... */ 588141cc406Sopenharmony_ci for( tmp = devs; tmp; tmp = tmp->next ) { 589141cc406Sopenharmony_ci if( !tmp->attached ) { 590141cc406Sopenharmony_ci tmp->attached = SANE_TRUE; 591141cc406Sopenharmony_ci strcpy( dn, tmp->dev_name ); 592141cc406Sopenharmony_ci break; 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci } 595141cc406Sopenharmony_ci } else { 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci vendor = strtol( &dev->usbId[0], 0, 0 ); 598141cc406Sopenharmony_ci product = strtol( &dev->usbId[7], 0, 0 ); 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci /* check the first match... */ 601141cc406Sopenharmony_ci for( tmp = devs; tmp; tmp = tmp->next ) { 602141cc406Sopenharmony_ci if( tmp->vendor_id == vendor && tmp->device_id == product ) { 603141cc406Sopenharmony_ci if( !tmp->attached ) { 604141cc406Sopenharmony_ci tmp->attached = SANE_TRUE; 605141cc406Sopenharmony_ci strcpy( dn, tmp->dev_name ); 606141cc406Sopenharmony_ci break; 607141cc406Sopenharmony_ci } 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci } 611141cc406Sopenharmony_ci 612141cc406Sopenharmony_ci if( !dn[0] ) { 613141cc406Sopenharmony_ci DBG( _DBG_ERROR, "No supported device found!\n" ); 614141cc406Sopenharmony_ci return -1; 615141cc406Sopenharmony_ci } 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci status = sanei_access_lock( dn, 5 ); 618141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) { 619141cc406Sopenharmony_ci DBG( _DBG_ERROR, "sanei_access_lock failed: %d\n", status ); 620141cc406Sopenharmony_ci return -1; 621141cc406Sopenharmony_ci } 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci status = sanei_usb_open( dn, &handle ); 624141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) { 625141cc406Sopenharmony_ci DBG( _DBG_ERROR, "sanei_usb_open failed: %s (%d)\n", 626141cc406Sopenharmony_ci strerror(errno), errno); 627141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 628141cc406Sopenharmony_ci return -1; 629141cc406Sopenharmony_ci } 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci /* replace the old devname, so we are able to have multiple 632141cc406Sopenharmony_ci * auto-detected devices 633141cc406Sopenharmony_ci */ 634141cc406Sopenharmony_ci free( dev->name ); 635141cc406Sopenharmony_ci dev->name = strdup(dn); 636141cc406Sopenharmony_ci dev->sane.name = dev->name; 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci } else { 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci status = sanei_access_lock( dev->sane.name, 5 ); 641141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) { 642141cc406Sopenharmony_ci DBG( _DBG_ERROR, "sanei_access_lock failed: %d\n", status ); 643141cc406Sopenharmony_ci return -1; 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci status = sanei_usb_open( dev->name, &handle ); 647141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) { 648141cc406Sopenharmony_ci DBG( _DBG_ERROR, "sanei_usb_open failed: %s (%d)\n", 649141cc406Sopenharmony_ci strerror(errno), errno); 650141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 651141cc406Sopenharmony_ci return -1; 652141cc406Sopenharmony_ci } 653141cc406Sopenharmony_ci } 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci was_empty = SANE_FALSE; 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci result = sanei_usb_get_vendor_product( handle, &vendor, &product ); 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci if( SANE_STATUS_GOOD == result ) { 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci sprintf( devStr, "0x%04X-0x%04X", vendor, product ); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci DBG(_DBG_INFO,"Vendor ID=0x%04X, Product ID=0x%04X\n",vendor,product); 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci if( dev->usbId[0] != '\0' ) { 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci if( 0 != strcmp( dev->usbId, devStr )) { 668141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Specified Vendor and Product ID " 669141cc406Sopenharmony_ci "doesn't match with the ones\n" 670141cc406Sopenharmony_ci "in the config file\n" ); 671141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 672141cc406Sopenharmony_ci sanei_usb_close( handle ); 673141cc406Sopenharmony_ci return -1; 674141cc406Sopenharmony_ci } 675141cc406Sopenharmony_ci } else { 676141cc406Sopenharmony_ci sprintf( dev->usbId, "0x%04X-0x%04X", vendor, product ); 677141cc406Sopenharmony_ci was_empty = SANE_TRUE; 678141cc406Sopenharmony_ci } 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci } else { 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci DBG( _DBG_INFO, "Can't get vendor & product ID from driver...\n" ); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci /* if the ioctl stuff is not supported by the kernel and we have 685141cc406Sopenharmony_ci * nothing specified, we have to give up... 686141cc406Sopenharmony_ci */ 687141cc406Sopenharmony_ci if( dev->usbId[0] == '\0' ) { 688141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Cannot autodetect Vendor an Product ID, " 689141cc406Sopenharmony_ci "please specify in config file.\n" ); 690141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 691141cc406Sopenharmony_ci sanei_usb_close( handle ); 692141cc406Sopenharmony_ci return -1; 693141cc406Sopenharmony_ci } 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci vendor = strtol( &dev->usbId[0], 0, 0 ); 696141cc406Sopenharmony_ci product = strtol( &dev->usbId[7], 0, 0 ); 697141cc406Sopenharmony_ci DBG( _DBG_INFO, "... using the specified: " 698141cc406Sopenharmony_ci "0x%04X-0x%04X\n", vendor, product ); 699141cc406Sopenharmony_ci } 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci /* before accessing the scanner, check if supported! 702141cc406Sopenharmony_ci */ 703141cc406Sopenharmony_ci if( !usb_IsDeviceInList( dev->usbId )) { 704141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Device >%s<, is not supported!\n", dev->usbId ); 705141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 706141cc406Sopenharmony_ci sanei_usb_close( handle ); 707141cc406Sopenharmony_ci return -1; 708141cc406Sopenharmony_ci } 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci status = usbio_DetectLM983x( handle, &version ); 711141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) { 712141cc406Sopenharmony_ci sanei_usb_close( handle ); 713141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 714141cc406Sopenharmony_ci return -1; 715141cc406Sopenharmony_ci } 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci if ((version < 3) || (version > 4)) { 718141cc406Sopenharmony_ci DBG( _DBG_ERROR, "This is not a LM9831 or LM9832 chip based scanner.\n" ); 719141cc406Sopenharmony_ci sanei_usb_close( handle ); 720141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 721141cc406Sopenharmony_ci return -1; 722141cc406Sopenharmony_ci } 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci /* need to set the handle and the detected chiptype... */ 725141cc406Sopenharmony_ci dev->fd = handle; 726141cc406Sopenharmony_ci dev->usbDev.HwSetting.chip = (version==3 ? _LM9831:_LM9832); 727141cc406Sopenharmony_ci usbio_ResetLM983x( dev ); 728141cc406Sopenharmony_ci dev->fd = -1; 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci dev->usbDev.vendor = vendor; 731141cc406Sopenharmony_ci dev->usbDev.product = product; 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci DBG( _DBG_INFO, "Detected vendor & product ID: " 734141cc406Sopenharmony_ci "0x%04X-0x%04X\n", vendor, product ); 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci /* 737141cc406Sopenharmony_ci * Plustek uses the misc IO 1/2 to get the PCB ID 738141cc406Sopenharmony_ci * (PCB = printed circuit board), so it's possible to have one 739141cc406Sopenharmony_ci * product ID and up to 7 different devices... 740141cc406Sopenharmony_ci */ 741141cc406Sopenharmony_ci if( 0x07B3 == vendor ) { 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci handle = usb_CheckForPlustekDevice( handle, dev ); 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ci if( was_empty ) 746141cc406Sopenharmony_ci dev->usbId[0] = '\0'; 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci if( handle >= 0 ) { 749141cc406Sopenharmony_ci if( !keep_lock ) 750141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 751141cc406Sopenharmony_ci return handle; 752141cc406Sopenharmony_ci } 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci } else { 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci /* now roam through the setting list... */ 757141cc406Sopenharmony_ci lc = 13; 758141cc406Sopenharmony_ci strncpy( devStr, dev->usbId, lc ); 759141cc406Sopenharmony_ci devStr[lc] = '\0'; 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci if( 0x400 == vendor ) { 762141cc406Sopenharmony_ci if((dev->adj.mov < 0) || (dev->adj.mov > 1)) { 763141cc406Sopenharmony_ci DBG(_DBG_INFO, "BearPaw MOV out of range: %d\n", dev->adj.mov); 764141cc406Sopenharmony_ci dev->adj.mov = 0; 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci sprintf( devStr, "%s-%d", dev->usbId, dev->adj.mov ); 767141cc406Sopenharmony_ci lc = strlen(devStr); 768141cc406Sopenharmony_ci DBG( _DBG_INFO, "BearPaw device: %s (%d)\n", devStr, lc ); 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci if( was_empty ) 772141cc406Sopenharmony_ci dev->usbId[0] = '\0'; 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci /* if we don't use the PCD ID extension... 775141cc406Sopenharmony_ci */ 776141cc406Sopenharmony_ci for( i = 0; NULL != Settings[i].pIDString; i++ ) { 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ci if( 0 == strncmp( Settings[i].pIDString, devStr, lc )) { 779141cc406Sopenharmony_ci DBG( _DBG_INFO, "Device description for >%s< found.\n", devStr ); 780141cc406Sopenharmony_ci usb_initDev( dev, i, handle, vendor ); 781141cc406Sopenharmony_ci if( !keep_lock ) 782141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 783141cc406Sopenharmony_ci return handle; 784141cc406Sopenharmony_ci } 785141cc406Sopenharmony_ci } 786141cc406Sopenharmony_ci } 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_ci sanei_access_unlock( dev->sane.name ); 789141cc406Sopenharmony_ci sanei_usb_close( handle ); 790141cc406Sopenharmony_ci DBG( _DBG_ERROR, "No matching device found >%s<\n", devStr ); 791141cc406Sopenharmony_ci return -1; 792141cc406Sopenharmony_ci} 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci/** 795141cc406Sopenharmony_ci */ 796141cc406Sopenharmony_cistatic int usbDev_close( Plustek_Device *dev ) 797141cc406Sopenharmony_ci{ 798141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_close()\n" ); 799141cc406Sopenharmony_ci sanei_usb_close( dev->fd ); 800141cc406Sopenharmony_ci dev->fd = -1; 801141cc406Sopenharmony_ci return 0; 802141cc406Sopenharmony_ci} 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci/** convert the stuff 805141cc406Sopenharmony_ci */ 806141cc406Sopenharmony_cistatic int usbDev_getCaps( Plustek_Device *dev ) 807141cc406Sopenharmony_ci{ 808141cc406Sopenharmony_ci DCapsDef *scaps = &dev->usbDev.Caps; 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_getCaps()\n" ); 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_ci dev->caps.dwFlag = 0; 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci if(((DEVCAPSFLAG_Positive & scaps->wFlags) && 815141cc406Sopenharmony_ci (DEVCAPSFLAG_Negative & scaps->wFlags)) || 816141cc406Sopenharmony_ci (DEVCAPSFLAG_TPA & scaps->wFlags)) { 817141cc406Sopenharmony_ci dev->caps.dwFlag |= SFLAG_TPA; 818141cc406Sopenharmony_ci } 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_ci dev->caps.wMaxExtentX = scaps->Normal.Size.x; 821141cc406Sopenharmony_ci dev->caps.wMaxExtentY = scaps->Normal.Size.y; 822141cc406Sopenharmony_ci return 0; 823141cc406Sopenharmony_ci} 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci/** usbDev_getCropInfo 826141cc406Sopenharmony_ci * function to set the image relevant stuff 827141cc406Sopenharmony_ci */ 828141cc406Sopenharmony_cistatic int usbDev_getCropInfo( Plustek_Device *dev, CropInfo *ci ) 829141cc406Sopenharmony_ci{ 830141cc406Sopenharmony_ci WinInfo size; 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_getCropInfo()\n" ); 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci usb_GetImageInfo( dev, &ci->ImgDef, &size ); 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci ci->dwPixelsPerLine = size.dwPixels; 837141cc406Sopenharmony_ci ci->dwLinesPerArea = size.dwLines; 838141cc406Sopenharmony_ci ci->dwBytesPerLine = size.dwBytes; 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci if( ci->ImgDef.dwFlag & SCANFLAG_DWORDBoundary ) 841141cc406Sopenharmony_ci ci->dwBytesPerLine = (ci->dwBytesPerLine + 3UL) & 0xfffffffcUL; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci DBG( _DBG_INFO, "PPL = %lu\n", ci->dwPixelsPerLine ); 844141cc406Sopenharmony_ci DBG( _DBG_INFO, "LPA = %lu\n", ci->dwLinesPerArea ); 845141cc406Sopenharmony_ci DBG( _DBG_INFO, "BPL = %lu\n", ci->dwBytesPerLine ); 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci return 0; 848141cc406Sopenharmony_ci} 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci/** 851141cc406Sopenharmony_ci */ 852141cc406Sopenharmony_cistatic int usbDev_setMap( Plustek_Device *dev, SANE_Word *map, 853141cc406Sopenharmony_ci SANE_Word length, SANE_Word channel ) 854141cc406Sopenharmony_ci{ 855141cc406Sopenharmony_ci SANE_Word i, idx; 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci DBG(_DBG_INFO,"Setting map[%u] at 0x%08lx\n",channel,(unsigned long)map); 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ci _VAR_NOT_USED( dev ); 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci if( channel == _MAP_MASTER ) { 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci for( i = 0; i < length; i++ ) { 864141cc406Sopenharmony_ci a_bMap[i] = (SANE_Byte)map[i]; 865141cc406Sopenharmony_ci a_bMap[length +i] = (SANE_Byte)map[i]; 866141cc406Sopenharmony_ci a_bMap[(length*2)+i] = (SANE_Byte)map[i]; 867141cc406Sopenharmony_ci } 868141cc406Sopenharmony_ci 869141cc406Sopenharmony_ci } else { 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci idx = 0; 872141cc406Sopenharmony_ci if( channel == _MAP_GREEN ) 873141cc406Sopenharmony_ci idx = 1; 874141cc406Sopenharmony_ci if( channel == _MAP_BLUE ) 875141cc406Sopenharmony_ci idx = 2; 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci for( i = 0; i < length; i++ ) { 878141cc406Sopenharmony_ci a_bMap[(length * idx)+i] = (SANE_Byte)map[i]; 879141cc406Sopenharmony_ci } 880141cc406Sopenharmony_ci } 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_ci return 0; 883141cc406Sopenharmony_ci} 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci/** 886141cc406Sopenharmony_ci */ 887141cc406Sopenharmony_cistatic int 888141cc406Sopenharmony_ciusbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si ) 889141cc406Sopenharmony_ci{ 890141cc406Sopenharmony_ci ScanDef *scan = &dev->scanning; 891141cc406Sopenharmony_ci DCapsDef *caps = &dev->usbDev.Caps; 892141cc406Sopenharmony_ci 893141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_setScanEnv()\n" ); 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci /* clear all the stuff */ 896141cc406Sopenharmony_ci memset( scan, 0, sizeof(ScanDef)); 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci if((si->ImgDef.dwFlag & SCANDEF_Adf) && 899141cc406Sopenharmony_ci (si->ImgDef.dwFlag & SCANDEF_ContinuousScan)) { 900141cc406Sopenharmony_ci scan->sParam.dMCLK = dMCLK_ADF; 901141cc406Sopenharmony_ci } 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci /* Save necessary information */ 904141cc406Sopenharmony_ci scan->fGrayFromColor = 0; 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci /* for some devices and settings, we tweak the physical settings 907141cc406Sopenharmony_ci * how to get the image - but not in calibration mode 908141cc406Sopenharmony_ci */ 909141cc406Sopenharmony_ci if((si->ImgDef.dwFlag & SCANFLAG_Calibration) == 0) { 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci if( si->ImgDef.wDataType == COLOR_256GRAY ) { 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci if( !(si->ImgDef.dwFlag & SCANDEF_Adf) && !usb_IsCISDevice(dev) && 914141cc406Sopenharmony_ci (caps->OpticDpi.x == 1200 && si->ImgDef.xyDpi.x <= 300)) { 915141cc406Sopenharmony_ci scan->fGrayFromColor = 2; 916141cc406Sopenharmony_ci si->ImgDef.wDataType = COLOR_TRUE24; 917141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Gray from color set!\n" ); 918141cc406Sopenharmony_ci } 919141cc406Sopenharmony_ci 920141cc406Sopenharmony_ci if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) { 921141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Gray(8-bit) from color set!\n" ); 922141cc406Sopenharmony_ci scan->fGrayFromColor = 2; 923141cc406Sopenharmony_ci si->ImgDef.wDataType = COLOR_TRUE24; 924141cc406Sopenharmony_ci } 925141cc406Sopenharmony_ci 926141cc406Sopenharmony_ci } else if ( si->ImgDef.wDataType == COLOR_GRAY16 ) { 927141cc406Sopenharmony_ci if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) { 928141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Gray(16-bit) from color set!\n" ); 929141cc406Sopenharmony_ci scan->fGrayFromColor = 2; 930141cc406Sopenharmony_ci si->ImgDef.wDataType = COLOR_TRUE48; 931141cc406Sopenharmony_ci } 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci } else if ( si->ImgDef.wDataType == COLOR_BW ) { 934141cc406Sopenharmony_ci if( caps->workaroundFlag & _WAF_BIN_FROM_COLOR ) { 935141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Binary from color set!\n" ); 936141cc406Sopenharmony_ci scan->fGrayFromColor = 10; 937141cc406Sopenharmony_ci si->ImgDef.wDataType = COLOR_TRUE24; 938141cc406Sopenharmony_ci } 939141cc406Sopenharmony_ci } 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci usb_SaveImageInfo( dev, &si->ImgDef ); 943141cc406Sopenharmony_ci usb_GetImageInfo ( dev, &si->ImgDef, &scan->sParam.Size ); 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci /* mask the flags */ 946141cc406Sopenharmony_ci scan->dwFlag = si->ImgDef.dwFlag & 947141cc406Sopenharmony_ci (SCANFLAG_bgr | SCANFLAG_BottomUp | SCANFLAG_Calibration | 948141cc406Sopenharmony_ci SCANFLAG_DWORDBoundary | SCANFLAG_RightAlign | 949141cc406Sopenharmony_ci SCANFLAG_StillModule | SCANDEF_Adf | SCANDEF_ContinuousScan); 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci if( !(SCANDEF_QualityScan & si->ImgDef.dwFlag)) { 952141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Preview Mode set!\n" ); 953141cc406Sopenharmony_ci } else { 954141cc406Sopenharmony_ci DBG( _DBG_INFO, "* Preview Mode NOT set!\n" ); 955141cc406Sopenharmony_ci scan->dwFlag |= SCANDEF_QualityScan; 956141cc406Sopenharmony_ci } 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci scan->sParam.brightness = si->siBrightness; 959141cc406Sopenharmony_ci scan->sParam.contrast = si->siContrast; 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci if( scan->sParam.bBitDepth <= 8 ) 962141cc406Sopenharmony_ci scan->dwFlag &= ~SCANFLAG_RightAlign; 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci if( scan->dwFlag & SCANFLAG_DWORDBoundary ) { 965141cc406Sopenharmony_ci if( scan->fGrayFromColor && scan->fGrayFromColor < 10) 966141cc406Sopenharmony_ci scan->dwBytesLine = (scan->sParam.Size.dwBytes / 3 + 3) & 0xfffffffcUL; 967141cc406Sopenharmony_ci else 968141cc406Sopenharmony_ci scan->dwBytesLine = (scan->sParam.Size.dwBytes + 3UL) & 0xfffffffcUL; 969141cc406Sopenharmony_ci 970141cc406Sopenharmony_ci } else { 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci if( scan->fGrayFromColor && scan->fGrayFromColor < 10) 973141cc406Sopenharmony_ci scan->dwBytesLine = scan->sParam.Size.dwBytes / 3; 974141cc406Sopenharmony_ci else 975141cc406Sopenharmony_ci scan->dwBytesLine = scan->sParam.Size.dwBytes; 976141cc406Sopenharmony_ci } 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci /* on CIS based devices we have to reconfigure the illumination 979141cc406Sopenharmony_ci * settings for the gray modes 980141cc406Sopenharmony_ci */ 981141cc406Sopenharmony_ci usb_AdjustCISLampSettings( dev, SANE_TRUE ); 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci if( scan->dwFlag & SCANFLAG_BottomUp) 984141cc406Sopenharmony_ci scan->lBufAdjust = -(long)scan->dwBytesLine; 985141cc406Sopenharmony_ci else 986141cc406Sopenharmony_ci scan->lBufAdjust = scan->dwBytesLine; 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci /* LM9831 has a BUG in 16-bit mode, 989141cc406Sopenharmony_ci * so we generate pseudo 16-bit data from 8-bit 990141cc406Sopenharmony_ci */ 991141cc406Sopenharmony_ci if( scan->sParam.bBitDepth > 8 ) { 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci if( _LM9831 == dev->usbDev.HwSetting.chip ) { 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci scan->sParam.bBitDepth = 8; 996141cc406Sopenharmony_ci scan->dwFlag |= SCANFLAG_Pseudo48; 997141cc406Sopenharmony_ci scan->sParam.Size.dwBytes >>= 1; 998141cc406Sopenharmony_ci } 999141cc406Sopenharmony_ci } 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci /* Source selection */ 1002141cc406Sopenharmony_ci if( scan->sParam.bSource == SOURCE_Reflection ) { 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci dev->usbDev.pSource = &caps->Normal; 1005141cc406Sopenharmony_ci scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + 1006141cc406Sopenharmony_ci (u_long)dev->usbDev.Normal.lLeft; 1007141cc406Sopenharmony_ci scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + 1008141cc406Sopenharmony_ci (u_long)dev->usbDev.Normal.lUp; 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci } else if( scan->sParam.bSource == SOURCE_Transparency ) { 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci dev->usbDev.pSource = &caps->Positive; 1013141cc406Sopenharmony_ci scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + 1014141cc406Sopenharmony_ci (u_long)dev->usbDev.Positive.lLeft; 1015141cc406Sopenharmony_ci scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + 1016141cc406Sopenharmony_ci (u_long)dev->usbDev.Positive.lUp; 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci } else if( scan->sParam.bSource == SOURCE_Negative ) { 1019141cc406Sopenharmony_ci 1020141cc406Sopenharmony_ci dev->usbDev.pSource = &caps->Negative; 1021141cc406Sopenharmony_ci scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + 1022141cc406Sopenharmony_ci (u_long)dev->usbDev.Negative.lLeft; 1023141cc406Sopenharmony_ci scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + 1024141cc406Sopenharmony_ci (u_long)dev->usbDev.Negative.lUp; 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci } else { 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci dev->usbDev.pSource = &dev->usbDev.Caps.Adf; 1029141cc406Sopenharmony_ci scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + 1030141cc406Sopenharmony_ci (u_long)dev->usbDev.Normal.lLeft; 1031141cc406Sopenharmony_ci scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + 1032141cc406Sopenharmony_ci (u_long)dev->usbDev.Normal.lUp; 1033141cc406Sopenharmony_ci } 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci if( scan->sParam.bSource == SOURCE_ADF ) { 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci if( scan->dwFlag & SCANDEF_ContinuousScan ) 1038141cc406Sopenharmony_ci dev->usbDev.fLastScanIsAdf = SANE_TRUE; 1039141cc406Sopenharmony_ci else 1040141cc406Sopenharmony_ci dev->usbDev.fLastScanIsAdf = SANE_FALSE; 1041141cc406Sopenharmony_ci } 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci return 0; 1044141cc406Sopenharmony_ci} 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci/** 1047141cc406Sopenharmony_ci */ 1048141cc406Sopenharmony_cistatic int 1049141cc406Sopenharmony_ciusbDev_stopScan( Plustek_Device *dev ) 1050141cc406Sopenharmony_ci{ 1051141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_stopScan()\n" ); 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci /* in cancel-mode we first stop the motor */ 1054141cc406Sopenharmony_ci usb_ScanEnd( dev ); 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci dev->scanning.dwFlag = 0; 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci if( NULL != dev->scanning.pScanBuffer ) { 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci free( dev->scanning.pScanBuffer ); 1061141cc406Sopenharmony_ci dev->scanning.pScanBuffer = NULL; 1062141cc406Sopenharmony_ci usb_StartLampTimer( dev ); 1063141cc406Sopenharmony_ci } 1064141cc406Sopenharmony_ci return 0; 1065141cc406Sopenharmony_ci} 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci/** 1068141cc406Sopenharmony_ci */ 1069141cc406Sopenharmony_cistatic int 1070141cc406Sopenharmony_ciusbDev_startScan( Plustek_Device *dev ) 1071141cc406Sopenharmony_ci{ 1072141cc406Sopenharmony_ci ScanDef *scan = &dev->scanning; 1073141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_startScan()\n" ); 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci/* HEINER: Preview currently not working correctly */ 1076141cc406Sopenharmony_ci#if 0 1077141cc406Sopenharmony_ci if( scan->dwFlag & SCANDEF_QualityScan ) 1078141cc406Sopenharmony_ci dev->usbDev.a_bRegs[0x0a] = 0; 1079141cc406Sopenharmony_ci else 1080141cc406Sopenharmony_ci dev->usbDev.a_bRegs[0x0a] = 1; 1081141cc406Sopenharmony_ci#endif 1082141cc406Sopenharmony_ci dev->usbDev.a_bRegs[0x0a] = 0; 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_ci if((scan->dwFlag & SCANDEF_Adf) && (scan->dwFlag & SCANDEF_ContinuousScan)) { 1085141cc406Sopenharmony_ci scan->fCalibrated = SANE_TRUE; 1086141cc406Sopenharmony_ci } else { 1087141cc406Sopenharmony_ci scan->fCalibrated = SANE_FALSE; 1088141cc406Sopenharmony_ci } 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci scan->sParam.PhyDpi.x = usb_SetAsicDpiX(dev,scan->sParam.UserDpi.x); 1091141cc406Sopenharmony_ci scan->sParam.PhyDpi.y = usb_SetAsicDpiY(dev,scan->sParam.UserDpi.y); 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_ci /* Allocate shading/scan buffer */ 1094141cc406Sopenharmony_ci scan->pScanBuffer = (u_long*)malloc( _SCANBUF_SIZE ); 1095141cc406Sopenharmony_ci 1096141cc406Sopenharmony_ci if( scan->pScanBuffer == NULL ) 1097141cc406Sopenharmony_ci return _E_ALLOC; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci scan->dwFlag |= SCANFLAG_StartScan; 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci /* some devices (esp. BearPaw) do need a lamp switch off before 1102141cc406Sopenharmony_ci * switching it on again. Otherwise it might happen that the lamp 1103141cc406Sopenharmony_ci * remains off 1104141cc406Sopenharmony_ci */ 1105141cc406Sopenharmony_ci if(dev->usbDev.Caps.workaroundFlag & _WAF_LOFF_ON_START) { 1106141cc406Sopenharmony_ci if (usb_GetLampStatus(dev)) 1107141cc406Sopenharmony_ci usb_LampOn( dev, SANE_FALSE, SANE_TRUE ); 1108141cc406Sopenharmony_ci } 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci usb_LampOn( dev, SANE_TRUE, SANE_TRUE ); 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_ci m_fStart = m_fFirst = SANE_TRUE; 1113141cc406Sopenharmony_ci m_fAutoPark = (scan->dwFlag&SCANFLAG_StillModule)?SANE_FALSE:SANE_TRUE; 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci if( usb_IsSheetFedDevice(dev)) 1116141cc406Sopenharmony_ci if(usb_InCalibrationMode(dev)) 1117141cc406Sopenharmony_ci m_fAutoPark = SANE_FALSE; 1118141cc406Sopenharmony_ci 1119141cc406Sopenharmony_ci usb_StopLampTimer( dev ); 1120141cc406Sopenharmony_ci return 0; 1121141cc406Sopenharmony_ci} 1122141cc406Sopenharmony_ci 1123141cc406Sopenharmony_ci/** 1124141cc406Sopenharmony_ci * do the reading stuff here... 1125141cc406Sopenharmony_ci * first we perform the calibration step, and then we read the image 1126141cc406Sopenharmony_ci * line for line 1127141cc406Sopenharmony_ci */ 1128141cc406Sopenharmony_cistatic int 1129141cc406Sopenharmony_ciusbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf ) 1130141cc406Sopenharmony_ci{ 1131141cc406Sopenharmony_ci int result; 1132141cc406Sopenharmony_ci SANE_Bool use_alt_cal = SANE_FALSE; 1133141cc406Sopenharmony_ci ScanDef *scan = &dev->scanning; 1134141cc406Sopenharmony_ci DCapsDef *scaps = &dev->usbDev.Caps; 1135141cc406Sopenharmony_ci HWDef *hw = &dev->usbDev.HwSetting; 1136141cc406Sopenharmony_ci 1137141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_PrepareScan()\n" ); 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci /* check the current position of the sensor and move it back 1140141cc406Sopenharmony_ci * to it's home position if necessary... 1141141cc406Sopenharmony_ci */ 1142141cc406Sopenharmony_ci if( !usb_IsSheetFedDevice(dev)) 1143141cc406Sopenharmony_ci usb_SensorStatus( dev ); 1144141cc406Sopenharmony_ci 1145141cc406Sopenharmony_ci /* CIS devices need special handling... */ 1146141cc406Sopenharmony_ci if( usb_IsCISDevice(dev)) { 1147141cc406Sopenharmony_ci use_alt_cal = SANE_TRUE; 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci } else { 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci if( dev->adj.altCalibrate ) 1152141cc406Sopenharmony_ci use_alt_cal = SANE_TRUE; 1153141cc406Sopenharmony_ci } 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci /* for the skip functionality use the "old" calibration functions */ 1156141cc406Sopenharmony_ci if( dev->usbDev.Caps.workaroundFlag & _WAF_BYPASS_CALIBRATION ) { 1157141cc406Sopenharmony_ci use_alt_cal = SANE_FALSE; 1158141cc406Sopenharmony_ci } 1159141cc406Sopenharmony_ci 1160141cc406Sopenharmony_ci if( use_alt_cal ) { 1161141cc406Sopenharmony_ci result = cano_DoCalibration( dev ); 1162141cc406Sopenharmony_ci } else { 1163141cc406Sopenharmony_ci result = usb_DoCalibration( dev ); 1164141cc406Sopenharmony_ci } 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci if( SANE_TRUE != result ) { 1167141cc406Sopenharmony_ci DBG( _DBG_ERROR, "calibration failed!!!\n" ); 1168141cc406Sopenharmony_ci return _E_ABORT; 1169141cc406Sopenharmony_ci } 1170141cc406Sopenharmony_ci 1171141cc406Sopenharmony_ci if( dev->adj.cacheCalData ) 1172141cc406Sopenharmony_ci usb_SaveCalData( dev ); 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci DBG( _DBG_INFO, "calibration done.\n" ); 1175141cc406Sopenharmony_ci if( usb_InCalibrationMode(dev)) 1176141cc406Sopenharmony_ci return 0; 1177141cc406Sopenharmony_ci 1178141cc406Sopenharmony_ci if( !(scan->dwFlag & SCANFLAG_Scanning)) { 1179141cc406Sopenharmony_ci 1180141cc406Sopenharmony_ci usleep( 10 * 1000 ); 1181141cc406Sopenharmony_ci 1182141cc406Sopenharmony_ci /* need to preset that here, as we need it during parameter setting 1183141cc406Sopenharmony_ci */ 1184141cc406Sopenharmony_ci scan->bLinesToSkip = (u_char)(scan->sParam.PhyDpi.y / 50); 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci scan->dwLinesDiscard = 0; 1187141cc406Sopenharmony_ci if( scan->sParam.bChannels == 3 ) { 1188141cc406Sopenharmony_ci scan->dwLinesDiscard = (u_long)scaps->bSensorDistance * 1189141cc406Sopenharmony_ci scan->sParam.PhyDpi.y / scaps->OpticDpi.y; 1190141cc406Sopenharmony_ci scan->dwLinesDiscard <<= 1; 1191141cc406Sopenharmony_ci } 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci if( !usb_SetScanParameters( dev, &scan->sParam )) { 1194141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Setting Scan Parameters failed!\n" ); 1195141cc406Sopenharmony_ci return 0; 1196141cc406Sopenharmony_ci } 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci /* if we bypass the calibration step, we wait on lamp warmup here... 1199141cc406Sopenharmony_ci */ 1200141cc406Sopenharmony_ci if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION ) { 1201141cc406Sopenharmony_ci if( !usb_Wait4Warmup( dev )) { 1202141cc406Sopenharmony_ci DBG( _DBG_INFO, "usbDev_Prepare() - Cancel detected...\n" ); 1203141cc406Sopenharmony_ci return 0; 1204141cc406Sopenharmony_ci } 1205141cc406Sopenharmony_ci } 1206141cc406Sopenharmony_ci 1207141cc406Sopenharmony_ci scan->pbScanBufBegin = (u_char*)scan->pScanBuffer; 1208141cc406Sopenharmony_ci 1209141cc406Sopenharmony_ci if((dev->caps.dwFlag & SFLAG_ADF) && (scaps->OpticDpi.x == 600)) 1210141cc406Sopenharmony_ci scan->dwLinesScanBuf = 8; 1211141cc406Sopenharmony_ci else 1212141cc406Sopenharmony_ci scan->dwLinesScanBuf = 32; 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci scan->dwBytesScanBuf = scan->dwLinesScanBuf * 1215141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci scan->dwNumberOfScanBufs = _SCANBUF_SIZE / scan->dwBytesScanBuf; 1218141cc406Sopenharmony_ci scan->dwLinesPerScanBufs = scan->dwNumberOfScanBufs * 1219141cc406Sopenharmony_ci scan->dwLinesScanBuf; 1220141cc406Sopenharmony_ci scan->pbScanBufEnd = scan->pbScanBufBegin + 1221141cc406Sopenharmony_ci scan->dwLinesPerScanBufs * 1222141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1223141cc406Sopenharmony_ci scan->dwRedShift = 0; 1224141cc406Sopenharmony_ci scan->dwBlueShift = 0; 1225141cc406Sopenharmony_ci scan->dwGreenShift = 0; 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci /* CCD scanner */ 1228141cc406Sopenharmony_ci if( scan->sParam.bChannels == 3 ) { 1229141cc406Sopenharmony_ci 1230141cc406Sopenharmony_ci scan->dwLinesDiscard = (u_long)scaps->bSensorDistance * 1231141cc406Sopenharmony_ci scan->sParam.PhyDpi.y / scaps->OpticDpi.y; 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci switch( scaps->bSensorOrder ) { 1234141cc406Sopenharmony_ci 1235141cc406Sopenharmony_ci case SENSORORDER_rgb: 1236141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin; 1237141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1238141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1239141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1240141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1241141cc406Sopenharmony_ci break; 1242141cc406Sopenharmony_ci 1243141cc406Sopenharmony_ci case SENSORORDER_rbg: 1244141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin; 1245141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1246141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1247141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1248141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1249141cc406Sopenharmony_ci break; 1250141cc406Sopenharmony_ci 1251141cc406Sopenharmony_ci case SENSORORDER_gbr: 1252141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin; 1253141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1254141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1255141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1256141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1257141cc406Sopenharmony_ci break; 1258141cc406Sopenharmony_ci 1259141cc406Sopenharmony_ci case SENSORORDER_grb: 1260141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin; 1261141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1262141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1263141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1264141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1265141cc406Sopenharmony_ci break; 1266141cc406Sopenharmony_ci 1267141cc406Sopenharmony_ci case SENSORORDER_brg: 1268141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin; 1269141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1270141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1271141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1272141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1273141cc406Sopenharmony_ci break; 1274141cc406Sopenharmony_ci 1275141cc406Sopenharmony_ci case SENSORORDER_bgr: 1276141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin; 1277141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1278141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes; 1279141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * 1280141cc406Sopenharmony_ci scan->sParam.Size.dwPhyBytes * 2UL; 1281141cc406Sopenharmony_ci } 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci /* double it for last channel */ 1284141cc406Sopenharmony_ci scan->dwLinesDiscard <<= 1; 1285141cc406Sopenharmony_ci scan->dwGreenShift = (7UL+scan->sParam.bBitDepth) >> 3; 1286141cc406Sopenharmony_ci scan->Green.pb += scan->dwGreenShift; 1287141cc406Sopenharmony_ci scan->Blue.pb += (scan->dwGreenShift * 2); 1288141cc406Sopenharmony_ci 1289141cc406Sopenharmony_ci if( scan->dwFlag & SCANFLAG_bgr) { 1290141cc406Sopenharmony_ci 1291141cc406Sopenharmony_ci u_char *pb = scan->Blue.pb; 1292141cc406Sopenharmony_ci 1293141cc406Sopenharmony_ci scan->Blue.pb = scan->Red.pb; 1294141cc406Sopenharmony_ci scan->Red.pb = pb; 1295141cc406Sopenharmony_ci scan->dwBlueShift = 0; 1296141cc406Sopenharmony_ci scan->dwRedShift = scan->dwGreenShift << 1; 1297141cc406Sopenharmony_ci } else { 1298141cc406Sopenharmony_ci scan->dwRedShift = 0; 1299141cc406Sopenharmony_ci scan->dwBlueShift = scan->dwGreenShift << 1; 1300141cc406Sopenharmony_ci } 1301141cc406Sopenharmony_ci 1302141cc406Sopenharmony_ci } else { 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci /* CIS section */ 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ci /* this might be a simple gray operation or AFE 1 channel op */ 1307141cc406Sopenharmony_ci scan->dwLinesDiscard = 0; 1308141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin; 1309141cc406Sopenharmony_ci 1310141cc406Sopenharmony_ci if(( scan->sParam.bDataType == SCANDATATYPE_Color ) && 1311141cc406Sopenharmony_ci ( hw->bReg_0x26 & _ONE_CH_COLOR )) { 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci u_char so; 1314141cc406Sopenharmony_ci u_long len = scan->sParam.Size.dwPhyBytes / 3; 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci so = scaps->bSensorOrder; 1317141cc406Sopenharmony_ci if (_WAF_RESET_SO_TO_RGB & scaps->workaroundFlag) { 1318141cc406Sopenharmony_ci if (scaps->bPCB != 0) { 1319141cc406Sopenharmony_ci if (scan->sParam.PhyDpi.x > scaps->bPCB) { 1320141cc406Sopenharmony_ci so = SENSORORDER_rgb; 1321141cc406Sopenharmony_ci DBG(_DBG_INFO, "* Resetting sensororder to RGB\n"); 1322141cc406Sopenharmony_ci } 1323141cc406Sopenharmony_ci } 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci switch( so ) { 1327141cc406Sopenharmony_ci 1328141cc406Sopenharmony_ci case SENSORORDER_rgb: 1329141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin; 1330141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + len; 1331141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + len * 2UL; 1332141cc406Sopenharmony_ci break; 1333141cc406Sopenharmony_ci 1334141cc406Sopenharmony_ci case SENSORORDER_gbr: 1335141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin; 1336141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + len; 1337141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + len * 2UL; 1338141cc406Sopenharmony_ci break; 1339141cc406Sopenharmony_ci default: 1340141cc406Sopenharmony_ci DBG( _DBG_ERROR, "CIS: This bSensorOrder " 1341141cc406Sopenharmony_ci "is not defined\n" ); 1342141cc406Sopenharmony_ci return _E_INTERNAL; 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci } 1345141cc406Sopenharmony_ci } 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci /* set a function to process the RAW data... */ 1348141cc406Sopenharmony_ci usb_GetImageProc( dev ); 1349141cc406Sopenharmony_ci 1350141cc406Sopenharmony_ci if( scan->sParam.bSource == SOURCE_ADF ) 1351141cc406Sopenharmony_ci scan->dwFlag |= SCANFLAG_StillModule; 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ci DBG( _DBG_INFO, "* scan->dwFlag=0x%08lx\n", scan->dwFlag ); 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci if( !usb_ScanBegin( dev, 1356141cc406Sopenharmony_ci (scan->dwFlag&SCANFLAG_StillModule) ? SANE_FALSE:SANE_TRUE)) { 1357141cc406Sopenharmony_ci 1358141cc406Sopenharmony_ci return _E_INTERNAL; 1359141cc406Sopenharmony_ci } 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci scan->dwFlag |= SCANFLAG_Scanning; 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci if( scan->sParam.UserDpi.y != scan->sParam.PhyDpi.y ) { 1364141cc406Sopenharmony_ci 1365141cc406Sopenharmony_ci if( scan->sParam.UserDpi.y < scan->sParam.PhyDpi.y ) { 1366141cc406Sopenharmony_ci 1367141cc406Sopenharmony_ci scan->wSumY = scan->sParam.PhyDpi.y - scan->sParam.UserDpi.y; 1368141cc406Sopenharmony_ci scan->dwFlag |= SCANFLAG_SampleY; 1369141cc406Sopenharmony_ci DBG( _DBG_INFO, "SampleY Flag set (%u != %u, wSumY=%u)\n", 1370141cc406Sopenharmony_ci scan->sParam.UserDpi.y, scan->sParam.PhyDpi.y, scan->wSumY ); 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci } 1373141cc406Sopenharmony_ci } 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_ci dumpPicInit( &scan->sParam, "plustek-pic.raw" ); 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci /* here the NT driver uses an extra reading thread... 1378141cc406Sopenharmony_ci * as the SANE stuff already forked the driver to read data, I think 1379141cc406Sopenharmony_ci * we should only read data by using a function... 1380141cc406Sopenharmony_ci */ 1381141cc406Sopenharmony_ci scan->dwLinesUser = scan->sParam.Size.dwLines; 1382141cc406Sopenharmony_ci if( !scan->dwLinesUser ) 1383141cc406Sopenharmony_ci return _E_BUFFER_TOO_SMALL; 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci if( scan->sParam.Size.dwLines < scan->dwLinesUser ) 1386141cc406Sopenharmony_ci scan->dwLinesUser = scan->sParam.Size.dwLines; 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci scan->sParam.Size.dwLines -= scan->dwLinesUser; 1389141cc406Sopenharmony_ci if( scan->dwFlag & SCANFLAG_BottomUp ) 1390141cc406Sopenharmony_ci scan->UserBuf.pb = buf + (scan->dwLinesUser - 1) * scan->dwBytesLine; 1391141cc406Sopenharmony_ci else 1392141cc406Sopenharmony_ci scan->UserBuf.pb = buf; 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci DBG(_DBG_INFO,"Reading the data now!\n" ); 1395141cc406Sopenharmony_ci DBG(_DBG_INFO,"PhyDpi.x = %u\n", scan->sParam.PhyDpi.x ); 1396141cc406Sopenharmony_ci DBG(_DBG_INFO,"PhyDpi.y = %u\n", scan->sParam.PhyDpi.y ); 1397141cc406Sopenharmony_ci DBG(_DBG_INFO,"UserDpi.x = %u\n", scan->sParam.UserDpi.x ); 1398141cc406Sopenharmony_ci DBG(_DBG_INFO,"UserDpi.y = %u\n", scan->sParam.UserDpi.y ); 1399141cc406Sopenharmony_ci DBG(_DBG_INFO,"NumberOfScanBufs = %lu\n",scan->dwNumberOfScanBufs); 1400141cc406Sopenharmony_ci DBG(_DBG_INFO,"LinesPerScanBufs = %lu\n",scan->dwLinesPerScanBufs); 1401141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwPhyBytes = %lu\n",scan->sParam.Size.dwPhyBytes); 1402141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwPhyPixels = %lu\n",scan->sParam.Size.dwPhyPixels); 1403141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwTotalBytes = %lu\n",scan->sParam.Size.dwTotalBytes); 1404141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwPixels = %lu\n",scan->sParam.Size.dwPixels); 1405141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwBytes = %lu\n",scan->sParam.Size.dwBytes); 1406141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwValidPixels = %lu\n",scan->sParam.Size.dwValidPixels); 1407141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwBytesScanBuf = %lu\n",scan->dwBytesScanBuf ); 1408141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwLinesDiscard = %lu\n",scan->dwLinesDiscard ); 1409141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwLinesToSkip = %u\n", scan->bLinesToSkip ); 1410141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwLinesUser = %lu\n",scan->dwLinesUser ); 1411141cc406Sopenharmony_ci DBG(_DBG_INFO,"dwBytesLine = %lu\n",scan->dwBytesLine ); 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci scan->pbGetDataBuf = scan->pbScanBufBegin; 1414141cc406Sopenharmony_ci 1415141cc406Sopenharmony_ci scan->dwLinesToProcess = usb_ReadData( dev ); 1416141cc406Sopenharmony_ci if( 0 == scan->dwLinesToProcess ) 1417141cc406Sopenharmony_ci return _E_DATAREAD; 1418141cc406Sopenharmony_ci 1419141cc406Sopenharmony_ci return 0; 1420141cc406Sopenharmony_ci} 1421141cc406Sopenharmony_ci 1422141cc406Sopenharmony_ci/** as the name says, read one line... 1423141cc406Sopenharmony_ci */ 1424141cc406Sopenharmony_cistatic int 1425141cc406Sopenharmony_ciusbDev_ReadLine( Plustek_Device *dev ) 1426141cc406Sopenharmony_ci{ 1427141cc406Sopenharmony_ci int wrap; 1428141cc406Sopenharmony_ci u_long cur; 1429141cc406Sopenharmony_ci ScanDef *scan = &dev->scanning; 1430141cc406Sopenharmony_ci HWDef *hw = &dev->usbDev.HwSetting; 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci cur = scan->dwLinesUser; 1433141cc406Sopenharmony_ci 1434141cc406Sopenharmony_ci /* we stay within this sample loop until one line has been processed for 1435141cc406Sopenharmony_ci * the user... 1436141cc406Sopenharmony_ci */ 1437141cc406Sopenharmony_ci while( cur == scan->dwLinesUser ) { 1438141cc406Sopenharmony_ci 1439141cc406Sopenharmony_ci if( usb_IsEscPressed()) { 1440141cc406Sopenharmony_ci DBG( _DBG_INFO, "readLine() - Cancel detected...\n" ); 1441141cc406Sopenharmony_ci return _E_ABORT; 1442141cc406Sopenharmony_ci } 1443141cc406Sopenharmony_ci 1444141cc406Sopenharmony_ci if( !(scan->dwFlag & SCANFLAG_SampleY)) { 1445141cc406Sopenharmony_ci 1446141cc406Sopenharmony_ci scan->pfnProcess( dev ); 1447141cc406Sopenharmony_ci 1448141cc406Sopenharmony_ci /* Adjust user buffer pointer */ 1449141cc406Sopenharmony_ci scan->UserBuf.pb += scan->lBufAdjust; 1450141cc406Sopenharmony_ci scan->dwLinesUser--; 1451141cc406Sopenharmony_ci 1452141cc406Sopenharmony_ci } else { 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ci scan->wSumY += scan->sParam.UserDpi.y; 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci if( scan->wSumY >= scan->sParam.PhyDpi.y ) { 1457141cc406Sopenharmony_ci scan->wSumY -= scan->sParam.PhyDpi.y; 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci scan->pfnProcess( dev ); 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci /* Adjust user buffer pointer */ 1462141cc406Sopenharmony_ci scan->UserBuf.pb += scan->lBufAdjust; 1463141cc406Sopenharmony_ci scan->dwLinesUser--; 1464141cc406Sopenharmony_ci } 1465141cc406Sopenharmony_ci } 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ci /* Adjust get buffer pointers */ 1468141cc406Sopenharmony_ci wrap = 0; 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci if( scan->sParam.bDataType == SCANDATATYPE_Color ) { 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci scan->Red.pb += scan->sParam.Size.dwPhyBytes; 1473141cc406Sopenharmony_ci if( scan->Red.pb >= scan->pbScanBufEnd ) { 1474141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin + scan->dwRedShift; 1475141cc406Sopenharmony_ci wrap = 1; 1476141cc406Sopenharmony_ci } 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci scan->Green.pb += scan->sParam.Size.dwPhyBytes; 1479141cc406Sopenharmony_ci if( scan->Green.pb >= scan->pbScanBufEnd ) { 1480141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwGreenShift; 1481141cc406Sopenharmony_ci wrap = 1; 1482141cc406Sopenharmony_ci } 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci scan->Blue.pb += scan->sParam.Size.dwPhyBytes; 1485141cc406Sopenharmony_ci if( scan->Blue.pb >= scan->pbScanBufEnd ) { 1486141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + scan->dwBlueShift; 1487141cc406Sopenharmony_ci wrap = 1; 1488141cc406Sopenharmony_ci } 1489141cc406Sopenharmony_ci } else { 1490141cc406Sopenharmony_ci scan->Green.pb += scan->sParam.Size.dwPhyBytes; 1491141cc406Sopenharmony_ci if( scan->Green.pb >= scan->pbScanBufEnd ) 1492141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + scan->dwGreenShift; 1493141cc406Sopenharmony_ci } 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci /* on any wrap-around of the get pointers in one channel mode 1496141cc406Sopenharmony_ci * we have to reset them 1497141cc406Sopenharmony_ci */ 1498141cc406Sopenharmony_ci if( wrap ) { 1499141cc406Sopenharmony_ci 1500141cc406Sopenharmony_ci u_long len = scan->sParam.Size.dwPhyBytes; 1501141cc406Sopenharmony_ci 1502141cc406Sopenharmony_ci if( hw->bReg_0x26 & _ONE_CH_COLOR ) { 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci if(scan->sParam.bDataType == SCANDATATYPE_Color) { 1505141cc406Sopenharmony_ci len /= 3; 1506141cc406Sopenharmony_ci } 1507141cc406Sopenharmony_ci scan->Red.pb = scan->pbScanBufBegin; 1508141cc406Sopenharmony_ci scan->Green.pb = scan->pbScanBufBegin + len; 1509141cc406Sopenharmony_ci scan->Blue.pb = scan->pbScanBufBegin + len * 2UL; 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci } 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci /* line processed, check if we have to get more... 1514141cc406Sopenharmony_ci */ 1515141cc406Sopenharmony_ci scan->dwLinesToProcess--; 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci if( 0 == scan->dwLinesToProcess ) { 1518141cc406Sopenharmony_ci 1519141cc406Sopenharmony_ci scan->dwLinesToProcess = usb_ReadData( dev ); 1520141cc406Sopenharmony_ci if( 0 == scan->dwLinesToProcess ) { 1521141cc406Sopenharmony_ci 1522141cc406Sopenharmony_ci if( usb_IsEscPressed()) 1523141cc406Sopenharmony_ci return _E_ABORT; 1524141cc406Sopenharmony_ci } 1525141cc406Sopenharmony_ci } 1526141cc406Sopenharmony_ci } 1527141cc406Sopenharmony_ci return 0; 1528141cc406Sopenharmony_ci} 1529141cc406Sopenharmony_ci 1530141cc406Sopenharmony_ci/* END PLUSTEK-USB.C ........................................................*/ 1531