1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com> 3141cc406Sopenharmony_ci HP ScanJet 4570c support by Markham Thomas 4141cc406Sopenharmony_ci ADF page detection and high DPI fixes by Bernard Badeer 5141cc406Sopenharmony_ci scanbd integration by Damiano Scaramuzza and Bernard Badeer 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci This file is part of a SANE backend for 43141cc406Sopenharmony_ci HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners 44141cc406Sopenharmony_ci*/ 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci#include "../include/sane/config.h" 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#include <stdio.h> 49141cc406Sopenharmony_ci#include <string.h> 50141cc406Sopenharmony_ci#include <unistd.h> 51141cc406Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H 52141cc406Sopenharmony_ci#include <sys/types.h> 53141cc406Sopenharmony_ci#endif 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#include "../include/sane/sane.h" 56141cc406Sopenharmony_ci#define BACKEND_NAME hp5590 57141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 58141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 59141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 60141cc406Sopenharmony_ci#include "hp5590_cmds.c" 61141cc406Sopenharmony_ci#include "hp5590_low.c" 62141cc406Sopenharmony_ci#include "../include/sane/sanei_net.h" 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci/* Debug levels */ 65141cc406Sopenharmony_ci#define DBG_err 0 66141cc406Sopenharmony_ci#define DBG_proc 10 67141cc406Sopenharmony_ci#define DBG_verbose 20 68141cc406Sopenharmony_ci#define DBG_details 30 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci#define hp5590_assert(exp) if(!(exp)) { \ 71141cc406Sopenharmony_ci DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ 72141cc406Sopenharmony_ci return SANE_STATUS_INVAL; \ 73141cc406Sopenharmony_ci} 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci#define hp5590_assert_void_return(exp) if(!(exp)) { \ 76141cc406Sopenharmony_ci DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ 77141cc406Sopenharmony_ci return; \ 78141cc406Sopenharmony_ci} 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci#define MY_MIN(a, b) (((a) < (b)) ? (a) : (b)) 81141cc406Sopenharmony_ci#define MY_MAX(a, b) (((a) > (b)) ? (a) : (b)) 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci/* #define HAS_WORKING_COLOR_48 */ 84141cc406Sopenharmony_ci#define BUILD 8 85141cc406Sopenharmony_ci#define USB_TIMEOUT 30 * 1000 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_cistatic SANE_Word 88141cc406Sopenharmony_cires_list[] = { 6, 100, 200, 300, 600, 1200, 2400 }; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_SOURCE_FLATBED SANE_I18N("Flatbed") 91141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_SOURCE_ADF SANE_I18N("ADF") 92141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX SANE_I18N("ADF Duplex") 93141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_SOURCE_TMA_SLIDES SANE_I18N("TMA Slides") 94141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES SANE_I18N("TMA Negatives") 95141cc406Sopenharmony_cistatic SANE_String_Const 96141cc406Sopenharmony_cisources_list[] = { 97141cc406Sopenharmony_ci SANE_VALUE_SCAN_SOURCE_FLATBED, 98141cc406Sopenharmony_ci SANE_VALUE_SCAN_SOURCE_ADF, 99141cc406Sopenharmony_ci SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX, 100141cc406Sopenharmony_ci SANE_VALUE_SCAN_SOURCE_TMA_SLIDES, 101141cc406Sopenharmony_ci SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES, 102141cc406Sopenharmony_ci NULL 103141cc406Sopenharmony_ci}; 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_MODE_COLOR_24 SANE_VALUE_SCAN_MODE_COLOR 106141cc406Sopenharmony_ci#define SANE_VALUE_SCAN_MODE_COLOR_48 SANE_I18N("Color (48 bits)") 107141cc406Sopenharmony_ci#define HAS_WORKING_COLOR_48 1 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci#define SANE_NAME_LAMP_TIMEOUT "extend-lamp-timeout" 110141cc406Sopenharmony_ci#define SANE_TITLE_LAMP_TIMEOUT SANE_I18N("Extend lamp timeout") 111141cc406Sopenharmony_ci#define SANE_DESC_LAMP_TIMEOUT SANE_I18N("Extends lamp timeout (from 15 minutes to 1 hour)") 112141cc406Sopenharmony_ci#define SANE_NAME_WAIT_FOR_BUTTON "wait-for-button" 113141cc406Sopenharmony_ci#define SANE_TITLE_WAIT_FOR_BUTTON SANE_I18N("Wait for button") 114141cc406Sopenharmony_ci#define SANE_DESC_WAIT_FOR_BUTTON SANE_I18N("Waits for button before scanning") 115141cc406Sopenharmony_ci#define SANE_NAME_BUTTON_PRESSED "button-pressed" 116141cc406Sopenharmony_ci#define SANE_TITLE_BUTTON_PRESSED SANE_I18N("Last button pressed") 117141cc406Sopenharmony_ci#define SANE_DESC_BUTTON_PRESSED SANE_I18N("Get ID of last button pressed (read only)") 118141cc406Sopenharmony_ci#define SANE_NAME_LCD_COUNTER "counter-value" 119141cc406Sopenharmony_ci#define SANE_TITLE_LCD_COUNTER SANE_I18N("LCD counter") 120141cc406Sopenharmony_ci#define SANE_DESC_LCD_COUNTER SANE_I18N("Get value of LCD counter (read only)") 121141cc406Sopenharmony_ci#define SANE_NAME_COLOR_LED "color-led" 122141cc406Sopenharmony_ci#define SANE_TITLE_COLOR_LED SANE_I18N("Color LED indicator") 123141cc406Sopenharmony_ci#define SANE_DESC_COLOR_LED SANE_I18N("Get value of LED indicator (read only)") 124141cc406Sopenharmony_ci#define SANE_NAME_DOC_IN_ADF "doc-in-adf" 125141cc406Sopenharmony_ci#define SANE_TITLE_DOC_IN_ADF SANE_I18N("Document available in ADF") 126141cc406Sopenharmony_ci#define SANE_DESC_DOC_IN_ADF SANE_I18N("Get state of document-available indicator in ADF (read only)") 127141cc406Sopenharmony_ci#define SANE_NAME_OVERWRITE_EOP_PIXEL "hide-eop-pixel" 128141cc406Sopenharmony_ci#define SANE_TITLE_OVERWRITE_EOP_PIXEL SANE_I18N("Hide end-of-page pixel") 129141cc406Sopenharmony_ci#define SANE_DESC_OVERWRITE_EOP_PIXEL SANE_I18N("Hide end-of-page indicator pixels and overwrite with neighbor pixels") 130141cc406Sopenharmony_ci#define SANE_NAME_TRAILING_LINES_MODE "trailing-lines-mode" 131141cc406Sopenharmony_ci#define SANE_TITLE_TRAILING_LINES_MODE SANE_I18N("Filling mode of trailing lines after scan data (ADF)") 132141cc406Sopenharmony_ci#define SANE_DESC_TRAILING_LINES_MODE SANE_I18N("raw = raw scan data, last = repeat last scan line, raster = b/w raster, "\ 133141cc406Sopenharmony_ci "white = white color, black = black color, color = RGB or gray color value") 134141cc406Sopenharmony_ci#define SANE_NAME_TRAILING_LINES_COLOR "trailing-lines-color" 135141cc406Sopenharmony_ci#define SANE_TITLE_TRAILING_LINES_COLOR SANE_I18N("RGB or gray color value for filling mode 'color'") 136141cc406Sopenharmony_ci#define SANE_DESC_TRAILING_LINES_COLOR SANE_I18N("Color value for trailing lines filling mode 'color'. "\ 137141cc406Sopenharmony_ci "RGB color as r*65536+256*g+b or gray value (default=violet or gray)") 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_COUNT 11 140141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_NONE_KEY "none" 141141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_POWER_KEY "power" 142141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_SCAN_KEY "scan" 143141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_COLLECT_KEY "collect" 144141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_FILE_KEY "file" 145141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_EMAIL_KEY "email" 146141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_COPY_KEY "copy" 147141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_UP_KEY "up" 148141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_DOWN_KEY "down" 149141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_MODE_KEY "mode" 150141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_CANCEL_KEY "cancel" 151141cc406Sopenharmony_ci#define BUTTON_PRESSED_VALUE_MAX_KEY_LEN 32 152141cc406Sopenharmony_cistatic SANE_String_Const 153141cc406Sopenharmony_cibuttonstate_list[] = { 154141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_NONE_KEY, 155141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_POWER_KEY, 156141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_SCAN_KEY, 157141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_COLLECT_KEY, 158141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_FILE_KEY, 159141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_EMAIL_KEY, 160141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_COPY_KEY, 161141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_UP_KEY, 162141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_DOWN_KEY, 163141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_MODE_KEY, 164141cc406Sopenharmony_ci BUTTON_PRESSED_VALUE_CANCEL_KEY, 165141cc406Sopenharmony_ci NULL 166141cc406Sopenharmony_ci}; 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci#define COLOR_LED_VALUE_COUNT 2 169141cc406Sopenharmony_ci#define COLOR_LED_VALUE_COLOR_KEY "color" 170141cc406Sopenharmony_ci#define COLOR_LED_VALUE_BLACKWHITE_KEY "black_white" 171141cc406Sopenharmony_ci#define COLOR_LED_VALUE_MAX_KEY_LEN 32 172141cc406Sopenharmony_cistatic SANE_String_Const 173141cc406Sopenharmony_cicolorledstate_list[] = { 174141cc406Sopenharmony_ci COLOR_LED_VALUE_COLOR_KEY, 175141cc406Sopenharmony_ci COLOR_LED_VALUE_BLACKWHITE_KEY, 176141cc406Sopenharmony_ci NULL 177141cc406Sopenharmony_ci}; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci#define LCD_COUNTER_VALUE_MIN 1 180141cc406Sopenharmony_ci#define LCD_COUNTER_VALUE_MAX 99 181141cc406Sopenharmony_ci#define LCD_COUNTER_VALUE_QUANT 1 182141cc406Sopenharmony_cistatic SANE_Range 183141cc406Sopenharmony_cilcd_counter_range = { 184141cc406Sopenharmony_ci LCD_COUNTER_VALUE_MIN, 185141cc406Sopenharmony_ci LCD_COUNTER_VALUE_MAX, 186141cc406Sopenharmony_ci LCD_COUNTER_VALUE_QUANT 187141cc406Sopenharmony_ci}; 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_RAW 0 190141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_LAST 1 191141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_RASTER 2 192141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_WHITE 3 193141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_BLACK 4 194141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_COLOR 5 195141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_VALUE_COUNT 6 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_RAW_KEY "raw" 198141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_LAST_KEY "last" 199141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_RASTER_KEY "raster" 200141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_WHITE_KEY "white" 201141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_BLACK_KEY "black" 202141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_COLOR_KEY "color" 203141cc406Sopenharmony_ci#define TRAILING_LINES_MODE_MAX_KEY_LEN 24 204141cc406Sopenharmony_cistatic SANE_String_Const 205141cc406Sopenharmony_citrailingmode_list[] = { 206141cc406Sopenharmony_ci TRAILING_LINES_MODE_RAW_KEY, 207141cc406Sopenharmony_ci TRAILING_LINES_MODE_LAST_KEY, 208141cc406Sopenharmony_ci TRAILING_LINES_MODE_RASTER_KEY, 209141cc406Sopenharmony_ci TRAILING_LINES_MODE_WHITE_KEY, 210141cc406Sopenharmony_ci TRAILING_LINES_MODE_BLACK_KEY, 211141cc406Sopenharmony_ci TRAILING_LINES_MODE_COLOR_KEY, 212141cc406Sopenharmony_ci NULL 213141cc406Sopenharmony_ci}; 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_ci#define MAX_SCAN_SOURCE_VALUE_LEN 24 216141cc406Sopenharmony_ci#define MAX_SCAN_MODE_VALUE_LEN 24 217141cc406Sopenharmony_ci 218141cc406Sopenharmony_cistatic SANE_Range 219141cc406Sopenharmony_cirange_x, range_y, range_qual; 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_cistatic SANE_String_Const 222141cc406Sopenharmony_cimode_list[] = { 223141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR_24, 224141cc406Sopenharmony_ci#ifdef HAS_WORKING_COLOR_48 225141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR_48, 226141cc406Sopenharmony_ci#endif /* HAS_WORKING_COLOR_48 */ 227141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 228141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 229141cc406Sopenharmony_ci NULL 230141cc406Sopenharmony_ci}; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_cienum hp5590_opt_idx { 233141cc406Sopenharmony_ci HP5590_OPT_NUM = 0, 234141cc406Sopenharmony_ci HP5590_OPT_TL_X, 235141cc406Sopenharmony_ci HP5590_OPT_TL_Y, 236141cc406Sopenharmony_ci HP5590_OPT_BR_X, 237141cc406Sopenharmony_ci HP5590_OPT_BR_Y, 238141cc406Sopenharmony_ci HP5590_OPT_MODE, 239141cc406Sopenharmony_ci HP5590_OPT_SOURCE, 240141cc406Sopenharmony_ci HP5590_OPT_RESOLUTION, 241141cc406Sopenharmony_ci HP5590_OPT_LAMP_TIMEOUT, 242141cc406Sopenharmony_ci HP5590_OPT_WAIT_FOR_BUTTON, 243141cc406Sopenharmony_ci HP5590_OPT_BUTTON_PRESSED, 244141cc406Sopenharmony_ci HP5590_OPT_COLOR_LED, 245141cc406Sopenharmony_ci HP5590_OPT_LCD_COUNTER, 246141cc406Sopenharmony_ci HP5590_OPT_DOC_IN_ADF, 247141cc406Sopenharmony_ci HP5590_OPT_PREVIEW, 248141cc406Sopenharmony_ci HP5590_OPT_OVERWRITE_EOP_PIXEL, 249141cc406Sopenharmony_ci HP5590_OPT_TRAILING_LINES_MODE, 250141cc406Sopenharmony_ci HP5590_OPT_TRAILING_LINES_COLOR, 251141cc406Sopenharmony_ci HP5590_OPT_LAST 252141cc406Sopenharmony_ci}; 253141cc406Sopenharmony_ci 254141cc406Sopenharmony_cistruct hp5590_scanner { 255141cc406Sopenharmony_ci struct scanner_info *info; 256141cc406Sopenharmony_ci enum proto_flags proto_flags; 257141cc406Sopenharmony_ci SANE_Device sane; 258141cc406Sopenharmony_ci SANE_Int dn; 259141cc406Sopenharmony_ci float br_x, br_y, tl_x, tl_y; 260141cc406Sopenharmony_ci unsigned int dpi; 261141cc406Sopenharmony_ci enum color_depths depth; 262141cc406Sopenharmony_ci enum scan_sources source; 263141cc406Sopenharmony_ci SANE_Bool extend_lamp_timeout; 264141cc406Sopenharmony_ci SANE_Bool wait_for_button; 265141cc406Sopenharmony_ci SANE_Bool preview; 266141cc406Sopenharmony_ci unsigned int quality; 267141cc406Sopenharmony_ci SANE_Option_Descriptor *opts; 268141cc406Sopenharmony_ci struct hp5590_scanner *next; 269141cc406Sopenharmony_ci unsigned long long image_size; 270141cc406Sopenharmony_ci unsigned long long transferred_image_size; 271141cc406Sopenharmony_ci void *bulk_read_state; 272141cc406Sopenharmony_ci SANE_Bool scanning; 273141cc406Sopenharmony_ci SANE_Bool overwrite_eop_pixel; 274141cc406Sopenharmony_ci SANE_Byte *eop_last_line_data; 275141cc406Sopenharmony_ci unsigned int eop_last_line_data_rpos; 276141cc406Sopenharmony_ci SANE_Int eop_trailing_lines_mode; 277141cc406Sopenharmony_ci SANE_Int eop_trailing_lines_color; 278141cc406Sopenharmony_ci SANE_Byte *adf_next_page_lines_data; 279141cc406Sopenharmony_ci unsigned int adf_next_page_lines_data_size; 280141cc406Sopenharmony_ci unsigned int adf_next_page_lines_data_rpos; 281141cc406Sopenharmony_ci unsigned int adf_next_page_lines_data_wpos; 282141cc406Sopenharmony_ci SANE_Byte *one_line_read_buffer; 283141cc406Sopenharmony_ci unsigned int one_line_read_buffer_rpos; 284141cc406Sopenharmony_ci SANE_Byte *color_shift_line_buffer1; 285141cc406Sopenharmony_ci unsigned int color_shift_buffered_lines1; 286141cc406Sopenharmony_ci SANE_Byte *color_shift_line_buffer2; 287141cc406Sopenharmony_ci unsigned int color_shift_buffered_lines2; 288141cc406Sopenharmony_ci}; 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_cistatic 291141cc406Sopenharmony_cistruct hp5590_scanner *scanners_list; 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci/******************************************************************************/ 294141cc406Sopenharmony_cistatic SANE_Status 295141cc406Sopenharmony_cicalc_image_params (struct hp5590_scanner *scanner, 296141cc406Sopenharmony_ci unsigned int *pixel_bits, 297141cc406Sopenharmony_ci unsigned int *pixels_per_line, 298141cc406Sopenharmony_ci unsigned int *bytes_per_line, 299141cc406Sopenharmony_ci unsigned int *lines, 300141cc406Sopenharmony_ci unsigned long long *image_size) 301141cc406Sopenharmony_ci{ 302141cc406Sopenharmony_ci unsigned int _pixel_bits; 303141cc406Sopenharmony_ci SANE_Status ret; 304141cc406Sopenharmony_ci unsigned int _pixels_per_line; 305141cc406Sopenharmony_ci unsigned int _bytes_per_line; 306141cc406Sopenharmony_ci unsigned int _lines; 307141cc406Sopenharmony_ci unsigned int _image_size; 308141cc406Sopenharmony_ci float var; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci if (!scanner) 313141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci ret = hp5590_calc_pixel_bits (scanner->dpi, scanner->depth, &_pixel_bits); 316141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 317141cc406Sopenharmony_ci return ret; 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci var = (float) (1.0 * (scanner->br_x - scanner->tl_x) * scanner->dpi); 320141cc406Sopenharmony_ci _pixels_per_line = var; 321141cc406Sopenharmony_ci if (var > _pixels_per_line) 322141cc406Sopenharmony_ci _pixels_per_line++; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci var = (float) (1.0 * (scanner->br_y - scanner->tl_y) * scanner->dpi); 325141cc406Sopenharmony_ci _lines = var; 326141cc406Sopenharmony_ci if (var > _lines) 327141cc406Sopenharmony_ci _lines++; 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci var = (float) (1.0 * _pixels_per_line / 8 * _pixel_bits); 330141cc406Sopenharmony_ci _bytes_per_line = var; 331141cc406Sopenharmony_ci if (var > _bytes_per_line) 332141cc406Sopenharmony_ci _bytes_per_line++; 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_ci _image_size = (unsigned long long) _lines * _bytes_per_line; 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: pixel_bits: %u, pixels_per_line: %u, " 337141cc406Sopenharmony_ci "bytes_per_line: %u, lines: %u, image_size: %u\n", 338141cc406Sopenharmony_ci __func__, 339141cc406Sopenharmony_ci _pixel_bits, _pixels_per_line, _bytes_per_line, _lines, _image_size); 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ci if (pixel_bits) 342141cc406Sopenharmony_ci *pixel_bits = _pixel_bits; 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci if (pixels_per_line) 345141cc406Sopenharmony_ci *pixels_per_line = _pixels_per_line; 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci if (bytes_per_line) 348141cc406Sopenharmony_ci *bytes_per_line = _bytes_per_line; 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_ci if (lines) 351141cc406Sopenharmony_ci *lines = _lines; 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci if (image_size) 354141cc406Sopenharmony_ci *image_size = _image_size; 355141cc406Sopenharmony_ci 356141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 357141cc406Sopenharmony_ci} 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci/******************************************************************************/ 360141cc406Sopenharmony_cistatic SANE_Status 361141cc406Sopenharmony_ciattach_usb_device (SANE_String_Const devname, 362141cc406Sopenharmony_ci enum hp_scanner_types hp_scanner_type) 363141cc406Sopenharmony_ci{ 364141cc406Sopenharmony_ci struct scanner_info *info; 365141cc406Sopenharmony_ci struct hp5590_scanner *scanner, *ptr; 366141cc406Sopenharmony_ci unsigned int max_count, count; 367141cc406Sopenharmony_ci SANE_Int dn; 368141cc406Sopenharmony_ci SANE_Status ret; 369141cc406Sopenharmony_ci const struct hp5590_model *hp5590_model; 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci DBG (DBG_proc, "%s: Opening USB device\n", __func__); 372141cc406Sopenharmony_ci if (sanei_usb_open (devname, &dn) != SANE_STATUS_GOOD) 373141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 374141cc406Sopenharmony_ci DBG (DBG_proc, "%s: USB device opened\n", __func__); 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci ret = hp5590_model_def (hp_scanner_type, &hp5590_model); 377141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 378141cc406Sopenharmony_ci return ret; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci if (hp5590_init_scanner (dn, hp5590_model->proto_flags, 381141cc406Sopenharmony_ci &info, hp_scanner_type) != 0) 382141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci DBG (1, "%s: found HP%s scanner at '%s'\n", 385141cc406Sopenharmony_ci __func__, info->model, devname); 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Reading max scan count\n", __func__); 388141cc406Sopenharmony_ci if (hp5590_read_max_scan_count (dn, hp5590_model->proto_flags, 389141cc406Sopenharmony_ci &max_count) != 0) 390141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 391141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Max Scanning count %u\n", __func__, max_count); 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Reading scan count\n", __func__); 394141cc406Sopenharmony_ci if (hp5590_read_scan_count (dn, hp5590_model->proto_flags, 395141cc406Sopenharmony_ci &count) != 0) 396141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 397141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Scanning count %u\n", __func__, count); 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci ret = hp5590_read_part_number (dn, hp5590_model->proto_flags); 400141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 401141cc406Sopenharmony_ci return ret; 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci ret = hp5590_stop_scan (dn, hp5590_model->proto_flags); 404141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 405141cc406Sopenharmony_ci return ret; 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci scanner = malloc (sizeof(struct hp5590_scanner)); 408141cc406Sopenharmony_ci if (!scanner) 409141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 410141cc406Sopenharmony_ci memset (scanner, 0, sizeof(struct hp5590_scanner)); 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_ci scanner->sane.model = info->model; 413141cc406Sopenharmony_ci scanner->sane.vendor = "HP"; 414141cc406Sopenharmony_ci scanner->sane.type = info->kind; 415141cc406Sopenharmony_ci scanner->sane.name = devname; 416141cc406Sopenharmony_ci scanner->dn = dn; 417141cc406Sopenharmony_ci scanner->proto_flags = hp5590_model->proto_flags; 418141cc406Sopenharmony_ci scanner->info = info; 419141cc406Sopenharmony_ci scanner->bulk_read_state = NULL; 420141cc406Sopenharmony_ci scanner->opts = NULL; 421141cc406Sopenharmony_ci scanner->eop_last_line_data = NULL; 422141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos = 0; 423141cc406Sopenharmony_ci scanner->adf_next_page_lines_data = NULL; 424141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_size = 0; 425141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos = 0; 426141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos = 0; 427141cc406Sopenharmony_ci scanner->one_line_read_buffer = NULL; 428141cc406Sopenharmony_ci scanner->one_line_read_buffer_rpos = 0; 429141cc406Sopenharmony_ci scanner->color_shift_line_buffer1 = NULL; 430141cc406Sopenharmony_ci scanner->color_shift_buffered_lines1 = 0; 431141cc406Sopenharmony_ci scanner->color_shift_line_buffer2 = NULL; 432141cc406Sopenharmony_ci scanner->color_shift_buffered_lines2 = 0; 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci if (!scanners_list) 435141cc406Sopenharmony_ci scanners_list = scanner; 436141cc406Sopenharmony_ci else 437141cc406Sopenharmony_ci { 438141cc406Sopenharmony_ci for (ptr = scanners_list; ptr->next; ptr = ptr->next); 439141cc406Sopenharmony_ci ptr->next = scanner; 440141cc406Sopenharmony_ci } 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 443141cc406Sopenharmony_ci} 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci/******************************************************************************/ 446141cc406Sopenharmony_cistatic SANE_Status 447141cc406Sopenharmony_ciattach_hp4570 (SANE_String_Const devname) 448141cc406Sopenharmony_ci{ 449141cc406Sopenharmony_ci return attach_usb_device (devname, SCANNER_HP4570); 450141cc406Sopenharmony_ci} 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci/******************************************************************************/ 453141cc406Sopenharmony_cistatic SANE_Status 454141cc406Sopenharmony_ciattach_hp5550 (SANE_String_Const devname) 455141cc406Sopenharmony_ci{ 456141cc406Sopenharmony_ci return attach_usb_device (devname, SCANNER_HP5550); 457141cc406Sopenharmony_ci} 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci/******************************************************************************/ 460141cc406Sopenharmony_cistatic SANE_Status 461141cc406Sopenharmony_ciattach_hp5590 (SANE_String_Const devname) 462141cc406Sopenharmony_ci{ 463141cc406Sopenharmony_ci return attach_usb_device (devname, SCANNER_HP5590); 464141cc406Sopenharmony_ci} 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci/******************************************************************************/ 467141cc406Sopenharmony_cistatic SANE_Status 468141cc406Sopenharmony_ciattach_hp7650 (SANE_String_Const devname) 469141cc406Sopenharmony_ci{ 470141cc406Sopenharmony_ci return attach_usb_device (devname, SCANNER_HP7650); 471141cc406Sopenharmony_ci} 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci/******************************************************************************/ 474141cc406Sopenharmony_ciSANE_Status 475141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 476141cc406Sopenharmony_ci{ 477141cc406Sopenharmony_ci SANE_Status ret; 478141cc406Sopenharmony_ci SANE_Word vendor_id, product_id; 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci DBG_INIT(); 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci DBG (1, "SANE backed for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 %u.%u.%u\n", 483141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 484141cc406Sopenharmony_ci DBG (1, "(c) Ilia Sotnikov <hostcc@gmail.com>\n"); 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci if (version_code) 487141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci sanei_usb_init(); 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci sanei_usb_set_timeout (USB_TIMEOUT); 492141cc406Sopenharmony_ci 493141cc406Sopenharmony_ci scanners_list = NULL; 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci ret = hp5590_vendor_product_id (SCANNER_HP4570, &vendor_id, &product_id); 496141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 497141cc406Sopenharmony_ci return ret; 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp4570); 500141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 501141cc406Sopenharmony_ci return ret; 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci ret = hp5590_vendor_product_id (SCANNER_HP5550, &vendor_id, &product_id); 504141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 505141cc406Sopenharmony_ci return ret; 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp5550); 508141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 509141cc406Sopenharmony_ci return ret; 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci ret = hp5590_vendor_product_id (SCANNER_HP5590, &vendor_id, &product_id); 512141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 513141cc406Sopenharmony_ci return ret; 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp5590); 516141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 517141cc406Sopenharmony_ci return ret; 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci ret = hp5590_vendor_product_id (SCANNER_HP7650, &vendor_id, &product_id); 520141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 521141cc406Sopenharmony_ci return ret; 522141cc406Sopenharmony_ci 523141cc406Sopenharmony_ci ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp7650); 524141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 525141cc406Sopenharmony_ci return ret; 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 528141cc406Sopenharmony_ci} 529141cc406Sopenharmony_ci 530141cc406Sopenharmony_ci/******************************************************************************/ 531141cc406Sopenharmony_civoid sane_exit (void) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci struct hp5590_scanner *ptr, *pnext; 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci for (ptr = scanners_list; ptr; ptr = pnext) 538141cc406Sopenharmony_ci { 539141cc406Sopenharmony_ci if (ptr->opts != NULL) 540141cc406Sopenharmony_ci free (ptr->opts); 541141cc406Sopenharmony_ci if (ptr->eop_last_line_data != NULL) { 542141cc406Sopenharmony_ci free (ptr->eop_last_line_data); 543141cc406Sopenharmony_ci ptr->eop_last_line_data = NULL; 544141cc406Sopenharmony_ci ptr->eop_last_line_data_rpos = 0; 545141cc406Sopenharmony_ci } 546141cc406Sopenharmony_ci if (ptr->adf_next_page_lines_data != NULL) { 547141cc406Sopenharmony_ci free (ptr->adf_next_page_lines_data); 548141cc406Sopenharmony_ci ptr->adf_next_page_lines_data = NULL; 549141cc406Sopenharmony_ci ptr->adf_next_page_lines_data_size = 0; 550141cc406Sopenharmony_ci ptr->adf_next_page_lines_data_wpos = 0; 551141cc406Sopenharmony_ci ptr->adf_next_page_lines_data_rpos = 0; 552141cc406Sopenharmony_ci } 553141cc406Sopenharmony_ci if (ptr->one_line_read_buffer != NULL) { 554141cc406Sopenharmony_ci free (ptr->one_line_read_buffer); 555141cc406Sopenharmony_ci ptr->one_line_read_buffer = NULL; 556141cc406Sopenharmony_ci ptr->one_line_read_buffer_rpos = 0; 557141cc406Sopenharmony_ci } 558141cc406Sopenharmony_ci if (ptr->color_shift_line_buffer1 != NULL) { 559141cc406Sopenharmony_ci free (ptr->color_shift_line_buffer1); 560141cc406Sopenharmony_ci ptr->color_shift_line_buffer1 = NULL; 561141cc406Sopenharmony_ci ptr->color_shift_buffered_lines1 = 0; 562141cc406Sopenharmony_ci } 563141cc406Sopenharmony_ci if (ptr->color_shift_line_buffer2 != NULL) { 564141cc406Sopenharmony_ci free (ptr->color_shift_line_buffer2); 565141cc406Sopenharmony_ci ptr->color_shift_line_buffer2 = NULL; 566141cc406Sopenharmony_ci ptr->color_shift_buffered_lines2 = 0; 567141cc406Sopenharmony_ci } 568141cc406Sopenharmony_ci pnext = ptr->next; 569141cc406Sopenharmony_ci free (ptr); 570141cc406Sopenharmony_ci } 571141cc406Sopenharmony_ci} 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci/******************************************************************************/ 574141cc406Sopenharmony_ciSANE_Status 575141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 576141cc406Sopenharmony_ci{ 577141cc406Sopenharmony_ci struct hp5590_scanner *ptr; 578141cc406Sopenharmony_ci unsigned int found, i; 579141cc406Sopenharmony_ci 580141cc406Sopenharmony_ci DBG (DBG_proc, "%s, local only: %u\n", __func__, local_only); 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci if (!device_list) 583141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci for (found = 0, ptr = scanners_list; ptr; found++, ptr = ptr->next); 586141cc406Sopenharmony_ci DBG (1, "Found %u devices\n", found); 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci found++; 589141cc406Sopenharmony_ci *device_list = malloc (found * sizeof (SANE_Device)); 590141cc406Sopenharmony_ci if (!*device_list) 591141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 592141cc406Sopenharmony_ci memset (*device_list, 0, found * sizeof(SANE_Device)); 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ci for (i = 0, ptr = scanners_list; ptr; i++, ptr = ptr->next) 595141cc406Sopenharmony_ci { 596141cc406Sopenharmony_ci (*device_list)[i] = &(ptr->sane); 597141cc406Sopenharmony_ci } 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 600141cc406Sopenharmony_ci} 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci/******************************************************************************/ 603141cc406Sopenharmony_ciSANE_Status 604141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 605141cc406Sopenharmony_ci{ 606141cc406Sopenharmony_ci struct hp5590_scanner *ptr; 607141cc406Sopenharmony_ci SANE_Option_Descriptor *opts; 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci DBG (DBG_proc, "%s: device name: %s\n", __func__, devicename); 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci if (!handle) 612141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci /* Allow to open the first available device by specifying zero-length name */ 615141cc406Sopenharmony_ci if (!devicename || !devicename[0]) { 616141cc406Sopenharmony_ci ptr = scanners_list; 617141cc406Sopenharmony_ci } else { 618141cc406Sopenharmony_ci for (ptr = scanners_list; 619141cc406Sopenharmony_ci ptr && strcmp (ptr->sane.name, devicename) != 0; 620141cc406Sopenharmony_ci ptr = ptr->next); 621141cc406Sopenharmony_ci } 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci if (!ptr) 624141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci /* DS: Without this after the first scan (and sane_close) 627141cc406Sopenharmony_ci * it was impossible to use again the read_buttons usb routine. 628141cc406Sopenharmony_ci * Function sane_close puts dn = -1. Now sane_open needs to open 629141cc406Sopenharmony_ci * the usb communication again. 630141cc406Sopenharmony_ci */ 631141cc406Sopenharmony_ci if (ptr->dn < 0) { 632141cc406Sopenharmony_ci DBG (DBG_proc, "%s: Reopening USB device\n", __func__); 633141cc406Sopenharmony_ci if (sanei_usb_open (ptr->sane.name, &ptr->dn) != SANE_STATUS_GOOD) 634141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 635141cc406Sopenharmony_ci DBG (DBG_proc, "%s: USB device reopened\n", __func__); 636141cc406Sopenharmony_ci } 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci ptr->tl_x = 0; 639141cc406Sopenharmony_ci ptr->tl_y = 0; 640141cc406Sopenharmony_ci ptr->br_x = ptr->info->max_size_x; 641141cc406Sopenharmony_ci ptr->br_y = ptr->info->max_size_y; 642141cc406Sopenharmony_ci ptr->dpi = res_list[1]; 643141cc406Sopenharmony_ci ptr->depth = DEPTH_BW; 644141cc406Sopenharmony_ci ptr->source = SOURCE_FLATBED; 645141cc406Sopenharmony_ci ptr->extend_lamp_timeout = SANE_FALSE; 646141cc406Sopenharmony_ci ptr->wait_for_button = SANE_FALSE; 647141cc406Sopenharmony_ci ptr->preview = SANE_FALSE; 648141cc406Sopenharmony_ci ptr->quality = 4; 649141cc406Sopenharmony_ci ptr->image_size = 0; 650141cc406Sopenharmony_ci ptr->scanning = SANE_FALSE; 651141cc406Sopenharmony_ci ptr->overwrite_eop_pixel = SANE_TRUE; 652141cc406Sopenharmony_ci ptr->eop_trailing_lines_mode = TRAILING_LINES_MODE_LAST; 653141cc406Sopenharmony_ci ptr->eop_trailing_lines_color = 0x7f007f; 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci *handle = ptr; 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci opts = malloc (sizeof (SANE_Option_Descriptor) * HP5590_OPT_LAST); 658141cc406Sopenharmony_ci if (!opts) 659141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].name = SANE_NAME_NUM_OPTIONS; 662141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].title = SANE_TITLE_NUM_OPTIONS; 663141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].desc = SANE_DESC_NUM_OPTIONS; 664141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].type = SANE_TYPE_INT; 665141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].unit = SANE_UNIT_NONE; 666141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].size = sizeof(SANE_Word); 667141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].cap = SANE_CAP_INACTIVE | SANE_CAP_SOFT_DETECT; 668141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].constraint_type = SANE_CONSTRAINT_NONE; 669141cc406Sopenharmony_ci opts[HP5590_OPT_NUM].constraint.string_list = NULL; 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci range_x.min = SANE_FIX(0); 672141cc406Sopenharmony_ci range_x.max = SANE_FIX(ptr->info->max_size_x * 25.4); 673141cc406Sopenharmony_ci range_x.quant = SANE_FIX(0.1); 674141cc406Sopenharmony_ci range_y.min = SANE_FIX(0); 675141cc406Sopenharmony_ci range_y.max = SANE_FIX(ptr->info->max_size_y * 25.4); 676141cc406Sopenharmony_ci range_y.quant = SANE_FIX(0.1); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci range_qual.min = SANE_FIX(4); 679141cc406Sopenharmony_ci range_qual.max = SANE_FIX(16); 680141cc406Sopenharmony_ci range_qual.quant = SANE_FIX(1); 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 683141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 684141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 685141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].type = SANE_TYPE_FIXED; 686141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].unit = SANE_UNIT_MM; 687141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].size = sizeof(SANE_Fixed); 688141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 689141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 690141cc406Sopenharmony_ci opts[HP5590_OPT_TL_X].constraint.range = &range_x; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 693141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 694141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 695141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].type = SANE_TYPE_FIXED; 696141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].unit = SANE_UNIT_MM; 697141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].size = sizeof(SANE_Fixed); 698141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 699141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 700141cc406Sopenharmony_ci opts[HP5590_OPT_TL_Y].constraint.range = &range_y; 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 703141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 704141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 705141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].type = SANE_TYPE_FIXED; 706141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].unit = SANE_UNIT_MM; 707141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].size = sizeof(SANE_Fixed); 708141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 709141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 710141cc406Sopenharmony_ci opts[HP5590_OPT_BR_X].constraint.range = &range_x; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 713141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 714141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 715141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].type = SANE_TYPE_FIXED; 716141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].unit = SANE_UNIT_MM; 717141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].size = sizeof(SANE_Fixed); 718141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 719141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 720141cc406Sopenharmony_ci opts[HP5590_OPT_BR_Y].constraint.range = &range_y; 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].name = SANE_NAME_SCAN_MODE; 723141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].title = SANE_TITLE_SCAN_MODE; 724141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].desc = SANE_DESC_SCAN_MODE; 725141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].type = SANE_TYPE_STRING; 726141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].unit = SANE_UNIT_NONE; 727141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].size = MAX_SCAN_MODE_VALUE_LEN; 728141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 729141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 730141cc406Sopenharmony_ci opts[HP5590_OPT_MODE].constraint.string_list = mode_list; 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci /* Show all features, check on feature in command line evaluation. */ 733141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 734141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 735141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 736141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].type = SANE_TYPE_STRING; 737141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].unit = SANE_UNIT_NONE; 738141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].size = MAX_SCAN_SOURCE_VALUE_LEN; 739141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 740141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 741141cc406Sopenharmony_ci opts[HP5590_OPT_SOURCE].constraint.string_list = sources_list; 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 744141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 745141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 746141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].type = SANE_TYPE_INT; 747141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].unit = SANE_UNIT_DPI; 748141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].size = sizeof(SANE_Int); 749141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 750141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 751141cc406Sopenharmony_ci opts[HP5590_OPT_RESOLUTION].constraint.word_list = res_list; 752141cc406Sopenharmony_ci 753141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].name = SANE_NAME_LAMP_TIMEOUT; 754141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].title = SANE_TITLE_LAMP_TIMEOUT; 755141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].desc = SANE_DESC_LAMP_TIMEOUT; 756141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].type = SANE_TYPE_BOOL; 757141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; 758141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].size = sizeof(SANE_Bool); 759141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 760141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_NONE; 761141cc406Sopenharmony_ci opts[HP5590_OPT_LAMP_TIMEOUT].constraint.string_list = NULL; 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].name = SANE_NAME_WAIT_FOR_BUTTON; 764141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].title = SANE_TITLE_WAIT_FOR_BUTTON; 765141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].desc = SANE_DESC_WAIT_FOR_BUTTON; 766141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; 767141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; 768141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].size = sizeof(SANE_Bool); 769141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 770141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; 771141cc406Sopenharmony_ci opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint.string_list = NULL; 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].name = SANE_NAME_BUTTON_PRESSED; 774141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].title = SANE_TITLE_BUTTON_PRESSED; 775141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].desc = SANE_DESC_BUTTON_PRESSED; 776141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].type = SANE_TYPE_STRING; 777141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].unit = SANE_UNIT_NONE; 778141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].size = BUTTON_PRESSED_VALUE_MAX_KEY_LEN; 779141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].cap = SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT; 780141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].constraint_type = SANE_CONSTRAINT_STRING_LIST; 781141cc406Sopenharmony_ci opts[HP5590_OPT_BUTTON_PRESSED].constraint.string_list = buttonstate_list; 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].name = SANE_NAME_COLOR_LED; 784141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].title = SANE_TITLE_COLOR_LED; 785141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].desc = SANE_DESC_COLOR_LED; 786141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].type = SANE_TYPE_STRING; 787141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].unit = SANE_UNIT_NONE; 788141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].size = COLOR_LED_VALUE_MAX_KEY_LEN; 789141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].cap = SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT; 790141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].constraint_type = SANE_CONSTRAINT_STRING_LIST; 791141cc406Sopenharmony_ci opts[HP5590_OPT_COLOR_LED].constraint.string_list = colorledstate_list; 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].name = SANE_NAME_LCD_COUNTER; 794141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].title = SANE_TITLE_LCD_COUNTER; 795141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].desc = SANE_DESC_LCD_COUNTER; 796141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].type = SANE_TYPE_INT; 797141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].unit = SANE_UNIT_NONE; 798141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].size = sizeof(SANE_Int); 799141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].cap = SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT; 800141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].constraint_type = SANE_CONSTRAINT_RANGE; 801141cc406Sopenharmony_ci opts[HP5590_OPT_LCD_COUNTER].constraint.range = &lcd_counter_range; 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].name = SANE_NAME_DOC_IN_ADF; 804141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].title = SANE_TITLE_DOC_IN_ADF; 805141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].desc = SANE_DESC_DOC_IN_ADF; 806141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].type = SANE_TYPE_BOOL; 807141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].unit = SANE_UNIT_NONE; 808141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].size = sizeof(SANE_Bool); 809141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].cap = SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT; 810141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].constraint_type = SANE_CONSTRAINT_NONE; 811141cc406Sopenharmony_ci opts[HP5590_OPT_DOC_IN_ADF].constraint.range = NULL; 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].name = SANE_NAME_PREVIEW; 814141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 815141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 816141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].type = SANE_TYPE_BOOL; 817141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].unit = SANE_UNIT_NONE; 818141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].size = sizeof(SANE_Bool); 819141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 820141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; 821141cc406Sopenharmony_ci opts[HP5590_OPT_PREVIEW].constraint.string_list = NULL; 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].name = SANE_NAME_OVERWRITE_EOP_PIXEL; 824141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].title = SANE_TITLE_OVERWRITE_EOP_PIXEL; 825141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].desc = SANE_DESC_OVERWRITE_EOP_PIXEL; 826141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].type = SANE_TYPE_BOOL; 827141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].unit = SANE_UNIT_NONE; 828141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].size = sizeof(SANE_Bool); 829141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 830141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].constraint_type = SANE_CONSTRAINT_NONE; 831141cc406Sopenharmony_ci opts[HP5590_OPT_OVERWRITE_EOP_PIXEL].constraint.string_list = NULL; 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].name = SANE_NAME_TRAILING_LINES_MODE; 834141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].title = SANE_TITLE_TRAILING_LINES_MODE; 835141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].desc = SANE_DESC_TRAILING_LINES_MODE; 836141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].type = SANE_TYPE_STRING; 837141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].unit = SANE_UNIT_NONE; 838141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].size = TRAILING_LINES_MODE_MAX_KEY_LEN; 839141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 840141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 841141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_MODE].constraint.string_list = trailingmode_list; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].name = SANE_NAME_TRAILING_LINES_COLOR; 844141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].title = SANE_TITLE_TRAILING_LINES_COLOR; 845141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].desc = SANE_DESC_TRAILING_LINES_COLOR; 846141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].type = SANE_TYPE_INT; 847141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].unit = SANE_UNIT_NONE; 848141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].size = sizeof(SANE_Int); 849141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 850141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].constraint_type = SANE_CONSTRAINT_NONE; 851141cc406Sopenharmony_ci opts[HP5590_OPT_TRAILING_LINES_COLOR].constraint.string_list = NULL; 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci ptr->opts = opts; 854141cc406Sopenharmony_ci 855141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 856141cc406Sopenharmony_ci} 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci/******************************************************************************/ 859141cc406Sopenharmony_civoid 860141cc406Sopenharmony_cisane_close (SANE_Handle handle) 861141cc406Sopenharmony_ci{ 862141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 865141cc406Sopenharmony_ci 866141cc406Sopenharmony_ci sanei_usb_close (scanner->dn); 867141cc406Sopenharmony_ci scanner->dn = -1; 868141cc406Sopenharmony_ci} 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci/******************************************************************************/ 871141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 872141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 873141cc406Sopenharmony_ci{ 874141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_ci DBG (DBG_proc, "%s, option: %u\n", __func__, option); 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci if (option >= HP5590_OPT_LAST) 879141cc406Sopenharmony_ci return NULL; 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci return &scanner->opts[option]; 882141cc406Sopenharmony_ci} 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_ci/*************************************DS:Support function read buttons status */ 885141cc406Sopenharmony_ciSANE_Status 886141cc406Sopenharmony_ciread_button_pressed(SANE_Handle handle, enum button_status * button_pressed) 887141cc406Sopenharmony_ci{ 888141cc406Sopenharmony_ci struct hp5590_scanner * scanner = handle; 889141cc406Sopenharmony_ci *button_pressed = BUTTON_NONE; 890141cc406Sopenharmony_ci enum button_status status = BUTTON_NONE; 891141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Checking button status (device_number = %u) (device_name = %s)\n", __func__, scanner->dn, scanner->sane.name); 892141cc406Sopenharmony_ci SANE_Status ret = hp5590_read_buttons (scanner->dn, scanner->proto_flags, &status); 893141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 894141cc406Sopenharmony_ci { 895141cc406Sopenharmony_ci DBG (DBG_proc, "%s: Error reading button status (%u)\n", __func__, ret); 896141cc406Sopenharmony_ci return ret; 897141cc406Sopenharmony_ci } 898141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Button pressed = %d\n", __func__, status); 899141cc406Sopenharmony_ci *button_pressed = status; 900141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 901141cc406Sopenharmony_ci} 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci/******************************************************************************/ 904141cc406Sopenharmony_ciSANE_Status 905141cc406Sopenharmony_ciread_lcd_and_led_values(SANE_Handle handle, 906141cc406Sopenharmony_ci SANE_Int * lcd_counter, 907141cc406Sopenharmony_ci enum color_led_status * color_led) 908141cc406Sopenharmony_ci{ 909141cc406Sopenharmony_ci struct hp5590_scanner * scanner = handle; 910141cc406Sopenharmony_ci *lcd_counter = 1; 911141cc406Sopenharmony_ci *color_led = LED_COLOR; 912141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Reading LCD and LED values (device_number = %u) (device_name = %s)\n", 913141cc406Sopenharmony_ci __func__, scanner->dn, scanner->sane.name); 914141cc406Sopenharmony_ci SANE_Status ret = hp5590_read_lcd_and_led (scanner->dn, scanner->proto_flags, lcd_counter, color_led); 915141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 916141cc406Sopenharmony_ci { 917141cc406Sopenharmony_ci DBG (DBG_proc, "%s: Error reading LCD and LED values (%u)\n", __func__, ret); 918141cc406Sopenharmony_ci return ret; 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: LCD = %d, LED = %s\n", __func__, *lcd_counter, 921141cc406Sopenharmony_ci *color_led == LED_BLACKWHITE ? COLOR_LED_VALUE_BLACKWHITE_KEY : COLOR_LED_VALUE_COLOR_KEY); 922141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 923141cc406Sopenharmony_ci} 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci/******************************************************************************/ 926141cc406Sopenharmony_ciSANE_Status 927141cc406Sopenharmony_ciread_doc_in_adf_value(SANE_Handle handle, 928141cc406Sopenharmony_ci SANE_Bool * doc_in_adf) 929141cc406Sopenharmony_ci{ 930141cc406Sopenharmony_ci struct hp5590_scanner * scanner = handle; 931141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Reading state of document-available in ADF (device_number = %u) (device_name = %s)\n", 932141cc406Sopenharmony_ci __func__, scanner->dn, scanner->sane.name); 933141cc406Sopenharmony_ci SANE_Status ret = hp5590_is_data_available (scanner->dn, scanner->proto_flags); 934141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD) 935141cc406Sopenharmony_ci *doc_in_adf = SANE_TRUE; 936141cc406Sopenharmony_ci else if (ret == SANE_STATUS_NO_DOCS) 937141cc406Sopenharmony_ci *doc_in_adf = SANE_FALSE; 938141cc406Sopenharmony_ci else 939141cc406Sopenharmony_ci { 940141cc406Sopenharmony_ci DBG (DBG_proc, "%s: Error reading state of document-available in ADF (%u)\n", __func__, ret); 941141cc406Sopenharmony_ci return ret; 942141cc406Sopenharmony_ci } 943141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: doc_in_adf = %s\n", __func__, *doc_in_adf == SANE_FALSE ? "false" : "true"); 944141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 945141cc406Sopenharmony_ci} 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci/******************************************************************************/ 948141cc406Sopenharmony_ciSANE_Status 949141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 950141cc406Sopenharmony_ci SANE_Action action, void *value, 951141cc406Sopenharmony_ci SANE_Int * info) 952141cc406Sopenharmony_ci{ 953141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci if (!value) 956141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci if (!handle) 959141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci if (option >= HP5590_OPT_LAST) 962141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 965141cc406Sopenharmony_ci { 966141cc406Sopenharmony_ci if (option == HP5590_OPT_NUM) 967141cc406Sopenharmony_ci { 968141cc406Sopenharmony_ci DBG(3, "%s: get total number of options - %u\n", __func__, HP5590_OPT_LAST); 969141cc406Sopenharmony_ci *((SANE_Int *) value) = HP5590_OPT_LAST; 970141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 971141cc406Sopenharmony_ci } 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci if (!scanner->opts) 974141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci DBG (DBG_proc, "%s: get option '%s' value\n", __func__, scanner->opts[option].name); 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci if (option == HP5590_OPT_BR_X) 979141cc406Sopenharmony_ci { 980141cc406Sopenharmony_ci *(SANE_Fixed *) value = SANE_FIX (scanner->br_x * 25.4); 981141cc406Sopenharmony_ci } 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci if (option == HP5590_OPT_BR_Y) 984141cc406Sopenharmony_ci { 985141cc406Sopenharmony_ci *(SANE_Fixed *) value = SANE_FIX (scanner->br_y * 25.4); 986141cc406Sopenharmony_ci } 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci if (option == HP5590_OPT_TL_X) 989141cc406Sopenharmony_ci { 990141cc406Sopenharmony_ci *(SANE_Fixed *) value = SANE_FIX ((scanner->tl_x) * 25.4); 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci if (option == HP5590_OPT_TL_Y) 994141cc406Sopenharmony_ci { 995141cc406Sopenharmony_ci *(SANE_Fixed *) value = SANE_FIX (scanner->tl_y * 25.4); 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci if (option == HP5590_OPT_MODE) 999141cc406Sopenharmony_ci { 1000141cc406Sopenharmony_ci switch (scanner->depth) { 1001141cc406Sopenharmony_ci case DEPTH_BW: 1002141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1003141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_MODE_LINEART, strlen (SANE_VALUE_SCAN_MODE_LINEART)); 1004141cc406Sopenharmony_ci break; 1005141cc406Sopenharmony_ci case DEPTH_GRAY: 1006141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1007141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_MODE_GRAY, strlen (SANE_VALUE_SCAN_MODE_GRAY)); 1008141cc406Sopenharmony_ci break; 1009141cc406Sopenharmony_ci case DEPTH_COLOR_24: 1010141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1011141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_24, strlen (SANE_VALUE_SCAN_MODE_COLOR_24)); 1012141cc406Sopenharmony_ci break; 1013141cc406Sopenharmony_ci case DEPTH_COLOR_48: 1014141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1015141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_48, strlen (SANE_VALUE_SCAN_MODE_COLOR_48)); 1016141cc406Sopenharmony_ci break; 1017141cc406Sopenharmony_ci default: 1018141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1019141cc406Sopenharmony_ci } 1020141cc406Sopenharmony_ci } 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci if (option == HP5590_OPT_SOURCE) 1023141cc406Sopenharmony_ci { 1024141cc406Sopenharmony_ci switch (scanner->source) { 1025141cc406Sopenharmony_ci case SOURCE_FLATBED: 1026141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1027141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_SOURCE_FLATBED, strlen (SANE_VALUE_SCAN_SOURCE_FLATBED)); 1028141cc406Sopenharmony_ci break; 1029141cc406Sopenharmony_ci case SOURCE_ADF: 1030141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1031141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF, strlen (SANE_VALUE_SCAN_SOURCE_ADF)); 1032141cc406Sopenharmony_ci break; 1033141cc406Sopenharmony_ci case SOURCE_ADF_DUPLEX: 1034141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1035141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX, strlen (SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX)); 1036141cc406Sopenharmony_ci break; 1037141cc406Sopenharmony_ci case SOURCE_TMA_SLIDES: 1038141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1039141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_SLIDES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_SLIDES)); 1040141cc406Sopenharmony_ci break; 1041141cc406Sopenharmony_ci case SOURCE_TMA_NEGATIVES: 1042141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1043141cc406Sopenharmony_ci memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES)); 1044141cc406Sopenharmony_ci break; 1045141cc406Sopenharmony_ci case SOURCE_NONE: 1046141cc406Sopenharmony_ci default: 1047141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1048141cc406Sopenharmony_ci } 1049141cc406Sopenharmony_ci } 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci if (option == HP5590_OPT_RESOLUTION) 1052141cc406Sopenharmony_ci { 1053141cc406Sopenharmony_ci *(SANE_Int *) value = scanner->dpi; 1054141cc406Sopenharmony_ci } 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci if (option == HP5590_OPT_LAMP_TIMEOUT) 1057141cc406Sopenharmony_ci { 1058141cc406Sopenharmony_ci *(SANE_Bool *) value = scanner->extend_lamp_timeout; 1059141cc406Sopenharmony_ci } 1060141cc406Sopenharmony_ci 1061141cc406Sopenharmony_ci if (option == HP5590_OPT_WAIT_FOR_BUTTON) 1062141cc406Sopenharmony_ci { 1063141cc406Sopenharmony_ci *(SANE_Bool *) value = scanner->wait_for_button; 1064141cc406Sopenharmony_ci } 1065141cc406Sopenharmony_ci 1066141cc406Sopenharmony_ci if (option == HP5590_OPT_BUTTON_PRESSED) 1067141cc406Sopenharmony_ci { 1068141cc406Sopenharmony_ci enum button_status button_pressed = BUTTON_NONE; 1069141cc406Sopenharmony_ci SANE_Status ret = read_button_pressed(scanner, &button_pressed); 1070141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1071141cc406Sopenharmony_ci return ret; 1072141cc406Sopenharmony_ci switch (button_pressed) { 1073141cc406Sopenharmony_ci case BUTTON_POWER: 1074141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_POWER_KEY, scanner->opts[option].size); 1075141cc406Sopenharmony_ci break; 1076141cc406Sopenharmony_ci case BUTTON_SCAN: 1077141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_SCAN_KEY, scanner->opts[option].size); 1078141cc406Sopenharmony_ci break; 1079141cc406Sopenharmony_ci case BUTTON_COLLECT: 1080141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_COLLECT_KEY, scanner->opts[option].size); 1081141cc406Sopenharmony_ci break; 1082141cc406Sopenharmony_ci case BUTTON_FILE: 1083141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_FILE_KEY, scanner->opts[option].size); 1084141cc406Sopenharmony_ci break; 1085141cc406Sopenharmony_ci case BUTTON_EMAIL: 1086141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_EMAIL_KEY, scanner->opts[option].size); 1087141cc406Sopenharmony_ci break; 1088141cc406Sopenharmony_ci case BUTTON_COPY: 1089141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_COPY_KEY, scanner->opts[option].size); 1090141cc406Sopenharmony_ci break; 1091141cc406Sopenharmony_ci case BUTTON_UP: 1092141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_UP_KEY, scanner->opts[option].size); 1093141cc406Sopenharmony_ci break; 1094141cc406Sopenharmony_ci case BUTTON_DOWN: 1095141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_DOWN_KEY, scanner->opts[option].size); 1096141cc406Sopenharmony_ci break; 1097141cc406Sopenharmony_ci case BUTTON_MODE: 1098141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_MODE_KEY, scanner->opts[option].size); 1099141cc406Sopenharmony_ci break; 1100141cc406Sopenharmony_ci case BUTTON_CANCEL: 1101141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_CANCEL_KEY, scanner->opts[option].size); 1102141cc406Sopenharmony_ci break; 1103141cc406Sopenharmony_ci case BUTTON_NONE: 1104141cc406Sopenharmony_ci default: 1105141cc406Sopenharmony_ci strncpy (value, BUTTON_PRESSED_VALUE_NONE_KEY, scanner->opts[option].size); 1106141cc406Sopenharmony_ci } 1107141cc406Sopenharmony_ci } 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci if (option == HP5590_OPT_COLOR_LED) 1110141cc406Sopenharmony_ci { 1111141cc406Sopenharmony_ci SANE_Int lcd_counter = 0; 1112141cc406Sopenharmony_ci enum color_led_status color_led = LED_COLOR; 1113141cc406Sopenharmony_ci SANE_Status ret = read_lcd_and_led_values(scanner, &lcd_counter, &color_led); 1114141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1115141cc406Sopenharmony_ci return ret; 1116141cc406Sopenharmony_ci switch (color_led) { 1117141cc406Sopenharmony_ci case LED_BLACKWHITE: 1118141cc406Sopenharmony_ci strncpy (value, COLOR_LED_VALUE_BLACKWHITE_KEY, scanner->opts[option].size); 1119141cc406Sopenharmony_ci break; 1120141cc406Sopenharmony_ci case LED_COLOR: 1121141cc406Sopenharmony_ci default: 1122141cc406Sopenharmony_ci strncpy (value, COLOR_LED_VALUE_COLOR_KEY, scanner->opts[option].size); 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci } 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci if (option == HP5590_OPT_LCD_COUNTER) 1127141cc406Sopenharmony_ci { 1128141cc406Sopenharmony_ci SANE_Int lcd_counter = 0; 1129141cc406Sopenharmony_ci enum color_led_status color_led = LED_COLOR; 1130141cc406Sopenharmony_ci SANE_Status ret = read_lcd_and_led_values(scanner, &lcd_counter, &color_led); 1131141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1132141cc406Sopenharmony_ci return ret; 1133141cc406Sopenharmony_ci *(SANE_Int *) value = lcd_counter; 1134141cc406Sopenharmony_ci } 1135141cc406Sopenharmony_ci 1136141cc406Sopenharmony_ci if (option == HP5590_OPT_DOC_IN_ADF) 1137141cc406Sopenharmony_ci { 1138141cc406Sopenharmony_ci SANE_Bool doc_in_adf = SANE_FALSE; 1139141cc406Sopenharmony_ci SANE_Status ret = read_doc_in_adf_value(scanner, &doc_in_adf); 1140141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1141141cc406Sopenharmony_ci return ret; 1142141cc406Sopenharmony_ci *(SANE_Bool *) value = doc_in_adf; 1143141cc406Sopenharmony_ci } 1144141cc406Sopenharmony_ci 1145141cc406Sopenharmony_ci if (option == HP5590_OPT_PREVIEW) 1146141cc406Sopenharmony_ci { 1147141cc406Sopenharmony_ci *(SANE_Bool *) value = scanner->preview; 1148141cc406Sopenharmony_ci } 1149141cc406Sopenharmony_ci 1150141cc406Sopenharmony_ci if (option == HP5590_OPT_OVERWRITE_EOP_PIXEL) 1151141cc406Sopenharmony_ci { 1152141cc406Sopenharmony_ci *(SANE_Bool *) value = scanner->overwrite_eop_pixel; 1153141cc406Sopenharmony_ci } 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci if (option == HP5590_OPT_TRAILING_LINES_MODE) 1156141cc406Sopenharmony_ci { 1157141cc406Sopenharmony_ci switch (scanner->eop_trailing_lines_mode) { 1158141cc406Sopenharmony_ci case TRAILING_LINES_MODE_RAW: 1159141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1160141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_RAW_KEY, strlen (TRAILING_LINES_MODE_RAW_KEY)); 1161141cc406Sopenharmony_ci break; 1162141cc406Sopenharmony_ci case TRAILING_LINES_MODE_LAST: 1163141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1164141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_LAST_KEY, strlen (TRAILING_LINES_MODE_LAST_KEY)); 1165141cc406Sopenharmony_ci break; 1166141cc406Sopenharmony_ci case TRAILING_LINES_MODE_RASTER: 1167141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1168141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_RASTER_KEY, strlen (TRAILING_LINES_MODE_RASTER_KEY)); 1169141cc406Sopenharmony_ci break; 1170141cc406Sopenharmony_ci case TRAILING_LINES_MODE_BLACK: 1171141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1172141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_BLACK_KEY, strlen (TRAILING_LINES_MODE_BLACK_KEY)); 1173141cc406Sopenharmony_ci break; 1174141cc406Sopenharmony_ci case TRAILING_LINES_MODE_WHITE: 1175141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1176141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_WHITE_KEY, strlen (TRAILING_LINES_MODE_WHITE_KEY)); 1177141cc406Sopenharmony_ci break; 1178141cc406Sopenharmony_ci case TRAILING_LINES_MODE_COLOR: 1179141cc406Sopenharmony_ci memset (value , 0, scanner->opts[option].size); 1180141cc406Sopenharmony_ci memcpy (value, TRAILING_LINES_MODE_COLOR_KEY, strlen (TRAILING_LINES_MODE_COLOR_KEY)); 1181141cc406Sopenharmony_ci break; 1182141cc406Sopenharmony_ci default: 1183141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1184141cc406Sopenharmony_ci } 1185141cc406Sopenharmony_ci } 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci if (option == HP5590_OPT_TRAILING_LINES_COLOR) 1188141cc406Sopenharmony_ci { 1189141cc406Sopenharmony_ci *(SANE_Int *) value = scanner->eop_trailing_lines_color; 1190141cc406Sopenharmony_ci } 1191141cc406Sopenharmony_ci } 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci if (action == SANE_ACTION_SET_VALUE) 1194141cc406Sopenharmony_ci { 1195141cc406Sopenharmony_ci if (option == HP5590_OPT_NUM) 1196141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci if (option == HP5590_OPT_BR_X) 1199141cc406Sopenharmony_ci { 1200141cc406Sopenharmony_ci float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; 1201141cc406Sopenharmony_ci if (val <= scanner->tl_x) 1202141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1203141cc406Sopenharmony_ci scanner->br_x = val; 1204141cc406Sopenharmony_ci if (info) 1205141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS; 1206141cc406Sopenharmony_ci } 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci if (option == HP5590_OPT_BR_Y) 1209141cc406Sopenharmony_ci { 1210141cc406Sopenharmony_ci float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; 1211141cc406Sopenharmony_ci if (val <= scanner->tl_y) 1212141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1213141cc406Sopenharmony_ci scanner->br_y = val; 1214141cc406Sopenharmony_ci if (info) 1215141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS; 1216141cc406Sopenharmony_ci } 1217141cc406Sopenharmony_ci 1218141cc406Sopenharmony_ci if (option == HP5590_OPT_TL_X) 1219141cc406Sopenharmony_ci { 1220141cc406Sopenharmony_ci float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; 1221141cc406Sopenharmony_ci if (val >= scanner->br_x) 1222141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1223141cc406Sopenharmony_ci scanner->tl_x = val; 1224141cc406Sopenharmony_ci if (info) 1225141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS; 1226141cc406Sopenharmony_ci } 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci if (option == HP5590_OPT_TL_Y) 1229141cc406Sopenharmony_ci { 1230141cc406Sopenharmony_ci float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; 1231141cc406Sopenharmony_ci if (val >= scanner->br_y) 1232141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1233141cc406Sopenharmony_ci scanner->tl_y = val; 1234141cc406Sopenharmony_ci if (info) 1235141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS; 1236141cc406Sopenharmony_ci } 1237141cc406Sopenharmony_ci 1238141cc406Sopenharmony_ci if (option == HP5590_OPT_MODE) 1239141cc406Sopenharmony_ci { 1240141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_LINEART) == 0) 1241141cc406Sopenharmony_ci { 1242141cc406Sopenharmony_ci scanner->depth = DEPTH_BW; 1243141cc406Sopenharmony_ci } 1244141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_GRAY) == 0) 1245141cc406Sopenharmony_ci { 1246141cc406Sopenharmony_ci scanner->depth = DEPTH_GRAY; 1247141cc406Sopenharmony_ci } 1248141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_24) == 0) 1249141cc406Sopenharmony_ci { 1250141cc406Sopenharmony_ci scanner->depth = DEPTH_COLOR_24; 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_48) == 0) 1253141cc406Sopenharmony_ci { 1254141cc406Sopenharmony_ci scanner->depth = DEPTH_COLOR_48; 1255141cc406Sopenharmony_ci } 1256141cc406Sopenharmony_ci else 1257141cc406Sopenharmony_ci { 1258141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1259141cc406Sopenharmony_ci } 1260141cc406Sopenharmony_ci 1261141cc406Sopenharmony_ci if (info) 1262141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1263141cc406Sopenharmony_ci } 1264141cc406Sopenharmony_ci 1265141cc406Sopenharmony_ci if (option == HP5590_OPT_SOURCE) 1266141cc406Sopenharmony_ci { 1267141cc406Sopenharmony_ci range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_FLATBED) == 0) 1270141cc406Sopenharmony_ci { 1271141cc406Sopenharmony_ci scanner->source = SOURCE_FLATBED; 1272141cc406Sopenharmony_ci range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); 1273141cc406Sopenharmony_ci range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); 1274141cc406Sopenharmony_ci scanner->br_x = scanner->info->max_size_x; 1275141cc406Sopenharmony_ci scanner->br_y = scanner->info->max_size_y; 1276141cc406Sopenharmony_ci } 1277141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF) == 0) 1278141cc406Sopenharmony_ci { 1279141cc406Sopenharmony_ci /* In ADF modes the device can scan up to ADF_MAX_Y_INCHES, which is usually 1280141cc406Sopenharmony_ci * bigger than what scanner reports back during initialization 1281141cc406Sopenharmony_ci */ 1282141cc406Sopenharmony_ci if (! (scanner->info->features & FEATURE_ADF)) 1283141cc406Sopenharmony_ci { 1284141cc406Sopenharmony_ci DBG(DBG_err, "ADF feature not available: %s\n", (char *) value); 1285141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1286141cc406Sopenharmony_ci } 1287141cc406Sopenharmony_ci scanner->source = SOURCE_ADF; 1288141cc406Sopenharmony_ci range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); 1289141cc406Sopenharmony_ci range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4); 1290141cc406Sopenharmony_ci scanner->br_x = scanner->info->max_size_x; 1291141cc406Sopenharmony_ci scanner->br_y = ADF_MAX_Y_INCHES; 1292141cc406Sopenharmony_ci } 1293141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX) == 0) 1294141cc406Sopenharmony_ci { 1295141cc406Sopenharmony_ci if (! (scanner->info->features & FEATURE_ADF)) 1296141cc406Sopenharmony_ci { 1297141cc406Sopenharmony_ci DBG(DBG_err, "ADF feature not available: %s\n", (char *) value); 1298141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1299141cc406Sopenharmony_ci } 1300141cc406Sopenharmony_ci scanner->source = SOURCE_ADF_DUPLEX; 1301141cc406Sopenharmony_ci range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); 1302141cc406Sopenharmony_ci range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4); 1303141cc406Sopenharmony_ci scanner->br_x = scanner->info->max_size_x; 1304141cc406Sopenharmony_ci scanner->br_y = ADF_MAX_Y_INCHES; 1305141cc406Sopenharmony_ci } 1306141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_SLIDES) == 0) 1307141cc406Sopenharmony_ci { 1308141cc406Sopenharmony_ci if (! (scanner->info->features & FEATURE_TMA)) 1309141cc406Sopenharmony_ci { 1310141cc406Sopenharmony_ci DBG(DBG_err, "TMA feature not available: %s\n", (char *) value); 1311141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1312141cc406Sopenharmony_ci } 1313141cc406Sopenharmony_ci scanner->source = SOURCE_TMA_SLIDES; 1314141cc406Sopenharmony_ci range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); 1315141cc406Sopenharmony_ci range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); 1316141cc406Sopenharmony_ci scanner->br_x = TMA_MAX_X_INCHES; 1317141cc406Sopenharmony_ci scanner->br_y = TMA_MAX_Y_INCHES; 1318141cc406Sopenharmony_ci } 1319141cc406Sopenharmony_ci else if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES) == 0) 1320141cc406Sopenharmony_ci { 1321141cc406Sopenharmony_ci if (! (scanner->info->features & FEATURE_TMA)) 1322141cc406Sopenharmony_ci { 1323141cc406Sopenharmony_ci DBG(DBG_err, "TMA feature not available: %s\n", (char *) value); 1324141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1325141cc406Sopenharmony_ci } 1326141cc406Sopenharmony_ci scanner->source = SOURCE_TMA_NEGATIVES; 1327141cc406Sopenharmony_ci range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); 1328141cc406Sopenharmony_ci range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); 1329141cc406Sopenharmony_ci scanner->br_x = TMA_MAX_X_INCHES; 1330141cc406Sopenharmony_ci scanner->br_y = TMA_MAX_Y_INCHES; 1331141cc406Sopenharmony_ci } 1332141cc406Sopenharmony_ci else 1333141cc406Sopenharmony_ci { 1334141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1335141cc406Sopenharmony_ci } 1336141cc406Sopenharmony_ci if (info) 1337141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1338141cc406Sopenharmony_ci } 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (option == HP5590_OPT_RESOLUTION) 1341141cc406Sopenharmony_ci { 1342141cc406Sopenharmony_ci scanner->dpi = *(SANE_Int *) value; 1343141cc406Sopenharmony_ci if (info) 1344141cc406Sopenharmony_ci *info = SANE_INFO_RELOAD_PARAMS; 1345141cc406Sopenharmony_ci } 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci if (option == HP5590_OPT_LAMP_TIMEOUT) 1348141cc406Sopenharmony_ci { 1349141cc406Sopenharmony_ci scanner->extend_lamp_timeout = *(SANE_Bool *) value; 1350141cc406Sopenharmony_ci } 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci if (option == HP5590_OPT_WAIT_FOR_BUTTON) 1353141cc406Sopenharmony_ci { 1354141cc406Sopenharmony_ci scanner->wait_for_button = *(SANE_Bool *) value; 1355141cc406Sopenharmony_ci } 1356141cc406Sopenharmony_ci 1357141cc406Sopenharmony_ci if (option == HP5590_OPT_BUTTON_PRESSED) 1358141cc406Sopenharmony_ci { 1359141cc406Sopenharmony_ci DBG(DBG_verbose, "State of buttons is read only. Setting of state will be ignored.\n"); 1360141cc406Sopenharmony_ci } 1361141cc406Sopenharmony_ci 1362141cc406Sopenharmony_ci if (option == HP5590_OPT_COLOR_LED) 1363141cc406Sopenharmony_ci { 1364141cc406Sopenharmony_ci DBG(DBG_verbose, "State of color LED indicator is read only. Setting of state will be ignored.\n"); 1365141cc406Sopenharmony_ci } 1366141cc406Sopenharmony_ci 1367141cc406Sopenharmony_ci if (option == HP5590_OPT_LCD_COUNTER) 1368141cc406Sopenharmony_ci { 1369141cc406Sopenharmony_ci DBG(DBG_verbose, "Value of LCD counter is read only. Setting of value will be ignored.\n"); 1370141cc406Sopenharmony_ci } 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci if (option == HP5590_OPT_DOC_IN_ADF) 1373141cc406Sopenharmony_ci { 1374141cc406Sopenharmony_ci DBG(DBG_verbose, "Value of document-available indicator is read only. Setting of value will be ignored.\n"); 1375141cc406Sopenharmony_ci } 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci if (option == HP5590_OPT_PREVIEW) 1378141cc406Sopenharmony_ci { 1379141cc406Sopenharmony_ci scanner->preview = *(SANE_Bool *) value; 1380141cc406Sopenharmony_ci } 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci if (option == HP5590_OPT_OVERWRITE_EOP_PIXEL) 1383141cc406Sopenharmony_ci { 1384141cc406Sopenharmony_ci scanner->overwrite_eop_pixel = *(SANE_Bool *) value; 1385141cc406Sopenharmony_ci } 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci if (option == HP5590_OPT_TRAILING_LINES_MODE) 1388141cc406Sopenharmony_ci { 1389141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_RAW_KEY) == 0) 1390141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_RAW; 1391141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_LAST_KEY) == 0) 1392141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_LAST; 1393141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_RASTER_KEY) == 0) 1394141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_RASTER; 1395141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_BLACK_KEY) == 0) 1396141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_BLACK; 1397141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_WHITE_KEY) == 0) 1398141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_WHITE; 1399141cc406Sopenharmony_ci if (strcmp ((char *) value, (char *) TRAILING_LINES_MODE_COLOR_KEY) == 0) 1400141cc406Sopenharmony_ci scanner->eop_trailing_lines_mode = TRAILING_LINES_MODE_COLOR; 1401141cc406Sopenharmony_ci } 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci if (option == HP5590_OPT_TRAILING_LINES_COLOR) 1404141cc406Sopenharmony_ci { 1405141cc406Sopenharmony_ci scanner->eop_trailing_lines_color = *(SANE_Int *) value; 1406141cc406Sopenharmony_ci } 1407141cc406Sopenharmony_ci } 1408141cc406Sopenharmony_ci 1409141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1410141cc406Sopenharmony_ci} 1411141cc406Sopenharmony_ci 1412141cc406Sopenharmony_ci/******************************************************************************/ 1413141cc406Sopenharmony_ciSANE_Status sane_get_parameters (SANE_Handle handle, 1414141cc406Sopenharmony_ci SANE_Parameters * params) 1415141cc406Sopenharmony_ci{ 1416141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 1417141cc406Sopenharmony_ci SANE_Status ret; 1418141cc406Sopenharmony_ci unsigned int pixel_bits; 1419141cc406Sopenharmony_ci 1420141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 1421141cc406Sopenharmony_ci 1422141cc406Sopenharmony_ci if (!params) 1423141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci if (!handle) 1426141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1427141cc406Sopenharmony_ci 1428141cc406Sopenharmony_ci ret = calc_image_params (scanner, 1429141cc406Sopenharmony_ci (unsigned int *) &pixel_bits, 1430141cc406Sopenharmony_ci (unsigned int *) ¶ms->pixels_per_line, 1431141cc406Sopenharmony_ci (unsigned int *) ¶ms->bytes_per_line, 1432141cc406Sopenharmony_ci (unsigned int *) ¶ms->lines, NULL); 1433141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1434141cc406Sopenharmony_ci return ret; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci switch (scanner->depth) { 1437141cc406Sopenharmony_ci case DEPTH_BW: 1438141cc406Sopenharmony_ci params->depth = pixel_bits; 1439141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 1440141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 1441141cc406Sopenharmony_ci break; 1442141cc406Sopenharmony_ci case DEPTH_GRAY: 1443141cc406Sopenharmony_ci params->depth = pixel_bits; 1444141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 1445141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 1446141cc406Sopenharmony_ci break; 1447141cc406Sopenharmony_ci case DEPTH_COLOR_24: 1448141cc406Sopenharmony_ci params->depth = pixel_bits / 3; 1449141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 1450141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 1451141cc406Sopenharmony_ci break; 1452141cc406Sopenharmony_ci case DEPTH_COLOR_48: 1453141cc406Sopenharmony_ci params->depth = pixel_bits / 3; 1454141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 1455141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 1456141cc406Sopenharmony_ci break; 1457141cc406Sopenharmony_ci default: 1458141cc406Sopenharmony_ci DBG(DBG_err, "%s: Unknown depth\n", __func__); 1459141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1460141cc406Sopenharmony_ci } 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci DBG (DBG_proc, "format: %u, last_frame: %u, bytes_per_line: %u, " 1464141cc406Sopenharmony_ci "pixels_per_line: %u, lines: %u, depth: %u\n", 1465141cc406Sopenharmony_ci params->format, params->last_frame, 1466141cc406Sopenharmony_ci params->bytes_per_line, params->pixels_per_line, 1467141cc406Sopenharmony_ci params->lines, params->depth); 1468141cc406Sopenharmony_ci 1469141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1470141cc406Sopenharmony_ci} 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci/******************************************************************************/ 1473141cc406Sopenharmony_ciSANE_Status 1474141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1475141cc406Sopenharmony_ci{ 1476141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 1477141cc406Sopenharmony_ci SANE_Status ret; 1478141cc406Sopenharmony_ci unsigned int bytes_per_line; 1479141cc406Sopenharmony_ci 1480141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 1481141cc406Sopenharmony_ci 1482141cc406Sopenharmony_ci if (!scanner) 1483141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1484141cc406Sopenharmony_ci 1485141cc406Sopenharmony_ci /* Cleanup for all pages. */ 1486141cc406Sopenharmony_ci if (scanner->eop_last_line_data) 1487141cc406Sopenharmony_ci { 1488141cc406Sopenharmony_ci /* Release last line data */ 1489141cc406Sopenharmony_ci free (scanner->eop_last_line_data); 1490141cc406Sopenharmony_ci scanner->eop_last_line_data = NULL; 1491141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos = 0; 1492141cc406Sopenharmony_ci } 1493141cc406Sopenharmony_ci if (scanner->one_line_read_buffer) 1494141cc406Sopenharmony_ci { 1495141cc406Sopenharmony_ci /* Release temporary line buffer. */ 1496141cc406Sopenharmony_ci free (scanner->one_line_read_buffer); 1497141cc406Sopenharmony_ci scanner->one_line_read_buffer = NULL; 1498141cc406Sopenharmony_ci scanner->one_line_read_buffer_rpos = 0; 1499141cc406Sopenharmony_ci } 1500141cc406Sopenharmony_ci if (scanner->color_shift_line_buffer1) 1501141cc406Sopenharmony_ci { 1502141cc406Sopenharmony_ci /* Release line buffer1 for shifting colors. */ 1503141cc406Sopenharmony_ci free (scanner->color_shift_line_buffer1); 1504141cc406Sopenharmony_ci scanner->color_shift_line_buffer1 = NULL; 1505141cc406Sopenharmony_ci scanner->color_shift_buffered_lines1 = 0; 1506141cc406Sopenharmony_ci } 1507141cc406Sopenharmony_ci if (scanner->color_shift_line_buffer2) 1508141cc406Sopenharmony_ci { 1509141cc406Sopenharmony_ci /* Release line buffer2 for shifting colors. */ 1510141cc406Sopenharmony_ci free (scanner->color_shift_line_buffer2); 1511141cc406Sopenharmony_ci scanner->color_shift_line_buffer2 = NULL; 1512141cc406Sopenharmony_ci scanner->color_shift_buffered_lines2 = 0; 1513141cc406Sopenharmony_ci } 1514141cc406Sopenharmony_ci 1515141cc406Sopenharmony_ci if ( scanner->scanning == SANE_TRUE 1516141cc406Sopenharmony_ci && ( scanner->source == SOURCE_ADF 1517141cc406Sopenharmony_ci || scanner->source == SOURCE_ADF_DUPLEX)) 1518141cc406Sopenharmony_ci { 1519141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: Scanner is scanning, check if more data is available\n", 1520141cc406Sopenharmony_ci __func__); 1521141cc406Sopenharmony_ci ret = hp5590_is_data_available (scanner->dn, scanner->proto_flags); 1522141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD) 1523141cc406Sopenharmony_ci { 1524141cc406Sopenharmony_ci DBG (DBG_verbose, "%s: More data is available\n", __func__); 1525141cc406Sopenharmony_ci scanner->transferred_image_size = scanner->image_size; 1526141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1527141cc406Sopenharmony_ci } 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci if (ret != SANE_STATUS_NO_DOCS) 1530141cc406Sopenharmony_ci return ret; 1531141cc406Sopenharmony_ci } 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci sane_cancel (handle); 1534141cc406Sopenharmony_ci 1535141cc406Sopenharmony_ci if (scanner->wait_for_button) 1536141cc406Sopenharmony_ci { 1537141cc406Sopenharmony_ci enum button_status status; 1538141cc406Sopenharmony_ci for (;;) 1539141cc406Sopenharmony_ci { 1540141cc406Sopenharmony_ci ret = hp5590_read_buttons (scanner->dn, 1541141cc406Sopenharmony_ci scanner->proto_flags, 1542141cc406Sopenharmony_ci &status); 1543141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1544141cc406Sopenharmony_ci return ret; 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci if (status == BUTTON_CANCEL) 1547141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci if (status != BUTTON_NONE && status != BUTTON_POWER) 1550141cc406Sopenharmony_ci break; 1551141cc406Sopenharmony_ci usleep (100 * 1000); 1552141cc406Sopenharmony_ci } 1553141cc406Sopenharmony_ci } 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci DBG (DBG_verbose, "Init scanner\n"); 1556141cc406Sopenharmony_ci ret = hp5590_init_scanner (scanner->dn, scanner->proto_flags, 1557141cc406Sopenharmony_ci NULL, SCANNER_NONE); 1558141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1559141cc406Sopenharmony_ci return ret; 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci ret = hp5590_power_status (scanner->dn, scanner->proto_flags); 1562141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1563141cc406Sopenharmony_ci return ret; 1564141cc406Sopenharmony_ci 1565141cc406Sopenharmony_ci DBG (DBG_verbose, "Wakeup\n"); 1566141cc406Sopenharmony_ci ret = hp5590_select_source_and_wakeup (scanner->dn, scanner->proto_flags, 1567141cc406Sopenharmony_ci scanner->source, 1568141cc406Sopenharmony_ci scanner->extend_lamp_timeout); 1569141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1570141cc406Sopenharmony_ci return ret; 1571141cc406Sopenharmony_ci 1572141cc406Sopenharmony_ci ret = hp5590_set_scan_params (scanner->dn, 1573141cc406Sopenharmony_ci scanner->proto_flags, 1574141cc406Sopenharmony_ci scanner->info, 1575141cc406Sopenharmony_ci scanner->tl_x * scanner->dpi, 1576141cc406Sopenharmony_ci scanner->tl_y * scanner->dpi, 1577141cc406Sopenharmony_ci (scanner->br_x - scanner->tl_x) * scanner->dpi, 1578141cc406Sopenharmony_ci (scanner->br_y - scanner->tl_y) * scanner->dpi, 1579141cc406Sopenharmony_ci scanner->dpi, 1580141cc406Sopenharmony_ci scanner->depth, scanner->preview ? MODE_PREVIEW : MODE_NORMAL, 1581141cc406Sopenharmony_ci scanner->source); 1582141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1583141cc406Sopenharmony_ci { 1584141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1585141cc406Sopenharmony_ci return ret; 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci ret = calc_image_params (scanner, NULL, NULL, 1589141cc406Sopenharmony_ci &bytes_per_line, NULL, 1590141cc406Sopenharmony_ci &scanner->image_size); 1591141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1592141cc406Sopenharmony_ci { 1593141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1594141cc406Sopenharmony_ci return ret; 1595141cc406Sopenharmony_ci } 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci scanner->transferred_image_size = scanner->image_size; 1598141cc406Sopenharmony_ci 1599141cc406Sopenharmony_ci if ( scanner->depth == DEPTH_COLOR_24 1600141cc406Sopenharmony_ci || scanner->depth == DEPTH_COLOR_48) 1601141cc406Sopenharmony_ci { 1602141cc406Sopenharmony_ci DBG (1, "Color 24/48 bits: checking if image size is correctly " 1603141cc406Sopenharmony_ci "aligned on number of colors\n"); 1604141cc406Sopenharmony_ci if (bytes_per_line % 3) 1605141cc406Sopenharmony_ci { 1606141cc406Sopenharmony_ci DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on number of colors (3) " 1607141cc406Sopenharmony_ci "(image size: %llu, bytes per line %u)\n", 1608141cc406Sopenharmony_ci scanner->image_size, bytes_per_line); 1609141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1610141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1611141cc406Sopenharmony_ci } 1612141cc406Sopenharmony_ci DBG (1, "Color 24/48 bits: image size is correctly aligned on number of colors " 1613141cc406Sopenharmony_ci "(image size: %llu, bytes per line %u)\n", 1614141cc406Sopenharmony_ci scanner->image_size, bytes_per_line); 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci DBG (1, "Color 24/48 bits: checking if image size is correctly " 1617141cc406Sopenharmony_ci "aligned on bytes per line\n"); 1618141cc406Sopenharmony_ci if (scanner->image_size % bytes_per_line) 1619141cc406Sopenharmony_ci { 1620141cc406Sopenharmony_ci DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on bytes per line " 1621141cc406Sopenharmony_ci "(image size: %llu, bytes per line %u)\n", 1622141cc406Sopenharmony_ci scanner->image_size, bytes_per_line); 1623141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1624141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1625141cc406Sopenharmony_ci } 1626141cc406Sopenharmony_ci DBG (1, "Color 24/48 bits: image size correctly aligned on bytes per line " 1627141cc406Sopenharmony_ci "(images size: %llu, bytes per line: %u)\n", 1628141cc406Sopenharmony_ci scanner->image_size, bytes_per_line); 1629141cc406Sopenharmony_ci } 1630141cc406Sopenharmony_ci 1631141cc406Sopenharmony_ci DBG (DBG_verbose, "Final image size: %llu\n", scanner->image_size); 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci DBG (DBG_verbose, "Reverse calibration maps\n"); 1634141cc406Sopenharmony_ci ret = hp5590_send_reverse_calibration_map (scanner->dn, scanner->proto_flags); 1635141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1636141cc406Sopenharmony_ci { 1637141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1638141cc406Sopenharmony_ci return ret; 1639141cc406Sopenharmony_ci } 1640141cc406Sopenharmony_ci 1641141cc406Sopenharmony_ci DBG (DBG_verbose, "Forward calibration maps\n"); 1642141cc406Sopenharmony_ci ret = hp5590_send_forward_calibration_maps (scanner->dn, scanner->proto_flags); 1643141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1644141cc406Sopenharmony_ci { 1645141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1646141cc406Sopenharmony_ci return ret; 1647141cc406Sopenharmony_ci } 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci if (scanner->adf_next_page_lines_data) 1650141cc406Sopenharmony_ci { 1651141cc406Sopenharmony_ci free (scanner->adf_next_page_lines_data); 1652141cc406Sopenharmony_ci scanner->adf_next_page_lines_data = NULL; 1653141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_size = 0; 1654141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos = 0; 1655141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos = 0; 1656141cc406Sopenharmony_ci } 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci scanner->scanning = SANE_TRUE; 1659141cc406Sopenharmony_ci 1660141cc406Sopenharmony_ci DBG (DBG_verbose, "Starting scan\n"); 1661141cc406Sopenharmony_ci ret = hp5590_start_scan (scanner->dn, scanner->proto_flags); 1662141cc406Sopenharmony_ci /* Check for paper jam */ 1663141cc406Sopenharmony_ci if ( ret == SANE_STATUS_DEVICE_BUSY 1664141cc406Sopenharmony_ci && ( scanner->source == SOURCE_ADF 1665141cc406Sopenharmony_ci || scanner->source == SOURCE_ADF_DUPLEX)) 1666141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1669141cc406Sopenharmony_ci { 1670141cc406Sopenharmony_ci hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); 1671141cc406Sopenharmony_ci return ret; 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci 1674141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1675141cc406Sopenharmony_ci} 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci/******************************************************************************/ 1678141cc406Sopenharmony_cistatic void 1679141cc406Sopenharmony_ciinvert_negative_colors (unsigned char *buf, unsigned int bytes_per_line, struct hp5590_scanner *scanner) 1680141cc406Sopenharmony_ci{ 1681141cc406Sopenharmony_ci /* Invert lineart or negatives. */ 1682141cc406Sopenharmony_ci int is_linear = (scanner->depth == DEPTH_BW); 1683141cc406Sopenharmony_ci int is_negative = (scanner->source == SOURCE_TMA_NEGATIVES); 1684141cc406Sopenharmony_ci if (is_linear ^ is_negative) 1685141cc406Sopenharmony_ci { 1686141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; k++) 1687141cc406Sopenharmony_ci buf[k] ^= 0xff; 1688141cc406Sopenharmony_ci } 1689141cc406Sopenharmony_ci} 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci/******************************************************************************/ 1692141cc406Sopenharmony_cistatic SANE_Status 1693141cc406Sopenharmony_ciconvert_gray_and_lineart (struct hp5590_scanner *scanner, SANE_Byte *data, SANE_Int size) 1694141cc406Sopenharmony_ci{ 1695141cc406Sopenharmony_ci unsigned int pixels_per_line; 1696141cc406Sopenharmony_ci unsigned int pixel_bits; 1697141cc406Sopenharmony_ci unsigned int bytes_per_line; 1698141cc406Sopenharmony_ci unsigned int lines; 1699141cc406Sopenharmony_ci unsigned char *buf; 1700141cc406Sopenharmony_ci SANE_Status ret; 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_ci hp5590_assert (scanner != NULL); 1703141cc406Sopenharmony_ci hp5590_assert (data != NULL); 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci if ( ! (scanner->depth == DEPTH_BW || scanner->depth == DEPTH_GRAY)) 1706141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1707141cc406Sopenharmony_ci 1708141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci ret = calc_image_params (scanner, 1711141cc406Sopenharmony_ci &pixel_bits, 1712141cc406Sopenharmony_ci &pixels_per_line, &bytes_per_line, 1713141cc406Sopenharmony_ci NULL, NULL); 1714141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1715141cc406Sopenharmony_ci return ret; 1716141cc406Sopenharmony_ci 1717141cc406Sopenharmony_ci lines = size / bytes_per_line; 1718141cc406Sopenharmony_ci 1719141cc406Sopenharmony_ci buf = data; 1720141cc406Sopenharmony_ci for (unsigned int i = 0; i < lines; buf += bytes_per_line, ++i) 1721141cc406Sopenharmony_ci { 1722141cc406Sopenharmony_ci if (! scanner->eop_last_line_data) 1723141cc406Sopenharmony_ci { 1724141cc406Sopenharmony_ci if (pixels_per_line > 0) 1725141cc406Sopenharmony_ci { 1726141cc406Sopenharmony_ci /* Test for last-line indicator pixel. If found, store last line 1727141cc406Sopenharmony_ci * and optionally overwrite indicator pixel with neighbor value. 1728141cc406Sopenharmony_ci */ 1729141cc406Sopenharmony_ci unsigned int j = bytes_per_line - 1; 1730141cc406Sopenharmony_ci int eop_found = 0; 1731141cc406Sopenharmony_ci if (scanner->depth == DEPTH_GRAY) 1732141cc406Sopenharmony_ci { 1733141cc406Sopenharmony_ci eop_found = (buf[j] != 0); 1734141cc406Sopenharmony_ci if (scanner->overwrite_eop_pixel && (j > 0)) 1735141cc406Sopenharmony_ci { 1736141cc406Sopenharmony_ci buf[j] = buf[j-1]; 1737141cc406Sopenharmony_ci } 1738141cc406Sopenharmony_ci } 1739141cc406Sopenharmony_ci else if (scanner->depth == DEPTH_BW) 1740141cc406Sopenharmony_ci { 1741141cc406Sopenharmony_ci eop_found = (buf[j] != 0); 1742141cc406Sopenharmony_ci if (scanner->overwrite_eop_pixel && (j > 0)) 1743141cc406Sopenharmony_ci { 1744141cc406Sopenharmony_ci buf[j] = (buf[j-1] & 0x01) ? 0xff : 0; 1745141cc406Sopenharmony_ci } 1746141cc406Sopenharmony_ci } 1747141cc406Sopenharmony_ci 1748141cc406Sopenharmony_ci invert_negative_colors (buf, bytes_per_line, scanner); 1749141cc406Sopenharmony_ci 1750141cc406Sopenharmony_ci if (eop_found && (! scanner->eop_last_line_data)) 1751141cc406Sopenharmony_ci { 1752141cc406Sopenharmony_ci DBG (DBG_verbose, "Found end-of-page at line %u in reading block.\n", i); 1753141cc406Sopenharmony_ci scanner->eop_last_line_data = malloc(bytes_per_line); 1754141cc406Sopenharmony_ci if (! scanner->eop_last_line_data) 1755141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1756141cc406Sopenharmony_ci 1757141cc406Sopenharmony_ci memcpy (scanner->eop_last_line_data, buf, bytes_per_line); 1758141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos = 0; 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci /* Fill trailing line buffer with requested color. */ 1761141cc406Sopenharmony_ci if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_RASTER) 1762141cc406Sopenharmony_ci { 1763141cc406Sopenharmony_ci /* Black-white raster. */ 1764141cc406Sopenharmony_ci if (scanner->depth == DEPTH_BW) 1765141cc406Sopenharmony_ci { 1766141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0xaa, bytes_per_line); 1767141cc406Sopenharmony_ci } 1768141cc406Sopenharmony_ci else 1769141cc406Sopenharmony_ci { 1770141cc406Sopenharmony_ci /* Gray. */ 1771141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; ++k) 1772141cc406Sopenharmony_ci { 1773141cc406Sopenharmony_ci scanner->eop_last_line_data[k] = (k & 1 ? 0xff : 0); 1774141cc406Sopenharmony_ci } 1775141cc406Sopenharmony_ci } 1776141cc406Sopenharmony_ci } 1777141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_WHITE) 1778141cc406Sopenharmony_ci { 1779141cc406Sopenharmony_ci /* White. */ 1780141cc406Sopenharmony_ci if (scanner->depth == DEPTH_BW) 1781141cc406Sopenharmony_ci { 1782141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0x00, bytes_per_line); 1783141cc406Sopenharmony_ci } 1784141cc406Sopenharmony_ci else 1785141cc406Sopenharmony_ci { 1786141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0xff, bytes_per_line); 1787141cc406Sopenharmony_ci } 1788141cc406Sopenharmony_ci } 1789141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_BLACK) 1790141cc406Sopenharmony_ci { 1791141cc406Sopenharmony_ci /* Black. */ 1792141cc406Sopenharmony_ci if (scanner->depth == DEPTH_BW) 1793141cc406Sopenharmony_ci { 1794141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0xff, bytes_per_line); 1795141cc406Sopenharmony_ci } 1796141cc406Sopenharmony_ci else 1797141cc406Sopenharmony_ci { 1798141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0x00, bytes_per_line); 1799141cc406Sopenharmony_ci } 1800141cc406Sopenharmony_ci } 1801141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_COLOR) 1802141cc406Sopenharmony_ci { 1803141cc406Sopenharmony_ci if (scanner->depth == DEPTH_BW) 1804141cc406Sopenharmony_ci { 1805141cc406Sopenharmony_ci /* Black or white. */ 1806141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, scanner->eop_trailing_lines_color & 0x01 ? 0x00 : 0xff, bytes_per_line); 1807141cc406Sopenharmony_ci } 1808141cc406Sopenharmony_ci else 1809141cc406Sopenharmony_ci { 1810141cc406Sopenharmony_ci /* Gray value */ 1811141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, scanner->eop_trailing_lines_color & 0xff, bytes_per_line); 1812141cc406Sopenharmony_ci } 1813141cc406Sopenharmony_ci } 1814141cc406Sopenharmony_ci } 1815141cc406Sopenharmony_ci } 1816141cc406Sopenharmony_ci } 1817141cc406Sopenharmony_ci else 1818141cc406Sopenharmony_ci { 1819141cc406Sopenharmony_ci DBG (DBG_verbose, "Trailing lines mode: line=%u, mode=%d, color=%u\n", 1820141cc406Sopenharmony_ci i, scanner->eop_trailing_lines_mode, scanner->eop_trailing_lines_color); 1821141cc406Sopenharmony_ci 1822141cc406Sopenharmony_ci if ((scanner->source == SOURCE_ADF) || (scanner->source == SOURCE_ADF_DUPLEX)) 1823141cc406Sopenharmony_ci { 1824141cc406Sopenharmony_ci /* We are in in ADF mode after last-line and store next page data 1825141cc406Sopenharmony_ci * to buffer. 1826141cc406Sopenharmony_ci */ 1827141cc406Sopenharmony_ci if (! scanner->adf_next_page_lines_data) 1828141cc406Sopenharmony_ci { 1829141cc406Sopenharmony_ci unsigned int n_rest_lines = lines - i; 1830141cc406Sopenharmony_ci unsigned int buf_size = n_rest_lines * bytes_per_line; 1831141cc406Sopenharmony_ci scanner->adf_next_page_lines_data = malloc(buf_size); 1832141cc406Sopenharmony_ci if (! scanner->adf_next_page_lines_data) 1833141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1834141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_size = buf_size; 1835141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos = 0; 1836141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos = 0; 1837141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF between pages: Save n=%u next page lines in buffer.\n", n_rest_lines); 1838141cc406Sopenharmony_ci } 1839141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF between pages: Store line %u of %u.\n", i, lines); 1840141cc406Sopenharmony_ci invert_negative_colors (buf, bytes_per_line, scanner); 1841141cc406Sopenharmony_ci memcpy (scanner->adf_next_page_lines_data + scanner->adf_next_page_lines_data_wpos, buf, bytes_per_line); 1842141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos += bytes_per_line; 1843141cc406Sopenharmony_ci } 1844141cc406Sopenharmony_ci 1845141cc406Sopenharmony_ci if (scanner->eop_trailing_lines_mode != TRAILING_LINES_MODE_RAW) 1846141cc406Sopenharmony_ci { 1847141cc406Sopenharmony_ci /* Copy last line data or corresponding color over trailing lines 1848141cc406Sopenharmony_ci * data. 1849141cc406Sopenharmony_ci */ 1850141cc406Sopenharmony_ci memcpy (buf, scanner->eop_last_line_data, bytes_per_line); 1851141cc406Sopenharmony_ci } 1852141cc406Sopenharmony_ci } 1853141cc406Sopenharmony_ci } 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1856141cc406Sopenharmony_ci} 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci/******************************************************************************/ 1859141cc406Sopenharmony_cistatic unsigned char 1860141cc406Sopenharmony_ciget_checked (unsigned char *ptr, unsigned int i, unsigned int length) 1861141cc406Sopenharmony_ci{ 1862141cc406Sopenharmony_ci if (i < length) 1863141cc406Sopenharmony_ci { 1864141cc406Sopenharmony_ci return ptr[i]; 1865141cc406Sopenharmony_ci } 1866141cc406Sopenharmony_ci DBG (DBG_details, "get from array out of range: idx=%u, size=%u\n", i, length); 1867141cc406Sopenharmony_ci return 0; 1868141cc406Sopenharmony_ci} 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci/******************************************************************************/ 1871141cc406Sopenharmony_cistatic SANE_Status 1872141cc406Sopenharmony_ciconvert_to_rgb (struct hp5590_scanner *scanner, SANE_Byte *data, SANE_Int size) 1873141cc406Sopenharmony_ci{ 1874141cc406Sopenharmony_ci unsigned int pixels_per_line; 1875141cc406Sopenharmony_ci unsigned int pixel_bits; 1876141cc406Sopenharmony_ci unsigned int bytes_per_color; 1877141cc406Sopenharmony_ci unsigned int bytes_per_line; 1878141cc406Sopenharmony_ci unsigned int bytes_per_line_limit; 1879141cc406Sopenharmony_ci unsigned int lines; 1880141cc406Sopenharmony_ci unsigned int i, j; 1881141cc406Sopenharmony_ci unsigned char *buf; 1882141cc406Sopenharmony_ci unsigned char *bufptr; 1883141cc406Sopenharmony_ci unsigned char *ptr; 1884141cc406Sopenharmony_ci SANE_Status ret; 1885141cc406Sopenharmony_ci 1886141cc406Sopenharmony_ci hp5590_assert (scanner != NULL); 1887141cc406Sopenharmony_ci hp5590_assert (data != NULL); 1888141cc406Sopenharmony_ci 1889141cc406Sopenharmony_ci if ( ! (scanner->depth == DEPTH_COLOR_24 || scanner->depth == DEPTH_COLOR_48)) 1890141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 1893141cc406Sopenharmony_ci 1894141cc406Sopenharmony_ci#ifndef HAS_WORKING_COLOR_48 1895141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_48) 1896141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1897141cc406Sopenharmony_ci#endif 1898141cc406Sopenharmony_ci 1899141cc406Sopenharmony_ci ret = calc_image_params (scanner, 1900141cc406Sopenharmony_ci &pixel_bits, 1901141cc406Sopenharmony_ci &pixels_per_line, &bytes_per_line, 1902141cc406Sopenharmony_ci NULL, NULL); 1903141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1904141cc406Sopenharmony_ci return ret; 1905141cc406Sopenharmony_ci 1906141cc406Sopenharmony_ci lines = size / bytes_per_line; 1907141cc406Sopenharmony_ci bytes_per_color = (pixel_bits + 7) / 8; 1908141cc406Sopenharmony_ci 1909141cc406Sopenharmony_ci bytes_per_line_limit = bytes_per_line; 1910141cc406Sopenharmony_ci if ((scanner->depth == DEPTH_COLOR_48) && (bytes_per_line_limit > 3)) 1911141cc406Sopenharmony_ci { 1912141cc406Sopenharmony_ci /* Last-line indicator pixel has only 3 bytes instead of 6. */ 1913141cc406Sopenharmony_ci bytes_per_line_limit -= 3; 1914141cc406Sopenharmony_ci } 1915141cc406Sopenharmony_ci 1916141cc406Sopenharmony_ci DBG (DBG_verbose, "Length : %u\n", size); 1917141cc406Sopenharmony_ci 1918141cc406Sopenharmony_ci DBG (DBG_verbose, "Converting row RGB to normal RGB\n"); 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci DBG (DBG_verbose, "Bytes per line %u\n", bytes_per_line); 1921141cc406Sopenharmony_ci DBG (DBG_verbose, "Bytes per line limited %u\n", bytes_per_line_limit); 1922141cc406Sopenharmony_ci DBG (DBG_verbose, "Bytes per color %u\n", bytes_per_color); 1923141cc406Sopenharmony_ci DBG (DBG_verbose, "Pixels per line %u\n", pixels_per_line); 1924141cc406Sopenharmony_ci DBG (DBG_verbose, "Lines %u\n", lines); 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_ci /* Use working buffer for color mapping. */ 1927141cc406Sopenharmony_ci bufptr = malloc (size); 1928141cc406Sopenharmony_ci if (! bufptr) 1929141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1930141cc406Sopenharmony_ci memset (bufptr, 0, size); 1931141cc406Sopenharmony_ci buf = bufptr; 1932141cc406Sopenharmony_ci 1933141cc406Sopenharmony_ci ptr = data; 1934141cc406Sopenharmony_ci for (j = 0; j < lines; ptr += bytes_per_line_limit, buf += bytes_per_line, j++) 1935141cc406Sopenharmony_ci { 1936141cc406Sopenharmony_ci for (i = 0; i < pixels_per_line; i++) 1937141cc406Sopenharmony_ci { 1938141cc406Sopenharmony_ci /* Color mapping from raw scanner data to RGB buffer. */ 1939141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_24) 1940141cc406Sopenharmony_ci { 1941141cc406Sopenharmony_ci /* R */ 1942141cc406Sopenharmony_ci buf[i*3] = get_checked(ptr, i, bytes_per_line_limit); 1943141cc406Sopenharmony_ci /* G */ 1944141cc406Sopenharmony_ci buf[i*3+1] = get_checked(ptr, i+pixels_per_line, bytes_per_line_limit);; 1945141cc406Sopenharmony_ci /* B */ 1946141cc406Sopenharmony_ci buf[i*3+2] = get_checked(ptr, i+pixels_per_line*2, bytes_per_line_limit); 1947141cc406Sopenharmony_ci } 1948141cc406Sopenharmony_ci else if (scanner->depth == DEPTH_COLOR_48) 1949141cc406Sopenharmony_ci { 1950141cc406Sopenharmony_ci /* Note: The last-line indicator pixel uses only 24 bits, not 48. 1951141cc406Sopenharmony_ci *Blue uses offset of 2 bytes. Green swaps lo and hi. 1952141cc406Sopenharmony_ci */ 1953141cc406Sopenharmony_ci /* R lo, hi*/ 1954141cc406Sopenharmony_ci buf[i*6] = get_checked(ptr, 2*i+(pixels_per_line-1)*0+1, bytes_per_line_limit); 1955141cc406Sopenharmony_ci buf[i*6+1] = get_checked(ptr, 2*i+(pixels_per_line-1)*0+0, bytes_per_line_limit); 1956141cc406Sopenharmony_ci /* G lo, hi*/ 1957141cc406Sopenharmony_ci buf[i*6+2] = get_checked(ptr, 2*i+(pixels_per_line-1)*2+0, bytes_per_line_limit); 1958141cc406Sopenharmony_ci buf[i*6+3] = get_checked(ptr, 2*i+(pixels_per_line-1)*2+1, bytes_per_line_limit); 1959141cc406Sopenharmony_ci /* B lo, hi*/ 1960141cc406Sopenharmony_ci buf[i*6+4] = get_checked(ptr, 2*i+(pixels_per_line-1)*4+1+2, bytes_per_line_limit); 1961141cc406Sopenharmony_ci buf[i*6+5] = get_checked(ptr, 2*i+(pixels_per_line-1)*4+0+2, bytes_per_line_limit); 1962141cc406Sopenharmony_ci } 1963141cc406Sopenharmony_ci } 1964141cc406Sopenharmony_ci 1965141cc406Sopenharmony_ci if (! scanner->eop_last_line_data) 1966141cc406Sopenharmony_ci { 1967141cc406Sopenharmony_ci if (pixels_per_line > 0) 1968141cc406Sopenharmony_ci { 1969141cc406Sopenharmony_ci /* Test for last-line indicator pixel on blue. If found, store 1970141cc406Sopenharmony_ci * last line and optionally overwrite indicator pixel with 1971141cc406Sopenharmony_ci * neighbor value. 1972141cc406Sopenharmony_ci */ 1973141cc406Sopenharmony_ci i = pixels_per_line - 1; 1974141cc406Sopenharmony_ci int eop_found = 0; 1975141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_24) 1976141cc406Sopenharmony_ci { 1977141cc406Sopenharmony_ci /* DBG (DBG_details, "BUF24: %u %u %u\n", buf[i*3], buf[i*3+1], buf[i*3+2]); */ 1978141cc406Sopenharmony_ci eop_found = (buf[i*3+2] != 0); 1979141cc406Sopenharmony_ci if (scanner->overwrite_eop_pixel && (i > 0)) 1980141cc406Sopenharmony_ci { 1981141cc406Sopenharmony_ci buf[i*3] = buf[(i-1)*3]; 1982141cc406Sopenharmony_ci buf[i*3+1] = buf[(i-1)*3+1]; 1983141cc406Sopenharmony_ci buf[i*3+2] = buf[(i-1)*3+2]; 1984141cc406Sopenharmony_ci } 1985141cc406Sopenharmony_ci } 1986141cc406Sopenharmony_ci else if (scanner->depth == DEPTH_COLOR_48) 1987141cc406Sopenharmony_ci { 1988141cc406Sopenharmony_ci /* DBG (DBG_details, "BUF48: %u %u %u\n", buf[i*6+1], buf[i*6+3], buf[i*6+5]); */ 1989141cc406Sopenharmony_ci eop_found = (buf[i*6+5] != 0); 1990141cc406Sopenharmony_ci if (scanner->overwrite_eop_pixel && (i > 0)) 1991141cc406Sopenharmony_ci { 1992141cc406Sopenharmony_ci buf[i*6] = buf[(i-1)*6]; 1993141cc406Sopenharmony_ci buf[i*6+1] = buf[(i-1)*6+1]; 1994141cc406Sopenharmony_ci buf[i*6+2] = buf[(i-1)*6+2]; 1995141cc406Sopenharmony_ci buf[i*6+3] = buf[(i-1)*6+3]; 1996141cc406Sopenharmony_ci buf[i*6+4] = buf[(i-1)*6+4]; 1997141cc406Sopenharmony_ci buf[i*6+5] = buf[(i-1)*6+5]; 1998141cc406Sopenharmony_ci } 1999141cc406Sopenharmony_ci } 2000141cc406Sopenharmony_ci 2001141cc406Sopenharmony_ci invert_negative_colors (buf, bytes_per_line, scanner); 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci if (eop_found && (! scanner->eop_last_line_data)) 2004141cc406Sopenharmony_ci { 2005141cc406Sopenharmony_ci DBG (DBG_verbose, "Found end-of-page at line %u in reading block.\n", j); 2006141cc406Sopenharmony_ci scanner->eop_last_line_data = malloc(bytes_per_line); 2007141cc406Sopenharmony_ci if (! scanner->eop_last_line_data) 2008141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci memcpy (scanner->eop_last_line_data, buf, bytes_per_line); 2011141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos = 0; 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci /* Fill trailing line buffer with requested color. */ 2014141cc406Sopenharmony_ci if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_RASTER) 2015141cc406Sopenharmony_ci { 2016141cc406Sopenharmony_ci /* Black-white raster. */ 2017141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_24) 2018141cc406Sopenharmony_ci { 2019141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; ++k) 2020141cc406Sopenharmony_ci { 2021141cc406Sopenharmony_ci scanner->eop_last_line_data[k] = (k % 6 < 3 ? 0xff : 0); 2022141cc406Sopenharmony_ci } 2023141cc406Sopenharmony_ci } 2024141cc406Sopenharmony_ci else 2025141cc406Sopenharmony_ci { 2026141cc406Sopenharmony_ci /* Color48. */ 2027141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; ++k) 2028141cc406Sopenharmony_ci { 2029141cc406Sopenharmony_ci scanner->eop_last_line_data[k] = (k % 12 < 6 ? 0xff : 0); 2030141cc406Sopenharmony_ci } 2031141cc406Sopenharmony_ci } 2032141cc406Sopenharmony_ci } 2033141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_WHITE) 2034141cc406Sopenharmony_ci { 2035141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0xff, bytes_per_line); 2036141cc406Sopenharmony_ci } 2037141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_BLACK) 2038141cc406Sopenharmony_ci { 2039141cc406Sopenharmony_ci memset (scanner->eop_last_line_data, 0x00, bytes_per_line); 2040141cc406Sopenharmony_ci } 2041141cc406Sopenharmony_ci else if (scanner->eop_trailing_lines_mode == TRAILING_LINES_MODE_COLOR) 2042141cc406Sopenharmony_ci { 2043141cc406Sopenharmony_ci /* RGB color value. */ 2044141cc406Sopenharmony_ci int rgb[3]; 2045141cc406Sopenharmony_ci rgb[0] = (scanner->eop_trailing_lines_color >> 16) & 0xff; 2046141cc406Sopenharmony_ci rgb[1] = (scanner->eop_trailing_lines_color >> 8) & 0xff; 2047141cc406Sopenharmony_ci rgb[2] = scanner->eop_trailing_lines_color & 0xff; 2048141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_24) 2049141cc406Sopenharmony_ci { 2050141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; ++k) 2051141cc406Sopenharmony_ci { 2052141cc406Sopenharmony_ci scanner->eop_last_line_data[k] = rgb[k % 3]; 2053141cc406Sopenharmony_ci } 2054141cc406Sopenharmony_ci } 2055141cc406Sopenharmony_ci else 2056141cc406Sopenharmony_ci { 2057141cc406Sopenharmony_ci /* Color48. */ 2058141cc406Sopenharmony_ci for (unsigned int k = 0; k < bytes_per_line; ++k) 2059141cc406Sopenharmony_ci { 2060141cc406Sopenharmony_ci scanner->eop_last_line_data[k] = rgb[(k % 6) >> 1]; 2061141cc406Sopenharmony_ci } 2062141cc406Sopenharmony_ci } 2063141cc406Sopenharmony_ci } 2064141cc406Sopenharmony_ci } 2065141cc406Sopenharmony_ci } 2066141cc406Sopenharmony_ci } 2067141cc406Sopenharmony_ci else 2068141cc406Sopenharmony_ci { 2069141cc406Sopenharmony_ci DBG (DBG_verbose, "Trailing lines mode: line=%u, mode=%d, color=%u\n", 2070141cc406Sopenharmony_ci j, scanner->eop_trailing_lines_mode, scanner->eop_trailing_lines_color); 2071141cc406Sopenharmony_ci 2072141cc406Sopenharmony_ci if ((scanner->source == SOURCE_ADF) || (scanner->source == SOURCE_ADF_DUPLEX)) 2073141cc406Sopenharmony_ci { 2074141cc406Sopenharmony_ci /* We are in in ADF mode after last-line and store next page data 2075141cc406Sopenharmony_ci * to buffer. 2076141cc406Sopenharmony_ci */ 2077141cc406Sopenharmony_ci if (! scanner->adf_next_page_lines_data) 2078141cc406Sopenharmony_ci { 2079141cc406Sopenharmony_ci unsigned int n_rest_lines = lines - j; 2080141cc406Sopenharmony_ci unsigned int buf_size = n_rest_lines * bytes_per_line; 2081141cc406Sopenharmony_ci scanner->adf_next_page_lines_data = malloc(buf_size); 2082141cc406Sopenharmony_ci if (! scanner->adf_next_page_lines_data) 2083141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2084141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_size = buf_size; 2085141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos = 0; 2086141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos = 0; 2087141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF between pages: Save n=%u next page lines in buffer.\n", n_rest_lines); 2088141cc406Sopenharmony_ci } 2089141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF between pages: Store line %u of %u.\n", j, lines); 2090141cc406Sopenharmony_ci invert_negative_colors (buf, bytes_per_line, scanner); 2091141cc406Sopenharmony_ci memcpy (scanner->adf_next_page_lines_data + scanner->adf_next_page_lines_data_wpos, buf, bytes_per_line); 2092141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos += bytes_per_line; 2093141cc406Sopenharmony_ci } 2094141cc406Sopenharmony_ci 2095141cc406Sopenharmony_ci if (scanner->eop_trailing_lines_mode != TRAILING_LINES_MODE_RAW) 2096141cc406Sopenharmony_ci { 2097141cc406Sopenharmony_ci /* Copy last line data or corresponding color over trailing lines 2098141cc406Sopenharmony_ci * data. 2099141cc406Sopenharmony_ci */ 2100141cc406Sopenharmony_ci memcpy (buf, scanner->eop_last_line_data, bytes_per_line); 2101141cc406Sopenharmony_ci } 2102141cc406Sopenharmony_ci } 2103141cc406Sopenharmony_ci } 2104141cc406Sopenharmony_ci memcpy (data, bufptr, size); 2105141cc406Sopenharmony_ci free (bufptr); 2106141cc406Sopenharmony_ci 2107141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2108141cc406Sopenharmony_ci} 2109141cc406Sopenharmony_ci 2110141cc406Sopenharmony_ci/******************************************************************************/ 2111141cc406Sopenharmony_cistatic void 2112141cc406Sopenharmony_ciread_data_from_temporary_buffer(struct hp5590_scanner *scanner, 2113141cc406Sopenharmony_ci SANE_Byte * data, unsigned int max_length, 2114141cc406Sopenharmony_ci unsigned int bytes_per_line, SANE_Int *length) 2115141cc406Sopenharmony_ci{ 2116141cc406Sopenharmony_ci *length = 0; 2117141cc406Sopenharmony_ci if (scanner && scanner->one_line_read_buffer) 2118141cc406Sopenharmony_ci { 2119141cc406Sopenharmony_ci /* Copy scan data from temporary read buffer and return size copied data. */ 2120141cc406Sopenharmony_ci /* Release buffer, when no data left. */ 2121141cc406Sopenharmony_ci unsigned int rest_len; 2122141cc406Sopenharmony_ci rest_len = bytes_per_line - scanner->one_line_read_buffer_rpos; 2123141cc406Sopenharmony_ci rest_len = (rest_len < max_length) ? rest_len : max_length; 2124141cc406Sopenharmony_ci if (rest_len > 0) 2125141cc406Sopenharmony_ci { 2126141cc406Sopenharmony_ci memcpy (data, scanner->one_line_read_buffer + scanner->one_line_read_buffer_rpos, rest_len); 2127141cc406Sopenharmony_ci scanner->one_line_read_buffer_rpos += rest_len; 2128141cc406Sopenharmony_ci scanner->transferred_image_size -= rest_len; 2129141cc406Sopenharmony_ci *length = rest_len; 2130141cc406Sopenharmony_ci } 2131141cc406Sopenharmony_ci 2132141cc406Sopenharmony_ci DBG (DBG_verbose, "Copy scan data from temporary buffer: length = %u, rest in buffer = %u.\n", 2133141cc406Sopenharmony_ci *length, bytes_per_line - scanner->one_line_read_buffer_rpos); 2134141cc406Sopenharmony_ci 2135141cc406Sopenharmony_ci if (scanner->one_line_read_buffer_rpos >= bytes_per_line) 2136141cc406Sopenharmony_ci { 2137141cc406Sopenharmony_ci DBG (DBG_verbose, "Release temporary buffer.\n"); 2138141cc406Sopenharmony_ci free (scanner->one_line_read_buffer); 2139141cc406Sopenharmony_ci scanner->one_line_read_buffer = NULL; 2140141cc406Sopenharmony_ci scanner->one_line_read_buffer_rpos = 0; 2141141cc406Sopenharmony_ci } 2142141cc406Sopenharmony_ci } 2143141cc406Sopenharmony_ci} 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci/******************************************************************************/ 2146141cc406Sopenharmony_cistatic SANE_Status 2147141cc406Sopenharmony_cisane_read_internal (struct hp5590_scanner * scanner, SANE_Byte * data, 2148141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length, unsigned int bytes_per_line) 2149141cc406Sopenharmony_ci{ 2150141cc406Sopenharmony_ci SANE_Status ret; 2151141cc406Sopenharmony_ci 2152141cc406Sopenharmony_ci DBG (DBG_proc, "%s, length %u, left %llu\n", 2153141cc406Sopenharmony_ci __func__, 2154141cc406Sopenharmony_ci max_length, 2155141cc406Sopenharmony_ci scanner->transferred_image_size); 2156141cc406Sopenharmony_ci 2157141cc406Sopenharmony_ci SANE_Int length_limited = 0; 2158141cc406Sopenharmony_ci *length = max_length; 2159141cc406Sopenharmony_ci if ((unsigned long long) *length > scanner->transferred_image_size) 2160141cc406Sopenharmony_ci *length = (SANE_Int) scanner->transferred_image_size; 2161141cc406Sopenharmony_ci 2162141cc406Sopenharmony_ci /* Align reading size to bytes per line. */ 2163141cc406Sopenharmony_ci *length -= *length % bytes_per_line; 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_48) 2166141cc406Sopenharmony_ci { 2167141cc406Sopenharmony_ci /* Note: The last-line indicator pixel uses only 24 bits (3 bytes), not 2168141cc406Sopenharmony_ci * 48 bits (6 bytes). 2169141cc406Sopenharmony_ci */ 2170141cc406Sopenharmony_ci if (bytes_per_line > 3) 2171141cc406Sopenharmony_ci { 2172141cc406Sopenharmony_ci length_limited = *length - *length % (bytes_per_line - 3); 2173141cc406Sopenharmony_ci } 2174141cc406Sopenharmony_ci } 2175141cc406Sopenharmony_ci 2176141cc406Sopenharmony_ci DBG (DBG_verbose, "Aligning requested size to bytes per line " 2177141cc406Sopenharmony_ci "(requested: %d, aligned: %u, limit_for_48bit: %u)\n", 2178141cc406Sopenharmony_ci max_length, *length, length_limited); 2179141cc406Sopenharmony_ci 2180141cc406Sopenharmony_ci if (max_length <= 0) 2181141cc406Sopenharmony_ci { 2182141cc406Sopenharmony_ci DBG (DBG_verbose, "Buffer too small for one scan line. Need at least %u bytes per line.\n", 2183141cc406Sopenharmony_ci bytes_per_line); 2184141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2185141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2186141cc406Sopenharmony_ci } 2187141cc406Sopenharmony_ci 2188141cc406Sopenharmony_ci if (scanner->one_line_read_buffer) 2189141cc406Sopenharmony_ci { 2190141cc406Sopenharmony_ci /* Copy scan data from temporary read buffer. */ 2191141cc406Sopenharmony_ci read_data_from_temporary_buffer (scanner, data, max_length, bytes_per_line, length); 2192141cc406Sopenharmony_ci if (*length > 0) 2193141cc406Sopenharmony_ci { 2194141cc406Sopenharmony_ci DBG (DBG_verbose, "Return %d bytes, left %llu bytes.\n", *length, scanner->transferred_image_size); 2195141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2196141cc406Sopenharmony_ci } 2197141cc406Sopenharmony_ci } 2198141cc406Sopenharmony_ci 2199141cc406Sopenharmony_ci /* Buffer to return scanned data. We need at least space for one line to 2200141cc406Sopenharmony_ci * simplify color processing and last-line detection. If call buffer is too 2201141cc406Sopenharmony_ci * small, use temporary read buffer for reading one line instead. 2202141cc406Sopenharmony_ci */ 2203141cc406Sopenharmony_ci SANE_Byte * scan_data; 2204141cc406Sopenharmony_ci SANE_Int scan_data_length; 2205141cc406Sopenharmony_ci scan_data = data; 2206141cc406Sopenharmony_ci scan_data_length = *length; 2207141cc406Sopenharmony_ci 2208141cc406Sopenharmony_ci /* Note, read length is shorter in 48bit mode. */ 2209141cc406Sopenharmony_ci SANE_Int length_for_read = length_limited ? length_limited : scan_data_length; 2210141cc406Sopenharmony_ci if (length_for_read == 0) 2211141cc406Sopenharmony_ci { 2212141cc406Sopenharmony_ci /* Call buffer is too small for one line. Use temporary read buffer 2213141cc406Sopenharmony_ci * instead. 2214141cc406Sopenharmony_ci */ 2215141cc406Sopenharmony_ci if (! scanner->one_line_read_buffer) 2216141cc406Sopenharmony_ci { 2217141cc406Sopenharmony_ci scanner->one_line_read_buffer = malloc (bytes_per_line); 2218141cc406Sopenharmony_ci if (! scanner->one_line_read_buffer) 2219141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2220141cc406Sopenharmony_ci memset (scanner->one_line_read_buffer, 0, bytes_per_line); 2221141cc406Sopenharmony_ci } 2222141cc406Sopenharmony_ci 2223141cc406Sopenharmony_ci DBG (DBG_verbose, "Call buffer too small for one scan line. Use temporary read buffer for one line with %u bytes.\n", 2224141cc406Sopenharmony_ci bytes_per_line); 2225141cc406Sopenharmony_ci 2226141cc406Sopenharmony_ci /* Scan and process next line in temporary buffer. */ 2227141cc406Sopenharmony_ci scan_data = scanner->one_line_read_buffer; 2228141cc406Sopenharmony_ci scan_data_length = bytes_per_line; 2229141cc406Sopenharmony_ci length_for_read = bytes_per_line; 2230141cc406Sopenharmony_ci if (scanner->depth == DEPTH_COLOR_48) 2231141cc406Sopenharmony_ci { 2232141cc406Sopenharmony_ci /* The last-line indicator pixel uses only 24 bits (3 bytes), not 48 2233141cc406Sopenharmony_ci * bits (6 bytes). 2234141cc406Sopenharmony_ci */ 2235141cc406Sopenharmony_ci if (length_for_read > 3) 2236141cc406Sopenharmony_ci { 2237141cc406Sopenharmony_ci length_for_read -= 3; 2238141cc406Sopenharmony_ci } 2239141cc406Sopenharmony_ci } 2240141cc406Sopenharmony_ci } 2241141cc406Sopenharmony_ci 2242141cc406Sopenharmony_ci int read_from_scanner = 1; 2243141cc406Sopenharmony_ci if ((scanner->source == SOURCE_ADF) || (scanner->source == SOURCE_ADF_DUPLEX)) 2244141cc406Sopenharmony_ci { 2245141cc406Sopenharmony_ci if (scanner->eop_last_line_data) 2246141cc406Sopenharmony_ci { 2247141cc406Sopenharmony_ci /* Scanner is in ADF mode between last-line of previous page and 2248141cc406Sopenharmony_ci * start of next page. 2249141cc406Sopenharmony_ci * Fill remaining lines with last-line data. 2250141cc406Sopenharmony_ci */ 2251141cc406Sopenharmony_ci unsigned int wpos = 0; 2252141cc406Sopenharmony_ci while (wpos < (unsigned int) scan_data_length) 2253141cc406Sopenharmony_ci { 2254141cc406Sopenharmony_ci unsigned int n1 = scan_data_length - wpos; 2255141cc406Sopenharmony_ci unsigned int n2 = bytes_per_line - scanner->eop_last_line_data_rpos; 2256141cc406Sopenharmony_ci n1 = (n1 < n2) ? n1 : n2; 2257141cc406Sopenharmony_ci memcpy (scan_data + wpos, scanner->eop_last_line_data + scanner->eop_last_line_data_rpos, n1); 2258141cc406Sopenharmony_ci wpos += n1; 2259141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos += n1; 2260141cc406Sopenharmony_ci if (scanner->eop_last_line_data_rpos >= bytes_per_line) 2261141cc406Sopenharmony_ci scanner->eop_last_line_data_rpos = 0; 2262141cc406Sopenharmony_ci } 2263141cc406Sopenharmony_ci read_from_scanner = (wpos == 0); 2264141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF use last-line data, wlength=%u, length=%u\n", wpos, scan_data_length); 2265141cc406Sopenharmony_ci } 2266141cc406Sopenharmony_ci else if (scanner->adf_next_page_lines_data) 2267141cc406Sopenharmony_ci { 2268141cc406Sopenharmony_ci /* Scanner is in ADF mode at start of next page and already some next 2269141cc406Sopenharmony_ci * page data is available from earlier read operation. Return this 2270141cc406Sopenharmony_ci * data. 2271141cc406Sopenharmony_ci */ 2272141cc406Sopenharmony_ci unsigned int wpos = 0; 2273141cc406Sopenharmony_ci while ((wpos < (unsigned int) scan_data_length) && 2274141cc406Sopenharmony_ci (scanner->adf_next_page_lines_data_rpos < scanner->adf_next_page_lines_data_size)) 2275141cc406Sopenharmony_ci { 2276141cc406Sopenharmony_ci unsigned int n1 = scan_data_length - wpos; 2277141cc406Sopenharmony_ci unsigned int n2 = scanner->adf_next_page_lines_data_size - scanner->adf_next_page_lines_data_rpos; 2278141cc406Sopenharmony_ci n1 = (n1 < n2) ? n1 : n2; 2279141cc406Sopenharmony_ci memcpy (scan_data + wpos, scanner->adf_next_page_lines_data + scanner->adf_next_page_lines_data_rpos, n1); 2280141cc406Sopenharmony_ci wpos += n1; 2281141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos += n1; 2282141cc406Sopenharmony_ci if (scanner->adf_next_page_lines_data_rpos >= scanner->adf_next_page_lines_data_size) 2283141cc406Sopenharmony_ci { 2284141cc406Sopenharmony_ci free (scanner->adf_next_page_lines_data); 2285141cc406Sopenharmony_ci scanner->adf_next_page_lines_data = NULL; 2286141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_size = 0; 2287141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_rpos = 0; 2288141cc406Sopenharmony_ci scanner->adf_next_page_lines_data_wpos = 0; 2289141cc406Sopenharmony_ci } 2290141cc406Sopenharmony_ci } 2291141cc406Sopenharmony_ci scan_data_length = wpos; 2292141cc406Sopenharmony_ci read_from_scanner = (wpos == 0); 2293141cc406Sopenharmony_ci DBG (DBG_verbose, "ADF use next-page data, wlength=%u, length=%u\n", wpos, scan_data_length); 2294141cc406Sopenharmony_ci } 2295141cc406Sopenharmony_ci } 2296141cc406Sopenharmony_ci 2297141cc406Sopenharmony_ci if (read_from_scanner) 2298141cc406Sopenharmony_ci { 2299141cc406Sopenharmony_ci /* Read data from scanner. */ 2300141cc406Sopenharmony_ci ret = hp5590_read (scanner->dn, scanner->proto_flags, 2301141cc406Sopenharmony_ci scan_data, length_for_read, 2302141cc406Sopenharmony_ci scanner->bulk_read_state); 2303141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2304141cc406Sopenharmony_ci { 2305141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2306141cc406Sopenharmony_ci return ret; 2307141cc406Sopenharmony_ci } 2308141cc406Sopenharmony_ci 2309141cc406Sopenharmony_ci /* Look for last-line indicator pixels in convert functions. 2310141cc406Sopenharmony_ci * If found: 2311141cc406Sopenharmony_ci * - Overwrite indicator pixel with neighboring color (optional). 2312141cc406Sopenharmony_ci * - Save last line data for later use. 2313141cc406Sopenharmony_ci */ 2314141cc406Sopenharmony_ci ret = convert_to_rgb (scanner, scan_data, scan_data_length); 2315141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2316141cc406Sopenharmony_ci { 2317141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2318141cc406Sopenharmony_ci return ret; 2319141cc406Sopenharmony_ci } 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci ret = convert_gray_and_lineart (scanner, scan_data, scan_data_length); 2322141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2323141cc406Sopenharmony_ci return ret; 2324141cc406Sopenharmony_ci } 2325141cc406Sopenharmony_ci 2326141cc406Sopenharmony_ci if (data == scan_data) 2327141cc406Sopenharmony_ci { 2328141cc406Sopenharmony_ci /* Scanned to call buffer. */ 2329141cc406Sopenharmony_ci scanner->transferred_image_size -= scan_data_length; 2330141cc406Sopenharmony_ci *length = scan_data_length; 2331141cc406Sopenharmony_ci } 2332141cc406Sopenharmony_ci else 2333141cc406Sopenharmony_ci { 2334141cc406Sopenharmony_ci /* Scanned to temporary read buffer. */ 2335141cc406Sopenharmony_ci if (scanner->one_line_read_buffer) 2336141cc406Sopenharmony_ci { 2337141cc406Sopenharmony_ci /* Copy scan data from temporary read buffer. */ 2338141cc406Sopenharmony_ci read_data_from_temporary_buffer (scanner, data, max_length, scan_data_length, length); 2339141cc406Sopenharmony_ci } 2340141cc406Sopenharmony_ci else 2341141cc406Sopenharmony_ci { 2342141cc406Sopenharmony_ci *length = 0; 2343141cc406Sopenharmony_ci } 2344141cc406Sopenharmony_ci } 2345141cc406Sopenharmony_ci 2346141cc406Sopenharmony_ci DBG (DBG_verbose, "Return %d bytes, left %llu bytes\n", *length, scanner->transferred_image_size); 2347141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2348141cc406Sopenharmony_ci} 2349141cc406Sopenharmony_ci 2350141cc406Sopenharmony_ci/****************************************************************************** 2351141cc406Sopenharmony_ci * Copy at maximum the last n lines from the src buffer to the begin of the dst 2352141cc406Sopenharmony_ci * buffer. 2353141cc406Sopenharmony_ci * Return number of lines copied. 2354141cc406Sopenharmony_ci */ 2355141cc406Sopenharmony_cistatic SANE_Int 2356141cc406Sopenharmony_cicopy_n_last_lines(SANE_Byte * src, SANE_Int src_len, SANE_Byte * dst, SANE_Int n, unsigned int bytes_per_line) 2357141cc406Sopenharmony_ci{ 2358141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2359141cc406Sopenharmony_ci SANE_Int n_copy = MY_MIN(src_len, n); 2360141cc406Sopenharmony_ci SANE_Byte * src1 = src + (src_len - n_copy) * bytes_per_line; 2361141cc406Sopenharmony_ci memcpy (dst, src1, n_copy * bytes_per_line); 2362141cc406Sopenharmony_ci return n_copy; 2363141cc406Sopenharmony_ci} 2364141cc406Sopenharmony_ci 2365141cc406Sopenharmony_ci/****************************************************************************** 2366141cc406Sopenharmony_ci * Copy the color values from line - delta_lines to line. 2367141cc406Sopenharmony_ci * buffer2 : Source and target buffer. 2368141cc406Sopenharmony_ci * buffer1 : Only source buffer. Contains lines scanned before lines in buffer1. 2369141cc406Sopenharmony_ci * color_idx : Index of color to be copied (0..2). 2370141cc406Sopenharmony_ci * delta_lines : color shift. 2371141cc406Sopenharmony_ci * color_48 : True = 2 byte , false = 1 byte per color. 2372141cc406Sopenharmony_ci */ 2373141cc406Sopenharmony_cistatic void 2374141cc406Sopenharmony_cishift_color_lines(SANE_Byte * buffer2, SANE_Int n_lines2, SANE_Byte * buffer1, SANE_Int n_lines1, SANE_Int color_idx, SANE_Int delta_lines, SANE_Bool color_48, unsigned int bytes_per_line) 2375141cc406Sopenharmony_ci{ 2376141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2377141cc406Sopenharmony_ci for (SANE_Int i = n_lines2 - 1; i >= 0; --i) { 2378141cc406Sopenharmony_ci SANE_Byte * dst = buffer2 + i * bytes_per_line; 2379141cc406Sopenharmony_ci SANE_Int ii = i - delta_lines; 2380141cc406Sopenharmony_ci SANE_Byte * src = NULL; 2381141cc406Sopenharmony_ci SANE_Int source_color_idx = color_idx; 2382141cc406Sopenharmony_ci if (ii >= 0) { 2383141cc406Sopenharmony_ci /* Read from source and target buffer. */ 2384141cc406Sopenharmony_ci src = buffer2 + ii * bytes_per_line; 2385141cc406Sopenharmony_ci } else { 2386141cc406Sopenharmony_ci ii += n_lines1; 2387141cc406Sopenharmony_ci if (ii >= 0) { 2388141cc406Sopenharmony_ci /* Read from source only buffer. */ 2389141cc406Sopenharmony_ci src = buffer1 + ii * bytes_per_line; 2390141cc406Sopenharmony_ci } else { 2391141cc406Sopenharmony_ci /* Read other color from source position. */ 2392141cc406Sopenharmony_ci src = dst; 2393141cc406Sopenharmony_ci source_color_idx = 2; 2394141cc406Sopenharmony_ci } 2395141cc406Sopenharmony_ci } 2396141cc406Sopenharmony_ci /* Copy selected color values. */ 2397141cc406Sopenharmony_ci SANE_Int step = color_48 ? 2 : 1; 2398141cc406Sopenharmony_ci SANE_Int stride = 3 * step; 2399141cc406Sopenharmony_ci for (unsigned int pos = 0; pos < bytes_per_line; pos += stride) { 2400141cc406Sopenharmony_ci SANE_Int p1 = pos + step * source_color_idx; 2401141cc406Sopenharmony_ci SANE_Int p2 = pos + step * color_idx; 2402141cc406Sopenharmony_ci dst[p2] = src[p1]; 2403141cc406Sopenharmony_ci if (color_48) { 2404141cc406Sopenharmony_ci dst[p2 + 1] = src[p1 + 1]; 2405141cc406Sopenharmony_ci } 2406141cc406Sopenharmony_ci } 2407141cc406Sopenharmony_ci } 2408141cc406Sopenharmony_ci} 2409141cc406Sopenharmony_ci 2410141cc406Sopenharmony_ci/****************************************************************************** 2411141cc406Sopenharmony_ci * Append all lines from buffer2 to the end of buffer1 and keep max_lines last 2412141cc406Sopenharmony_ci * lines. 2413141cc406Sopenharmony_ci * buffer2 : Source line buffer. 2414141cc406Sopenharmony_ci * buffer1 : Target line buffer. Length will be adjusted. 2415141cc406Sopenharmony_ci * max_lines : Max number of lines in buffer1. 2416141cc406Sopenharmony_ci */ 2417141cc406Sopenharmony_cistatic void 2418141cc406Sopenharmony_ciappend_and_move_lines(SANE_Byte * buffer2, SANE_Int n_lines2, SANE_Byte * buffer1, unsigned int * n_lines1_ptr, SANE_Int max_lines, unsigned int bytes_per_line) 2419141cc406Sopenharmony_ci{ 2420141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2421141cc406Sopenharmony_ci SANE_Int rest1 = max_lines - *n_lines1_ptr; 2422141cc406Sopenharmony_ci SANE_Int copy2 = MY_MIN(n_lines2, max_lines); 2423141cc406Sopenharmony_ci if (copy2 > rest1) { 2424141cc406Sopenharmony_ci SANE_Int shift1 = *n_lines1_ptr + copy2 - max_lines; 2425141cc406Sopenharmony_ci SANE_Int blen = MY_MIN(max_lines - shift1, (SANE_Int) *n_lines1_ptr); 2426141cc406Sopenharmony_ci SANE_Byte * pdst = buffer1; 2427141cc406Sopenharmony_ci SANE_Byte * psrc = pdst + shift1 * bytes_per_line; 2428141cc406Sopenharmony_ci for (SANE_Int i = 0; i < blen; ++i) { 2429141cc406Sopenharmony_ci memcpy (pdst, psrc, bytes_per_line); 2430141cc406Sopenharmony_ci pdst += bytes_per_line; 2431141cc406Sopenharmony_ci psrc += bytes_per_line; 2432141cc406Sopenharmony_ci } 2433141cc406Sopenharmony_ci *n_lines1_ptr -= shift1; 2434141cc406Sopenharmony_ci } 2435141cc406Sopenharmony_ci SANE_Int n_copied = copy_n_last_lines(buffer2, n_lines2, buffer1 + *n_lines1_ptr * bytes_per_line, copy2, bytes_per_line); 2436141cc406Sopenharmony_ci *n_lines1_ptr += n_copied; 2437141cc406Sopenharmony_ci} 2438141cc406Sopenharmony_ci 2439141cc406Sopenharmony_ci 2440141cc406Sopenharmony_ci/******************************************************************************/ 2441141cc406Sopenharmony_ciSANE_Status 2442141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data, 2443141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 2444141cc406Sopenharmony_ci{ 2445141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 2446141cc406Sopenharmony_ci SANE_Status ret; 2447141cc406Sopenharmony_ci 2448141cc406Sopenharmony_ci DBG (DBG_proc, "%s, length %u, left %llu\n", 2449141cc406Sopenharmony_ci __func__, 2450141cc406Sopenharmony_ci max_length, 2451141cc406Sopenharmony_ci scanner->transferred_image_size); 2452141cc406Sopenharmony_ci 2453141cc406Sopenharmony_ci if (!length) 2454141cc406Sopenharmony_ci { 2455141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2456141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2457141cc406Sopenharmony_ci } 2458141cc406Sopenharmony_ci 2459141cc406Sopenharmony_ci if (scanner->transferred_image_size == 0) 2460141cc406Sopenharmony_ci { 2461141cc406Sopenharmony_ci *length = 0; 2462141cc406Sopenharmony_ci DBG (DBG_verbose, "Setting scan count\n"); 2463141cc406Sopenharmony_ci 2464141cc406Sopenharmony_ci ret = hp5590_inc_scan_count (scanner->dn, scanner->proto_flags); 2465141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2466141cc406Sopenharmony_ci return ret; 2467141cc406Sopenharmony_ci 2468141cc406Sopenharmony_ci /* Don't free bulk read state, some bytes could be left 2469141cc406Sopenharmony_ci * for the next images from ADF 2470141cc406Sopenharmony_ci */ 2471141cc406Sopenharmony_ci return SANE_STATUS_EOF; 2472141cc406Sopenharmony_ci } 2473141cc406Sopenharmony_ci 2474141cc406Sopenharmony_ci if (!scanner->bulk_read_state) 2475141cc406Sopenharmony_ci { 2476141cc406Sopenharmony_ci ret = hp5590_low_init_bulk_read_state (&scanner->bulk_read_state); 2477141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2478141cc406Sopenharmony_ci { 2479141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2480141cc406Sopenharmony_ci return ret; 2481141cc406Sopenharmony_ci } 2482141cc406Sopenharmony_ci } 2483141cc406Sopenharmony_ci 2484141cc406Sopenharmony_ci unsigned int bytes_per_line; 2485141cc406Sopenharmony_ci ret = calc_image_params (scanner, 2486141cc406Sopenharmony_ci NULL, NULL, 2487141cc406Sopenharmony_ci &bytes_per_line, 2488141cc406Sopenharmony_ci NULL, NULL); 2489141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2490141cc406Sopenharmony_ci return ret; 2491141cc406Sopenharmony_ci 2492141cc406Sopenharmony_ci ret = sane_read_internal(scanner, data, max_length, length, bytes_per_line); 2493141cc406Sopenharmony_ci 2494141cc406Sopenharmony_ci if ((ret == SANE_STATUS_GOOD) && (scanner->dpi == 2400) && 2495141cc406Sopenharmony_ci ((scanner->depth == DEPTH_COLOR_48) || (scanner->depth == DEPTH_COLOR_24))) 2496141cc406Sopenharmony_ci { 2497141cc406Sopenharmony_ci /* Correct color shift bug for 2400 dpi. 2498141cc406Sopenharmony_ci * Note: 2400 dpi only works in color mode. Grey mode and lineart seem to 2499141cc406Sopenharmony_ci * fail. 2500141cc406Sopenharmony_ci * Align colors by shifting B channel by 48 lines and G channel by 24 2501141cc406Sopenharmony_ci * lines. 2502141cc406Sopenharmony_ci */ 2503141cc406Sopenharmony_ci const SANE_Int offset_max = 48; 2504141cc406Sopenharmony_ci const SANE_Int offset_part = 24; 2505141cc406Sopenharmony_ci SANE_Bool color_48 = (scanner->depth == DEPTH_COLOR_48); 2506141cc406Sopenharmony_ci 2507141cc406Sopenharmony_ci if (! scanner->color_shift_line_buffer1) 2508141cc406Sopenharmony_ci { 2509141cc406Sopenharmony_ci scanner->color_shift_buffered_lines1 = 0; 2510141cc406Sopenharmony_ci scanner->color_shift_line_buffer1 = malloc (bytes_per_line * offset_max); 2511141cc406Sopenharmony_ci if (! scanner->color_shift_line_buffer1) 2512141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2513141cc406Sopenharmony_ci memset (scanner->color_shift_line_buffer1, 0, bytes_per_line * offset_max); 2514141cc406Sopenharmony_ci } 2515141cc406Sopenharmony_ci if (! scanner->color_shift_line_buffer2) 2516141cc406Sopenharmony_ci { 2517141cc406Sopenharmony_ci scanner->color_shift_buffered_lines2 = 0; 2518141cc406Sopenharmony_ci scanner->color_shift_line_buffer2 = malloc (bytes_per_line * offset_max); 2519141cc406Sopenharmony_ci if (! scanner->color_shift_line_buffer2) 2520141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2521141cc406Sopenharmony_ci memset (scanner->color_shift_line_buffer2, 0, bytes_per_line * offset_max); 2522141cc406Sopenharmony_ci } 2523141cc406Sopenharmony_ci 2524141cc406Sopenharmony_ci SANE_Int n_lines = *length / bytes_per_line; 2525141cc406Sopenharmony_ci scanner->color_shift_buffered_lines2 = MY_MIN(n_lines, offset_max); 2526141cc406Sopenharmony_ci copy_n_last_lines(data, n_lines, scanner->color_shift_line_buffer2, scanner->color_shift_buffered_lines2, bytes_per_line); 2527141cc406Sopenharmony_ci 2528141cc406Sopenharmony_ci shift_color_lines(data, n_lines, scanner->color_shift_line_buffer1, scanner->color_shift_buffered_lines1, 1, offset_part, color_48, bytes_per_line); 2529141cc406Sopenharmony_ci shift_color_lines(data, n_lines, scanner->color_shift_line_buffer1, scanner->color_shift_buffered_lines1, 0, offset_max, color_48, bytes_per_line); 2530141cc406Sopenharmony_ci 2531141cc406Sopenharmony_ci append_and_move_lines(scanner->color_shift_line_buffer2, scanner->color_shift_buffered_lines2, scanner->color_shift_line_buffer1, &(scanner->color_shift_buffered_lines1), offset_max, bytes_per_line); 2532141cc406Sopenharmony_ci } 2533141cc406Sopenharmony_ci 2534141cc406Sopenharmony_ci return ret; 2535141cc406Sopenharmony_ci} 2536141cc406Sopenharmony_ci 2537141cc406Sopenharmony_ci/******************************************************************************/ 2538141cc406Sopenharmony_civoid 2539141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2540141cc406Sopenharmony_ci{ 2541141cc406Sopenharmony_ci struct hp5590_scanner *scanner = handle; 2542141cc406Sopenharmony_ci SANE_Status ret; 2543141cc406Sopenharmony_ci 2544141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2545141cc406Sopenharmony_ci 2546141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2547141cc406Sopenharmony_ci 2548141cc406Sopenharmony_ci if (scanner->dn < 0) 2549141cc406Sopenharmony_ci return; 2550141cc406Sopenharmony_ci 2551141cc406Sopenharmony_ci hp5590_low_free_bulk_read_state (&scanner->bulk_read_state); 2552141cc406Sopenharmony_ci 2553141cc406Sopenharmony_ci ret = hp5590_stop_scan (scanner->dn, scanner->proto_flags); 2554141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 2555141cc406Sopenharmony_ci return; 2556141cc406Sopenharmony_ci} 2557141cc406Sopenharmony_ci 2558141cc406Sopenharmony_ci/******************************************************************************/ 2559141cc406Sopenharmony_ci 2560141cc406Sopenharmony_ciSANE_Status 2561141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, 2562141cc406Sopenharmony_ci SANE_Bool __sane_unused__ non_blocking) 2563141cc406Sopenharmony_ci{ 2564141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2565141cc406Sopenharmony_ci 2566141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2567141cc406Sopenharmony_ci} 2568141cc406Sopenharmony_ci 2569141cc406Sopenharmony_ci/******************************************************************************/ 2570141cc406Sopenharmony_ciSANE_Status 2571141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, 2572141cc406Sopenharmony_ci SANE_Int __sane_unused__ * fd) 2573141cc406Sopenharmony_ci{ 2574141cc406Sopenharmony_ci DBG (DBG_proc, "%s\n", __func__); 2575141cc406Sopenharmony_ci 2576141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2577141cc406Sopenharmony_ci} 2578141cc406Sopenharmony_ci 2579141cc406Sopenharmony_ci/* vim: sw=2 ts=8 2580141cc406Sopenharmony_ci */ 2581