piuspatch  v0.1
USB addition to PIE backend
only-pie/backend/pie.c
Go to the documentation of this file.
00001 /* sane - Scanner Access Now Easy. */
00002 
00097 #include "../include/sane/config.h"
00098 
00099 #include <errno.h>
00100 #include <fcntl.h>
00101 #include <limits.h>
00102 #include <signal.h>
00103 #include <stdio.h>
00104 #include <stdlib.h>
00105 #include <string.h>
00106 #include <sys/types.h>
00107 #include <sys/wait.h>
00108 #include <sys/time.h>
00109 #include <unistd.h>
00110 #include <stdint.h>
00111 #include <math.h>
00112 #include <limits.h>
00113 
00114 #include "../include/byteorder.h"       /* TODO portable ? */
00115 #include "../include/sane/sane.h"
00116 #include "../include/sane/sanei.h"
00117 #include "../include/sane/saneopts.h"
00118 #include "../include/sane/sanei_scsi.h"
00119 #include "../include/sane/sanei_usb.h"
00120 #include "../include/sane/sanei_debug.h"
00121 
00122 #define BACKEND_NAME    pie
00123 
00124 #include "../include/sane/sanei_backend.h"
00125 #include "../include/sane/sanei_config.h"
00126 
00127 #include "../include/sane/sanei_thread.h"
00128 #include "../include/sane/sanei_ir.h"
00129 #include "../include/sane/sanei_magic.h"
00130 
00131 /*
00132  * @@ Definitions  and static allocation
00133  */
00134 
00135 #include "pie-scsidef.h"
00136 #include "pie_usb.h"
00137 
00138 #define DBG_error0  0
00139 #define DBG_error   1
00140 #define DBG_sense   2
00141 #define DBG_warning 3
00142 #define DBG_inquiry 4
00143 
00144 #define DBG_info    5
00145 #define DBG_info2   6
00146 #define DBG_proc    7
00147 #define DBG_read    8
00148 #define DBG_sane_init   10
00149 #define DBG_sane_proc   11
00150 #define DBG_sane_info   12
00151 #define DBG_sane_option 13
00152 #define DBG_dump        14
00153 #define DBG_image       15
00154 #define DBG_poke        16
00155 
00156 #define BUILD 10
00157 
00158 #define PIE_CONFIG_FILE "pie.conf"
00159 
00160 /* Option string defines */
00161 
00162 #define LINEART_STR             SANE_VALUE_SCAN_MODE_LINEART
00163 #define HALFTONE_STR            SANE_VALUE_SCAN_MODE_HALFTONE
00164 #define GRAY_STR                SANE_VALUE_SCAN_MODE_GRAY
00165 #define COLOR_STR               SANE_VALUE_SCAN_MODE_COLOR
00166 #define COLOR_IR_STR            "RGBI"
00167 
00168 #define IR_NAME_STR             "swired"
00169 #define IR_TITLE_STR            "Infrared processing"
00170 #define IR_DESC_STR             "What to do with infrared plane";
00171 #define IR_SPECT_STR            "Reduce red overlap"
00172 #define IR_CLEAN_STR            "Remove dirt"
00173 
00174 #define THE_NONE_STR             "None"
00175 
00176 #define CROP_NAME_STR             "swcrop"
00177 #define CROP_TITLE_STR            "Cropping"
00178 #define CROP_DESC_STR             "How to crop the image";
00179 #define CROP_OUTER_STR            "Outside"
00180 #define CROP_INNER_STR            "Inside"
00181 
00182 /* Color modes the scanner is operated in */
00183 
00184 #define LINEART                         1
00185 #define HALFTONE                        2
00186 #define GRAYSCALE                       3
00187 #define RGB                             4
00188 /* USB film scanners: infrared modus */
00189 #define RGBI                            8
00190 
00191 /* USB film scanners: post scan processing */
00192 
00193 #define POST_SW_COLORS          (1 << 0)        /* gain, negatives, ..., can be done at any time */
00194 #define POST_SW_IRED            (1 << 1)        /* remove spectral overlap, needs complete scan */
00195 #define POST_SW_DIRT            (1 << 2)        /* our digital lavabo, needs complete scan */
00196 #define POST_SW_GRAIN           (1 << 3)        /* smoothen a bit */
00197 #define POST_SW_CROP            (1 << 4)        /* trim whole image in sane_start
00198                                                    before sane_get_parameters() is answered */
00199 #define POST_SW_IRED_MASK       (POST_SW_IRED | POST_SW_DIRT)
00200 #define POST_SW_ACCUM_MASK      (POST_SW_IRED_MASK | POST_SW_GRAIN | POST_SW_CROP)
00201 
00202 /* SCSI scanners: calibration modes */
00203 
00204 #define CAL_MODE_PREVIEW        (INQ_CAP_FAST_PREVIEW)
00205 #define CAL_MODE_FLATBED        0x00
00206 #define CAL_MODE_ADF            (INQ_OPT_DEV_ADF)
00207 #define CAL_MODE_TRANPSARENCY   (INQ_OPT_DEV_TP)
00208 #define CAL_MODE_TRANPSARENCY1  (INQ_OPT_DEV_TP1)
00209 
00210 #define min(a,b) (((a)<(b))?(a):(b))
00211 #define max(a,b) (((a)>(b))?(a):(b))
00212 
00213 /* names of scanners that are supported because */
00214 /* the inquiry_return_block is ok and driver is tested,
00215  * for USB film scanners a first rough identification
00216  */
00217 static char *scanner_str[] = {
00218   "DEVCOM", "9636PRO",
00219   "DEVCOM", "9636S",
00220   "DEVCOM", "9630S",
00221   "PIE", "ScanAce 1236S",
00222   "PIE", "ScanAce 1230S",
00223   "PIE", "ScanAce II",
00224   "PIE", "ScanAce III",
00225   "PIE", "ScanAce Plus",
00226   "PIE", "ScanAce II Plus",
00227   "PIE", "ScanAce III Plus",
00228   "PIE", "ScanAce V",
00229   "PIE", "ScanMedia",
00230   "PIE", "ScanMedia II",
00231   "PIE", "ScanAce 630S",
00232   "PIE", "ScanAce 636S",
00233   "AdLib", "JetScan 630",
00234   "AdLib", "JetScan 636PRO",
00235   /* USB film scanners */
00236   "PIE", "SF Scanner",
00237   "END_OF_LIST"
00238 };
00239 
00240 /* times (in us) to delay after certain commands. Scanner seems to lock up if it returns busy
00241  * status and commands are repeatedly reissued (by kernel error handler) */
00242 
00243 #define DOWNLOAD_GAMMA_WAIT_TIME        (1000000)
00244 #define SCAN_WAIT_TIME                  (1000000)
00245 #define SCAN_WARMUP_WAIT_TIME           (500000)
00246 #define TUR_WAIT_TIME                   (500000)
00247 
00248 /* otherwise lots of warnings when compiled with pthread enabled */
00249 #if defined USE_PTHREAD
00250 #define NO_PID (pthread_t) -1
00251 #else
00252 #define NO_PID -1
00253 #endif
00254 
00260 enum Pie_Option
00261 {
00262   OPT_NUM_OPTS = 0,
00263 
00264   /* ------------------------------------------- */
00265   OPT_MODE_GROUP,
00266   OPT_MODE,
00267   OPT_BIT_DEPTH,
00268   OPT_RESOLUTION,
00269 
00270 
00271   /* ------------------------------------------- */
00272 
00273   OPT_GEOMETRY_GROUP,
00274   OPT_TL_X,                     /* top-left x */
00275   OPT_TL_Y,                     /* top-left y */
00276   OPT_BR_X,                     /* bottom-right x */
00277   OPT_BR_Y,                     /* bottom-right y */
00278 
00279   /* ------------------------------------------- */
00280 
00281   OPT_ENHANCEMENT_GROUP,
00282 
00283   OPT_HALFTONE_PATTERN,         /* SCSI only */
00284   OPT_SPEED,
00285   OPT_THRESHOLD,                /* SCSI only */
00286 
00287   OPT_SW_CROP,                  /* USB only */
00288   OPT_SW_IRED,                  /* USB only */
00289   OPT_SW_GRAIN,                 /* USB only */
00290   OPT_SW_SRGB,                  /* USB only */
00291   OPT_SW_NEGA,                  /* USB only */
00292 
00293   OPT_GAMMA_VECTOR,             /* SCSI only */
00294   OPT_GAMMA_VECTOR_R,           /* SCSI only */
00295   OPT_GAMMA_VECTOR_G,           /* SCSI only */
00296   OPT_GAMMA_VECTOR_B,           /* SCSI only */
00297 
00298   /* ------------------------------------------- */
00299 
00300   OPT_ADVANCED_GROUP,
00301   OPT_PREVIEW,
00302 
00303   /* must come last: */
00304   NUM_OPTIONS
00305 };
00306 
00307 
00312 struct Pie_cal_info
00313 {
00314   int cal_type;
00315   int receive_bits;
00316   int send_bits;
00317   int num_lines;
00318   int pixels_per_line;
00319 };
00320 
00324 typedef struct Pie_Device
00325 {
00326   struct Pie_Device *next;
00327 
00328   char *devicename;             
00330   char *vendor;                 
00331   char *product;                
00332   char *version;                
00334   PIE_USB_Model *model;         
00335   SANE_Device sane;
00336   SANE_Range dpi_range;
00337   SANE_Range x_range;
00338   SANE_Range y_range;
00339 
00340   SANE_Range exposure_range;
00341   SANE_Range shadow_range;
00342   SANE_Range highlight_range;
00343 
00344   int inquiry_len;              
00346   int inquiry_x_res;            
00347   int inquiry_y_res;            
00348   int inquiry_pixel_resolution;
00349   double inquiry_fb_width;      
00350   double inquiry_fb_length;     
00352   int inquiry_trans_top_left_x;
00353   int inquiry_trans_top_left_y;
00354   double inquiry_trans_width;   
00355   double inquiry_trans_length;  
00357   int inquiry_halftones;        
00358   int inquiry_filters;          
00359   int inquiry_color_depths;     
00360   int inquiry_color_format;     
00361   int inquiry_image_format;     
00362   int inquiry_scan_capability;  
00363   int inquiry_optional_devices; 
00364   int inquiry_enhancements;     
00365   int inquiry_gamma_bits;       
00366   int inquiry_fast_preview_res; 
00367   int inquiry_min_highlight;    
00368   int inquiry_max_shadow;       
00369   int inquiry_cal_eqn;          
00370   int inquiry_min_exp;          
00371   int inquiry_max_exp;          
00373   SANE_String scan_mode_list[7];        
00374   SANE_String ir_sw_list[4];            
00375   SANE_String crop_sw_list[4];          
00377   SANE_Word bpp_list[4];        
00378   SANE_Word grain_sw_list[6];   
00380   SANE_String halftone_list[17];        
00382   SANE_String speed_list[9];    
00384   int cal_info_count;           
00385   struct Pie_cal_info *cal_info;        
00387   SANE_Status (*scsi_cmd) (int fd, const void *src, size_t src_size,
00388                            void *dst, size_t * dst_size);
00389 }
00390 Pie_Device;
00391 
00395 typedef struct Pie_Scanner
00396 {
00397   struct Pie_Scanner *next;
00398   Pie_Device *device;           
00400   int sfd;                      
00401   int bufsize;                  
00403   SANE_Option_Descriptor opt[NUM_OPTIONS];      
00404   Option_Value val[NUM_OPTIONS];        
00405   SANE_Int *gamma_table[4];     
00406   SANE_Range gamma_range;
00407   int gamma_length;             
00409   uint16_t *gamma_lut8;         
00410   uint16_t *gamma_lut16;
00411   double *ln_lut;              
00413   int scanning;                 
00414   SANE_Parameters params;
00415 
00416   SANE_Pid parking_pid;         
00417   SANE_Pid reader_pid;
00418   int pipe;
00419   int reader_fds;
00420   
00421   int colormode;                
00422   int processing;               
00423   int resolution;
00424   int cal_mode;                 
00426   int cal_filter;               
00427   PIE_USB_Calibration *cal_data;        
00429   int filter_offset1;           
00430   int filter_offset2;
00431 
00432   int bytes_per_line;           
00434   SANEI_IR_bufptr img_buffer;  
00435   int total_bytes_stored;
00436   int total_bytes_read;         
00437 }
00438 Pie_Scanner;
00439 
00440 /* forward declarations */
00441 
00442 static SANE_Status pie_usb_read_status (int dn, unsigned char *buf);
00443 SANE_Status
00444 pie_usb_scsi_wrapper (int fd, const void *src, size_t src_size, void *dst,
00445                       size_t * dst_size);
00446 static SANE_Status
00447 pie_sense_handler (int scsi_fd, unsigned char *result, void *arg);
00448 static SANE_Status pie_wait_scanner (Pie_Scanner * scanner);
00449 static SANE_Status pie_send_exposure (Pie_Scanner * scanner);
00450 static SANE_Status pie_send_highlight_shadow (Pie_Scanner * scanner);
00451 static SANE_Status pie_power_save (Pie_Scanner * scanner, int time);
00452 static SANE_Status pie_attach_one (const char *name);
00453 
00454 
00455 /* USB scanners can not be "killed" by a cancel
00456  * but have to complete their current USB transaction,
00457  *  used to gracefully cancel the child thread / process */
00458 static volatile sig_atomic_t cancel_requ;
00459 
00460 static const SANE_Range percentage_range_100 = {
00461   0 << SANE_FIXED_SCALE_SHIFT,  /* minimum */
00462   100 << SANE_FIXED_SCALE_SHIFT,        /* maximum */
00463   0 << SANE_FIXED_SCALE_SHIFT   /* quantization */
00464 };
00465 
00466 static Pie_Device *first_dev = NULL;
00467 static Pie_Scanner *first_handle = NULL;
00468 static const SANE_Device **devlist = NULL;
00469 
00470 #define DBG_DUMP(level, buf, n) { if (DBG_LEVEL >= (level)) pie_dump_buffer(level,buf,n); }
00471 
00472 
00473 /* USB film scanners we support
00474  */
00475 static PIE_USB_Model crystalscan_7200_model = {
00476   "PIE/Reflecta",               /* Device vendor string */
00477   "CrystalScan 7200",           /* Device model name */
00478   0x30,                         /* Model ID */
00479   PIE_USB_FLAG_MIRROR_IMAGE |   /* flags */
00480     PIE_USB_FLAG_XRES_FAKE,
00481   /* operation mode values for preview, skip calibration and quality */
00482   {0x00, 0x08, 0x0a},
00483   75000,                        /* default brightness */
00484   /* R, G, B gain constant */
00485   {4.19682524E-04, 3.92060196E-04, 3.89647803E-04},
00486   /* R, G, B normal mode offset factor */
00487   {1.05, 1.05, 1.05},
00488   16,                           /* minimal gain */
00489   42,                           /* maximal gain in quality mode */
00490   0x0f00,                       /* normal mode maximal exposure time */
00491   10,                           /* gain calibration part */
00492   {{0x16e6, 0x0ff2, 0x0ff2},    /* RGB texp and gain, first calibration if quality mode */
00493    0x16e6, {0x21, 0x21, 0x19}},
00494   {{0x0be2, 0x0bcf, 0x0b88},    /* RGB texp and gain, first calibration if normal mode */
00495    0x0be2, {0x35, 0x2c, 0x27}}
00496 };
00497 
00498 static PIE_USB_Model proscan_7200_model = {
00499   "PIE/Reflecta",               /* Device vendor string */
00500   "ProScan 7200",               /* Device model name */
00501   0x36,                         /* Model ID */
00502   PIE_USB_FLAG_MIRROR_IMAGE,    /* flags */
00503   /* operation mode values for preview, skip calibration and quality */
00504   {0x00, 0x08, 0x02},
00505   75000,                        /* default brightness */
00506   /* R, G, B gain constant */
00507   {4.19682524E-04, 3.92060196E-04, 3.89647803E-04},
00508   /* R, G, B normal mode offset factor */
00509   {1.2229896394, 1.0447735936, 0.9805181615},
00510   16,                           /* minimal gain */
00511   42,                           /* maximal gain in quality mode */
00512   0x0f00,                       /* normal mode maximal exposure time */
00513   10,                           /* gain calibration part */
00514   {{0x2c89, 0x1eb7, 0x17ca},    /* RGB texp and gain, first calibration if quality mode */
00515    0x2c89, {0x25, 0x25, 0x28}},
00516   {{0x0e79, 0x0bff, 0x0c6c},    /* RGB texp and gain, first calibration if normal mode */
00517    0x0e79, {0x3f, 0x3d, 0x39}}
00518 };
00519 
00520 /* list of USB descriptors, do not mind different models with the same USB id
00521  */
00522 static PIE_USB_Device_Entry pie_usb_device_list[] = {
00523   {0x05e3, 0x0145, &crystalscan_7200_model},    /* Reflecta CrystalScan 7200, id 0x30 */
00524   {0x05e3, 0x0145, &proscan_7200_model},        /* Reflecta ProScan 7200, id 0x36 */
00525   {0, 0, 0}
00526 };
00527 
00528 /*
00529  * @@ Utility functions mostly for USB code
00530  */
00531 
00532 /* ---------------------------------- PIE DUMP_BUFFER ---------------------------------- */
00540 static void
00541 pie_dump_buffer (int level, unsigned char *buf, int n)
00542 {
00543   char s[80], *p = s;
00544   int a = 0;
00545 
00546   while (n--)
00547     {
00548       if ((a % 16) == 0)
00549         p += sprintf (p, "  %04X  ", a);
00550 
00551       p += sprintf (p, "%02X ", *buf++);
00552 
00553       if ((n == 0) || (a % 16) == 15)
00554         {
00555           DBG (level, "%s\n", s);
00556           p = s;
00557         }
00558       a++;
00559     }
00560 }
00561 
00562 /* --------------------------------- PIE_USB_POKE_INTS --------------------------------- */
00577 static SANE_Status
00578 pie_usb_poke_ints (char *filename, int *nums, int *len)
00579 {
00580   FILE *afile;
00581   char buffer[1024];
00582   char *fres, *nptr;
00583   char *eptr = NULL;
00584   long int lnum;
00585   int i;
00586 
00587   afile = fopen (filename, "r");
00588   if (afile == NULL)
00589     {
00590       DBG (DBG_error, "pie_usb_poke_ints: file %s does not exist\n",
00591            filename);
00592       return SANE_STATUS_INVAL;
00593     }
00594 
00595   i = 0;
00596   do
00597     {
00598       fres = fgets (buffer, sizeof (buffer), afile);
00599       if (fres != NULL)
00600         {
00601           nptr = buffer;
00602           errno = 0;
00603           lnum = strtol (nptr, &eptr, 10);
00604           while ((errno == 0) && (nptr != eptr) && (i < *len))
00605             {
00606               nums[i] = lnum;
00607               i++;
00608               nptr = eptr;
00609 
00610               errno = 0;
00611               lnum = strtol (nptr, &eptr, 10);
00612             }
00613         }
00614     }
00615   while (fres != NULL);
00616   *len = i;
00617 
00618   fclose (afile);
00619 
00620   return SANE_STATUS_GOOD;
00621 }
00622 
00623 /* -------------------------------- PIE_USB_POKE_BYTES --------------------------------- */
00637 static SANE_Status
00638 pie_usb_poke_bytes (char *filename, unsigned char *nums, int *len)
00639 {
00640   FILE *afile;
00641   char buffer[1024];
00642   char *fres, *nptr;
00643   char *eptr = NULL;
00644   long int lnum;
00645   int i;
00646 
00647   afile = fopen (filename, "r");
00648   if (afile == NULL)
00649     {
00650       DBG (DBG_error, "pie_usb_poke_bytes: file %s does not exist\n",
00651            filename);
00652       return SANE_STATUS_INVAL;
00653     }
00654 
00655   i = 0;
00656   do
00657     {
00658       fres = fgets (buffer, sizeof (buffer), afile);
00659       if (fres != NULL)
00660         {
00661           nptr = buffer;
00662           errno = 0;
00663           lnum = strtol (nptr, &eptr, 16);
00664           while ((errno == 0) && (nptr != eptr) && (i < *len))
00665             {
00666               nums[i] = lnum & 0xff;
00667               i++;
00668               nptr = eptr;
00669 
00670               errno = 0;
00671               lnum = strtol (nptr, &eptr, 16);
00672             }
00673         }
00674     }
00675   while (fres != NULL);
00676   *len = i;
00677 
00678   fclose (afile);
00679 
00680   return SANE_STATUS_GOOD;
00681 }
00682 
00683 
00684 /* ------------------------------ PIE_USB_WRITE_PNM_FILE ------------------------------- */
00698 static SANE_Status
00699 pie_usb_write_pnm_file (char *filename, uint8_t * data, int depth,
00700                         int channels, int pixels_per_line, int lines)
00701 {
00702   FILE *out;
00703   int count;
00704 
00705   DBG (DBG_proc,
00706        "pie_usb_write_pnm_file: depth=%d, channels=%d, ppl=%d, lines=%d\n",
00707        depth, channels, pixels_per_line, lines);
00708 
00709   out = fopen (filename, "w");
00710   if (!out)
00711     {
00712       DBG (DBG_error,
00713            "pie_usb_write_pnm_file: could nor open %s for writing: %s\n",
00714            filename, strerror (errno));
00715       return SANE_STATUS_INVAL;
00716     }
00717   if (depth == 1)
00718     {
00719       fprintf (out, "P4\n%d\n%d\n", pixels_per_line, lines);
00720     }
00721   else
00722     {
00723       fprintf (out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6',
00724                pixels_per_line, lines, (int) pow (2, depth) - 1);
00725     }
00726   if (channels == 3)
00727     {
00728       for (count = 0; count < (pixels_per_line * lines * 3); count++)
00729         {
00730           if (depth == 16)
00731             fputc (*(data + 1), out);
00732           fputc (*(data++), out);
00733           if (depth == 16)
00734             data++;
00735         }
00736     }
00737   else
00738     {
00739       if (depth == 1)
00740         {
00741           pixels_per_line /= 8;
00742         }
00743       for (count = 0; count < (pixels_per_line * lines); count++)
00744         {
00745           switch (depth)
00746             {
00747             case 8:
00748               fputc (*(data + count), out);
00749               break;
00750             case 16:
00751               fputc (*(data + 1), out);
00752               fputc (*(data), out);
00753               data += 2;
00754               break;
00755             default:
00756               fputc (data[count], out);
00757               break;
00758             }
00759         }
00760     }
00761   fclose (out);
00762 
00763   DBG (DBG_info, "pie_usb_write_pnm_file: finished\n");
00764   return SANE_STATUS_GOOD;
00765 }
00766 
00767 /* ------------------------------ PIE_USB_SHADES_TO_PNM -------------------------------- */
00780 static SANE_Status
00781 pie_usb_shades_to_pnm (Pie_Scanner * scanner, char *name, int lines)
00782 {
00783   char plane[4][12] = { "-red.pnm", "-green.pnm", "-blue.pnm", "-ired.pnm" };
00784   char filename[256];
00785   unsigned char *buffer, *dest;
00786   int *shade[4];
00787   int pixels_per_line;
00788   int snd_length, bits;
00789   int i, j, k, val;
00790   SANE_Int status;
00791 
00792   DBG (DBG_proc, "pie_usb_shades_to_pnm\n");
00793 
00794   pixels_per_line = scanner->device->cal_info[0].pixels_per_line;
00795   snd_length = pixels_per_line;
00796   bits = scanner->device->cal_info[0].receive_bits;
00797   if (bits > 8)
00798     snd_length *= 2;
00799 
00800   buffer = malloc (snd_length * lines);
00801   if (!buffer)
00802     return SANE_STATUS_NO_MEM;
00803   for (k = 0; k < 4; k++)
00804     {
00805       shade[k] = scanner->cal_data->shades + k * pixels_per_line;
00806     }
00807 
00808   for (j = 0; j < 4; j++)
00809     {
00810       dest = buffer;
00811       if (bits > 8)
00812         for (i = 0; i < pixels_per_line; i++)
00813           {
00814             val = shade[j][i];
00815             *dest++ = val & 0xff;
00816             *dest++ = (val >> 8) & 0xff;
00817           }
00818       else
00819         for (i = 0; i < pixels_per_line; i++)
00820           *dest++ = shade[j][i] & 0xff;
00821       for (i = 1; i < lines; i++)
00822         {
00823           memcpy (dest, buffer, snd_length);
00824           dest += snd_length;
00825         }
00826 
00827       strncpy (filename, name, 240);
00828       strncat (filename, plane[j], 255);
00829       status = pie_usb_write_pnm_file (filename, buffer, bits,
00830                                        1, pixels_per_line, lines);
00831       if (status != SANE_STATUS_GOOD)
00832         return status;
00833     }
00834 
00835   free (buffer);
00836   return SANE_STATUS_GOOD;
00837 }
00838 
00839 /*
00840  * @@ SCSI over USB and related functions
00841  */
00842 
00843 /* ----------------------- PIE_USB_WRITE_CONTROL_SEQUENCE ------------------------ */
00856 static SANE_Status
00857 pie_usb_write_control_sequence (SANE_Int dn, PIE_USB_Value_Data sequ[])
00858 {
00859   SANE_Int status = SANE_STATUS_GOOD;
00860   int i;
00861 
00862   DBG (DBG_proc, "pie_usb_write_control_sequence writing\n");
00863 
00864   for (i = 0; (status == SANE_STATUS_GOOD) && (sequ[i].bValue != 0); i++)
00865     {
00866       status =
00867         sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
00868                                sequ[i].bValue, INDEX, 1, &(sequ[i].bData));
00869       if (status != SANE_STATUS_GOOD)
00870         {
00871           DBG (DBG_error, "pie_usb_write_control_sequence failed\n");
00872           return status;
00873         }
00874     }
00875   return SANE_STATUS_GOOD;
00876 }
00877 
00878 /* ---------------------------- PIE_USB_READY_STATE ------------------------------ */
00894 static SANE_Status
00895 pie_usb_ready_state (SANE_Int dn)
00896 {
00897   SANE_Status status;
00898   SANE_Byte val;
00899 
00900   status =
00901     sanei_usb_control_msg (dn, REQUEST_TYPE_IN, REQUEST_REGISTER,
00902                            VALUE_READ_REGISTER, INDEX, 1, &val);
00903   if (status != SANE_STATUS_GOOD)
00904     {
00905       DBG (DBG_error, "pie_usb_ready_state failed at 1st read\n");
00906       return status;
00907     }
00908   DBG (DBG_info, "pie_usb_ready_state got 0x%02x at 1st read\n", val);
00909 
00910   if (val <= 1)
00911     return SANE_STATUS_GOOD;
00912   if (val != 3)
00913     {
00914       DBG (DBG_error, "pie_usb_ready_state failed\n");
00915       return SANE_STATUS_INVAL;
00916     }
00917 
00918   status =
00919     sanei_usb_control_msg (dn, REQUEST_TYPE_IN, REQUEST_REGISTER,
00920                            VALUE_READ_REGISTER, INDEX, 1, &val);
00921   if (status != SANE_STATUS_GOOD)
00922     {
00923       DBG (DBG_error, "pie_usb_ready_state failed at 2nd read\n");
00924       return status;
00925     }
00926   DBG (DBG_info, "pie_usb_ready_state got 0x%02x at 2nd read\n", val);
00927 
00928   if (val == 0)
00929     return SANE_STATUS_GOOD;
00930   else if (val == 8)
00931     return SANE_STATUS_DEVICE_BUSY;
00932   else if (val == 2)
00933     return SANE_STATUS_IO_ERROR;
00934   else
00935     return SANE_STATUS_INVAL;
00936 }
00937 
00938 /* --------------------------- PIE_USB_WRITE_SCSI_CMD ---------------------------- */
00951 static SANE_Status
00952 pie_usb_write_scsi_cmd (SANE_Int dn, const SANE_Byte cmnd[6])
00953 {
00954   SANE_Status status;
00955   SANE_Byte mnd;
00956   int i;
00957 
00958   DBG (DBG_proc, "pie_usb_write_scsi_cmd writing 6 bytes\n");
00959 
00960   for (i = 0; i < 6; i++)
00961     {
00962       mnd = cmnd[i];
00963       status =
00964         sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
00965                                VALUE_WRITE_REGISTER, INDEX, 1, &mnd);
00966       if (status != SANE_STATUS_GOOD)
00967         {
00968           DBG (DBG_error, "pie_usb_write_scsi_cmd failed at byte %d\n", i);
00969           return status;
00970         }
00971     }
00972   return SANE_STATUS_GOOD;
00973 }
00974 
00975 /* ----------------------------- PIE_USB_BULK_READ ------------------------------- */
00989 static SANE_Status
00990 pie_usb_bulk_read (SANE_Int dn, SANE_Byte * data, size_t len)
00991 {
00992   SANE_Status status;
00993   size_t size;
00994   SANE_Byte outdata[8];
00995 
00996   DBG (DBG_proc, "pie_usb_bulk_read requesting %lu bytes\n", (u_long) len);
00997 
00998   if (len == 0)
00999 
01000     return SANE_STATUS_GOOD;
01001 
01002   memset (outdata, '\0', sizeof (outdata));
01003 
01004   while (len)
01005     {
01006       if (len > BULKIN_MAXSIZE)
01007         size = BULKIN_MAXSIZE;
01008       else
01009         size = len;
01010 
01011       outdata[4] = (size & 0xff);
01012       outdata[5] = ((size >> 8) & 0xff);
01013       outdata[6] = ((size >> 16) & 0xff);
01014       outdata[7] = ((size >> 24) & 0xff);
01015 
01016       status =
01017         sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
01018                                VALUE_BUFFER, INDEX, sizeof (outdata),
01019                                outdata);
01020       if (status != SANE_STATUS_GOOD)
01021         {
01022           DBG (DBG_error,
01023                "pie_usb_bulk_read failed while writing command: %s\n",
01024                sane_strstatus (status));
01025           return status;
01026         }
01027 
01028       DBG (DBG_info,
01029            "pie_usb_bulk_read trying to read %lu bytes of data\n",
01030            (u_long) size);
01031       status = sanei_usb_read_bulk (dn, data, &size);
01032       if (status != SANE_STATUS_GOOD)
01033         {
01034           DBG (DBG_error,
01035                "pie_usb_bulk_read failed while reading bulk data: %s\n",
01036                sane_strstatus (status));
01037           return status;
01038         }
01039 
01040       DBG (DBG_info,
01041            "pie_usb_bulk_read read %lu bytes, %lu remaining\n",
01042            (u_long) size, (u_long) (len - size));
01043       len -= size;
01044       data += size;
01045     }
01046 
01047   DBG (DBG_info, "pie_usb_bulk_read completed\n");
01048   return SANE_STATUS_GOOD;
01049 }
01050 
01051 /* ------------------------------- PIE_USB_READ ---------------------------------- */
01073 static SANE_Status
01074 pie_usb_read (int dn, const SANE_Byte * cmnd, void *buf, size_t * buf_len)
01075 {
01076   SANE_Status status;
01077   size_t length = *buf_len;
01078 
01079   DBG (DBG_proc, "pie_usb_read\n");
01080 
01081   status = pie_usb_write_scsi_cmd (dn, cmnd);
01082   if (status != SANE_STATUS_GOOD)
01083     return status;
01084   status = pie_usb_ready_state (dn);
01085   if (status != SANE_STATUS_GOOD)
01086     return status;
01087 
01088   status = pie_usb_bulk_read (dn, buf, length);
01089   if (status != SANE_STATUS_GOOD)
01090     return status;
01091 
01092   return pie_usb_ready_state (dn);
01093 }
01094 
01095 /* ------------------------------- PIE_USB_WRITE --------------------------------- */
01114 static SANE_Status
01115 pie_usb_write (int dn, const SANE_Byte * cmnd, size_t length)
01116 {
01117   SANE_Status status;
01118   SANE_Byte mnd;
01119   size_t i;
01120 
01121   DBG (DBG_proc, "pie_usb_write\n");
01122   if (length <= 6)
01123     return SANE_STATUS_GOOD;
01124 
01125   status = pie_usb_write_scsi_cmd (dn, cmnd);
01126   if (status != SANE_STATUS_GOOD)
01127     return status;
01128   status = pie_usb_ready_state (dn);
01129   if (status != SANE_STATUS_GOOD)
01130     return status;
01131 
01132   DBG (DBG_info, "pie_usb_write: now writing %lu bytes\n",
01133        (u_long) length - 6);
01134   for (i = 6; i < length; i++)
01135     {
01136       mnd = cmnd[i];
01137       status =
01138         sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
01139                                VALUE_WRITE_REGISTER, INDEX, 1, &mnd);
01140       if (status != SANE_STATUS_GOOD)
01141         {
01142           DBG (DBG_error, "pie_usb_write failed at byte %lu\n",
01143                (unsigned long) length);
01144           return status;
01145         }
01146     }
01147 
01148   return pie_usb_ready_state (dn);
01149 }
01150 
01151 /* ------------------------------ PIE_USB_COMMAND -------------------------------- */
01165 static SANE_Status
01166 pie_usb_command (int dn, const SANE_Byte * cmnd)
01167 {
01168   SANE_Status status;
01169 
01170   DBG (DBG_proc, "pie_usb_command\n");
01171 
01172   status = pie_usb_write_scsi_cmd (dn, cmnd);
01173   if (status != SANE_STATUS_GOOD)
01174     return status;
01175 
01176   return pie_usb_ready_state (dn);
01177 }
01178 
01179 /* ---------------------------- PIE_USB_SCSI_WRAPPER ----------------------------- */
01199 SANE_Status
01200 pie_usb_scsi_wrapper (int fd, const void *src, size_t src_size, void *dst,
01201                       size_t * dst_size)
01202 {
01203   /* values for some stereotype USB control write sequences */
01204   static PIE_USB_Value_Data PIE_USB_Init_Sequence_1[] = {
01205     {VALUE_INIT_1, 0x04},
01206     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55},
01207     {VALUE_INIT_2, 0x00},
01208     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78},
01209     {VALUE_INIT_2, 0x30},
01210     {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
01211     {VALUE_INIT_2, 0xff},
01212     {0x0, 0x0}
01213   };
01214   static PIE_USB_Value_Data PIE_USB_Init_Sequence_2[] = {
01215     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55},
01216     {VALUE_INIT_2, 0x00},
01217     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78},
01218     {VALUE_INIT_2, 0x00},
01219     {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
01220     {VALUE_INIT_2, 0xff},
01221     {0x0, 0x0}
01222   };
01223   static PIE_USB_Value_Data PIE_USB_Setup_SCSI_Sequence[] = {
01224     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0xaa}, {VALUE_INIT_2, 0x55},
01225     {VALUE_INIT_2, 0x00},
01226     {VALUE_INIT_2, 0xff}, {VALUE_INIT_2, 0x87}, {VALUE_INIT_2, 0x78},
01227     {VALUE_INIT_2, 0xe0},
01228     {VALUE_INIT_1, 0x05}, {VALUE_INIT_1, 0x04},
01229     {VALUE_INIT_2, 0xff},
01230     {0x0, 0x0}
01231   };
01232 
01233   SANE_Status status = SANE_STATUS_GOOD;
01234   const SANE_Byte *cmnd = src;
01235 
01236   if (cmnd[0] == INQUIRY)
01237     {
01238       status = pie_usb_write_control_sequence (fd, PIE_USB_Init_Sequence_1);
01239       if (status != SANE_STATUS_GOOD)
01240         return status;
01241       status = pie_usb_write_control_sequence (fd, PIE_USB_Init_Sequence_2);
01242       if (status != SANE_STATUS_GOOD)
01243         return status;
01244     }
01245   status = pie_usb_write_control_sequence (fd, PIE_USB_Setup_SCSI_Sequence);
01246   if (status != SANE_STATUS_GOOD)
01247     return status;
01248 
01249   switch (cmnd[0])
01250     {
01251     case TEST_UNIT_READY:
01252       DBG (DBG_proc, "pie_usb_scsi_wrapper doing TEST_UNIT_READY\n");
01253       status = pie_usb_command (fd, cmnd);
01254       break;
01255     case REQUEST_SENSE:
01256       DBG (DBG_proc, "pie_usb_scsi_wrapper doing REQUEST_SENSE\n");
01257       status = pie_usb_read (fd, cmnd, dst, dst_size);
01258       break;
01259     case READ:
01260       DBG (DBG_proc, "pie_usb_scsi_wrapper doing READ\n");
01261       status = pie_usb_read (fd, cmnd, dst, dst_size);
01262       break;
01263     case WRITE:
01264       DBG (DBG_proc, "pie_usb_scsi_wrapper doing WRITE\n");
01265       status = pie_usb_write (fd, cmnd, src_size);
01266       break;
01267     case INQUIRY:
01268       DBG (DBG_proc, "pie_usb_scsi_wrapper doing INQUIRY\n");
01269       status = pie_usb_read (fd, cmnd, dst, dst_size);
01270       break;
01271     case PARAM:
01272       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PARAM\n");
01273       status = pie_usb_read (fd, cmnd, dst, dst_size);
01274       break;
01275     case MODE:
01276       DBG (DBG_proc, "pie_usb_scsi_wrapper doing MODE\n");
01277       status = pie_usb_write (fd, cmnd, src_size);
01278       break;
01279     case RESERVE_UNIT:
01280       DBG (DBG_proc, "pie_usb_scsi_wrapper doing RESERVE_UNIT\n");
01281       status = pie_usb_command (fd, cmnd);
01282       break;
01283     case RELEASE_UNIT:
01284       DBG (DBG_proc, "pie_usb_scsi_wrapper doing RELEASE_UNIT\n");
01285       status = pie_usb_command (fd, cmnd);
01286       break;
01287     case PIE_COPY:
01288       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PIE_COPY\n");
01289       status = pie_usb_read (fd, cmnd, dst, dst_size);
01290       break;
01291     case SCAN:
01292       DBG (DBG_proc, "pie_usb_scsi_wrapper doing SCAN\n");
01293       status = pie_usb_command (fd, cmnd);
01294       break;
01295     case PIE_RELEASE_SCANNER:
01296       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PIE_RELEASE_SCANNER\n");
01297       status = pie_usb_write (fd, cmnd, src_size);
01298       break;
01299     case PIE_READ_CALIBRATION:
01300       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PIE_READ_CALIBRATION\n");
01301       status = pie_usb_read (fd, cmnd, dst, dst_size);
01302       break;
01303     case PIE_WRITE_CALIBRATION:
01304       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PIE_WRITE_CALIBRATION\n");
01305       status = pie_usb_write (fd, cmnd, src_size);
01306       break;
01307     case PIE_READ_STATUS:
01308       DBG (DBG_proc, "pie_usb_scsi_wrapper doing PIE_READ_STATUS\n");
01309       status = pie_usb_read (fd, cmnd, dst, dst_size);
01310       break;
01311     default:
01312       DBG (DBG_proc, "pie_usb_scsi_wrapper failed for command 0x%02x\n",
01313            cmnd[0]);
01314       status = SANE_STATUS_INVAL;
01315       break;
01316     }
01317 
01318   return status;
01319 }
01320 
01321 /* ---------------------------- PIE_USB_REQUEST_SENSE ---------------------------- */
01341 static SANE_Status
01342 pie_usb_request_sense (int dn, uint32_t * kascq)
01343 {
01344   unsigned char buffer[16];     /* for PIE's sense */
01345   size_t size;
01346   SANE_Status status;
01347 
01348   DBG (DBG_proc, "pie_usb_request_sense\n");
01349 
01350   size = 14;
01351   set_RS_allocation_length (request_senseC, size);
01352 
01353   status =
01354     pie_usb_scsi_wrapper (dn, request_senseC, sizeof (request_senseC), buffer,
01355                           &size);
01356   if (status != SANE_STATUS_GOOD)
01357     {
01358       DBG (DBG_error, "pie_usb_request_sense failed\n");
01359       return status;
01360     }
01361   *kascq = ((int) get_RS_sense_key (buffer) << 16) +
01362     ((int) get_RS_ASC (buffer) << 8) + (int) get_RS_ASCQ (buffer);
01363   pie_sense_handler (dn, buffer, NULL);
01364 
01365   return SANE_STATUS_GOOD;
01366 }
01367 
01368 
01369 /* -------------------------- PIE_SENSE_HANDLER ---------------------------- */
01382 static SANE_Status
01383 pie_sense_handler (__sane_unused__ int scsi_fd, unsigned char *result,
01384     __sane_unused__ void *arg)
01385 {
01386   unsigned char asc, ascq, sensekey;
01387   int asc_ascq, len;
01388   /* Pie_Device *dev = arg; */
01389 
01390   DBG (DBG_proc, "check condition sense handler\n");
01391 
01392   sensekey = get_RS_sense_key (result);
01393   asc = get_RS_ASC (result);
01394   ascq = get_RS_ASCQ (result);
01395   asc_ascq = (int) (256 * asc + ascq);
01396   len = 7 + get_RS_additional_length (result);
01397 
01398   if (get_RS_error_code (result) != 0x70)
01399     {
01400       DBG (DBG_proc, "invalid sense key => handled as DEVICE BUSY!\n");
01401       return SANE_STATUS_DEVICE_BUSY;   /* sense key invalid */
01402     }
01403 
01404   DBG (DBG_sense, "check condition sense: %s\n", sense_str[sensekey]);
01405 
01406   if (get_RS_ILI (result) != 0)
01407     {
01408       DBG (DBG_sense,
01409            "-> ILI-ERROR: requested data length is larger than actual length\n");
01410     }
01411 
01412   switch (sensekey)
01413     {
01414     case 0x00:                  /* no sense, could have been busy */
01415       return SANE_STATUS_IO_ERROR;
01416       break;
01417 
01418     case 0x02:
01419       if (asc_ascq == 0x0401)
01420         DBG (DBG_sense, "-> Not Ready - Warming Up\n");
01421       else if (asc_ascq == 0x0483)
01422         DBG (DBG_sense, "-> Not Ready - Need manual service\n");
01423       else if (asc_ascq == 0x0881)
01424         DBG (DBG_sense, "-> Not Ready - Communication time out\n");
01425       else
01426         DBG (DBG_sense, "-> unknown medium error: asc=%d, ascq=%d\n", asc,
01427              ascq);
01428       break;
01429 
01430     case 0x03:                  /* medium error */
01431       if (asc_ascq == 0x5300)
01432         DBG (DBG_sense, "-> Media load or eject failure\n");
01433       else if (asc_ascq == 0x3a00)
01434         DBG (DBG_sense, "-> Media not present\n");
01435       else if (asc_ascq == 0x3b05)
01436         DBG (DBG_sense, "-> Paper jam\n");
01437       else if (asc_ascq == 0x3a80)
01438         DBG (DBG_sense, "-> ADF paper out\n");
01439       else
01440         DBG (DBG_sense, "-> unknown medium error: asc=%d, ascq=%d\n", asc,
01441              ascq);
01442       break;
01443 
01444 
01445     case 0x04:                  /* hardware error */
01446       if (asc_ascq == 0x4081)
01447         DBG (DBG_sense, "-> CPU RAM failure\n");
01448       else if (asc_ascq == 0x4082)
01449         DBG (DBG_sense, "-> Scanning system RAM failure\n");
01450       else if (asc_ascq == 0x4083)
01451         DBG (DBG_sense, "-> Image buffer failure\n");
01452       else if (asc_ascq == 0x0403)
01453         DBG (DBG_sense, "-> Manual intervention required\n");
01454       else if (asc_ascq == 0x6200)
01455         DBG (DBG_sense, "-> Scan head position error\n");
01456       else if (asc_ascq == 0x6000)
01457         DBG (DBG_sense, "-> Lamp or CCD failure\n");
01458       else if (asc_ascq == 0x6081)
01459         DBG (DBG_sense, "-> Transparency lamp failure\n");
01460       else if (asc_ascq == 0x8180)
01461         DBG (DBG_sense, "-> DC offset or black level calibration failure\n");
01462       else if (asc_ascq == 0x8181)
01463         DBG (DBG_sense,
01464              "-> Integration time adjustment failure (too light)\n");
01465       else if (asc_ascq == 0x8182)
01466         DBG (DBG_sense,
01467              "-> Integration time adjustment failure (too dark)\n");
01468       else if (asc_ascq == 0x8183)
01469         DBG (DBG_sense, "-> Shading curve adjustment failure\n");
01470       else if (asc_ascq == 0x8184)
01471         DBG (DBG_sense, "-> Gain adjustment failure\n");
01472       else if (asc_ascq == 0x8185)
01473         DBG (DBG_sense, "-> Optical alignment failure\n");
01474       else if (asc_ascq == 0x8186)
01475         DBG (DBG_sense, "-> Optical locating failure\n");
01476       else if (asc_ascq == 0x8187)
01477         DBG (DBG_sense, "-> Scan pixel map less than 5100 pixels!\n");
01478       else if (asc_ascq == 0x4700)
01479         DBG (DBG_sense, "-> Parity error on SCSI bus\n");
01480       else if (asc_ascq == 0x4b00)
01481         DBG (DBG_sense, "-> Data phase error\n");
01482       else
01483         DBG (DBG_sense, "-> unknown hardware error: asc=%d, ascq=%d\n", asc,
01484              ascq);
01485       return SANE_STATUS_IO_ERROR;
01486       break;
01487 
01488 
01489     case 0x05:                  /* illegal request */
01490       if (asc_ascq == 0x1a00)
01491         DBG (DBG_sense, "-> Parameter list length error\n");
01492       else if (asc_ascq == 0x2c01)
01493         DBG (DBG_sense, "-> Too many windows specified\n");
01494       else if (asc_ascq == 0x2c02)
01495         DBG (DBG_sense, "-> Invalid combination of windows\n");
01496       else if (asc_ascq == 0x2c81)
01497         DBG (DBG_sense, "-> Illegal scanning frame\n");
01498       else if (asc_ascq == 0x2400)
01499         DBG (DBG_sense, "-> Invalid field in CDB\n");
01500       else if (asc_ascq == 0x2481)
01501         DBG (DBG_sense, "-> Request too many lines of data\n");
01502       else if (asc_ascq == 0x2000)
01503         DBG (DBG_sense, "-> Invalid command OP code\n");
01504       else if (asc_ascq == 0x2501)
01505         DBG (DBG_sense, "-> LUN not supported\n");
01506       else if (asc_ascq == 0x2601)
01507         DBG (DBG_sense, "-> Parameter not supported\n");
01508       else if (asc_ascq == 0x2602)
01509         DBG (DBG_sense,
01510              "-> Parameter value invalid - Parameter not specified\n");
01511       else if (asc_ascq == 0x2603)
01512         DBG (DBG_sense, "-> Parameter value invalid - Invalid threshold\n");
01513       else if (asc_ascq == 0x2680)
01514         DBG (DBG_sense,
01515              "-> Parameter value invalid - Control command sequence error\n");
01516       else if (asc_ascq == 0x2681)
01517         DBG (DBG_sense,
01518              "-> Parameter value invalid - Grain setting (halftone pattern\n");
01519       else if (asc_ascq == 0x2682)
01520         DBG (DBG_sense,
01521              "-> Parameter value invalid - Illegal resolution setting\n");
01522       else if (asc_ascq == 0x2683)
01523         DBG (DBG_sense,
01524              "-> Parameter value invalid - Invalid filter assignment\n");
01525       else if (asc_ascq == 0x2684)
01526         DBG (DBG_sense,
01527              "-> Parameter value invalid - Illegal gamma adjustment setting (look-up table)\n");
01528       else if (asc_ascq == 0x2685)
01529         DBG (DBG_sense,
01530              "-> Parameter value invalid - Illegal offset setting (digital brightness)\n");
01531       else if (asc_ascq == 0x2686)
01532         DBG (DBG_sense,
01533              "-> Parameter value invalid - Illegal bits per pixel setting\n");
01534       else if (asc_ascq == 0x2687)
01535         DBG (DBG_sense,
01536              "-> Parameter value invalid - Illegal contrast setting\n");
01537       else if (asc_ascq == 0x2688)
01538         DBG (DBG_sense,
01539              "-> Parameter value invalid - Illegal paper length setting\n");
01540       else if (asc_ascq == 0x2689)
01541         DBG (DBG_sense,
01542              "-> Parameter value invalid - Illegal highlight/shadow setting\n");
01543       else if (asc_ascq == 0x268a)
01544         DBG (DBG_sense,
01545              "-> Parameter value invalid - Illegal exposure time setting (analog brightness)\n");
01546       else if (asc_ascq == 0x268b)
01547         DBG (DBG_sense,
01548              "-> Parameter value invalid - Invalid device select or device not exist\n");
01549       else if (asc_ascq == 0x268c)
01550         DBG (DBG_sense,
01551              "-> Parameter value invalid - Illegal color packing\n");
01552       else if (asc_ascq == 0x3d00)
01553         DBG (DBG_sense, "-> Invalid bits in identify field\n");
01554 
01555 
01556 
01557       else if (asc_ascq == 0x4900)
01558         DBG (DBG_sense, "-> Invalid message\n");
01559       else if (asc_ascq == 0x8101)
01560         DBG (DBG_sense, "-> Not enough memory for color packing\n");
01561 
01562       if (len >= 0x11)
01563         {
01564           if (get_RS_SKSV (result) != 0)
01565             {
01566               if (get_RS_CD (result) == 0)
01567                 {
01568 
01569                   DBG (DBG_sense, "-> illegal parameter in CDB\n");
01570                 }
01571               else
01572                 {
01573                   DBG (DBG_sense,
01574                        "-> illegal parameter is in the data parameters sent during data out phase\n");
01575                 }
01576 
01577               DBG (DBG_sense, "-> error detected in byte %d\n",
01578                    get_RS_field_pointer (result));
01579             }
01580         }
01581       return SANE_STATUS_IO_ERROR;
01582       break;
01583 
01584 
01585     case 0x06:                  /* unit attention */
01586       if (asc_ascq == 0x2900)
01587         DBG (DBG_sense, "-> power on, reset or bus device reset\n");
01588       if (asc_ascq == 0x8200)
01589         DBG (DBG_sense,
01590              "-> unit attention - calibration disable not granted\n");
01591       if (asc_ascq == 0x8300)
01592         DBG (DBG_sense, "-> unit attention - calibration will be ignored\n");
01593       else
01594         DBG (DBG_sense, "-> unit attention: asc=%d, ascq=%d\n", asc, ascq);
01595       break;
01596 
01597 
01598     case 0x09:                  /* vendor specific */
01599       DBG (DBG_sense, "-> vendor specific sense-code: asc=%d, ascq=%d\n", asc,
01600            ascq);
01601       break;
01602 
01603     case 0x0b:
01604       if (asc_ascq == 0x0006)
01605         DBG (DBG_sense, "-> Received ABORT message from initiator\n");
01606       if (asc_ascq == 0x4800)
01607         DBG (DBG_sense, "-> Initiator detected error message received\n");
01608       if (asc_ascq == 0x4300)
01609         DBG (DBG_sense, "-> Message error\n");
01610       if (asc_ascq == 0x4500)
01611         DBG (DBG_sense, "-> Select or re-select error\n");
01612       else
01613         DBG (DBG_sense, "-> aborted command: asc=%d, ascq=%d\n", asc, ascq);
01614       break;
01615 
01616     }
01617 
01618   return SANE_STATUS_IO_ERROR;
01619 }
01620 
01621 /* --------------------------- PIE_USB_READ_STATUS ---------------------------- */
01636 static SANE_Status
01637 pie_usb_read_status (int dn, unsigned char *buf)
01638 {
01639   SANE_Status status;
01640   size_t size;
01641 
01642   DBG (DBG_proc, "pie_usb_read_status\n");
01643 
01644   size = 11;
01645 
01646   status =
01647     pie_usb_scsi_wrapper (dn, read_statusC, sizeof (read_statusC), buf,
01648                           &size);
01649   return status;
01650 }
01651 
01652 
01653 /*
01654  * @@ Initialization is rather similar for SCSI and USB scanners
01655  */
01656 
01657 /* ---------------------------------- PIE INIT ---------------------------------- */
01658 
01659 static void
01660 pie_init (Pie_Device * dev, SANE_Int is_USB)    /* pie_init is called once while driver-initialization */
01661 {
01662   DBG (DBG_proc, "init\n");
01663 
01664   dev->cal_info_count = 0;
01665   dev->cal_info = NULL;
01666   dev->halftone_list[0] = NULL;
01667   dev->speed_list[0] = NULL;
01668 
01669   dev->devicename = NULL;
01670   dev->inquiry_len = 0;
01671   dev->model = NULL;
01672 
01673   if (is_USB == 0)
01674     {
01675 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
01676   DBG (DBG_info,
01677        "variable scsi buffer size (usage of sanei_scsi_open_extended)\n");
01678 #else
01679   DBG (DBG_info, "fixed scsi buffer size = %d bytes\n",
01680        sanei_scsi_max_request_size);
01681 #endif
01682       dev->scsi_cmd = sanei_scsi_cmd;
01683     }
01684   else
01685     {
01686       dev->scsi_cmd = pie_usb_scsi_wrapper;
01687     }
01688 }
01689 
01690 /* -------------------------------- PIE PRINT INQUIRY ------------------------- */
01691 
01692 static void
01693 pie_print_inquiry (Pie_Device * dev)
01694 {
01695   DBG (DBG_inquiry, "INQUIRY:\n");
01696   DBG (DBG_inquiry, "========\n");
01697   DBG (DBG_inquiry, "\n");
01698   DBG (DBG_inquiry, "vendor........................: '%s'\n", dev->vendor);
01699   DBG (DBG_inquiry, "product.......................: '%s'\n", dev->product);
01700   DBG (DBG_inquiry, "version.......................: '%s'\n", dev->version);
01701 
01702   DBG (DBG_inquiry, "X resolution..................: %d dpi\n",
01703        dev->inquiry_x_res);
01704   DBG (DBG_inquiry, "Y resolution..................: %d dpi\n",
01705        dev->inquiry_y_res);
01706   DBG (DBG_inquiry, "pixel resolution..............: %d dpi\n",
01707        dev->inquiry_pixel_resolution);
01708   DBG (DBG_inquiry, "fb width......................: %f in\n",
01709        dev->inquiry_fb_width);
01710   DBG (DBG_inquiry, "fb length.....................: %f in\n",
01711        dev->inquiry_fb_length);
01712 
01713   DBG (DBG_inquiry, "transparency width............: %f in\n",
01714        dev->inquiry_trans_width);
01715   DBG (DBG_inquiry, "transparency length...........: %f in\n",
01716        dev->inquiry_trans_length);
01717   DBG (DBG_inquiry, "transparency offset...........: %d,%d\n",
01718        dev->inquiry_trans_top_left_x, dev->inquiry_trans_top_left_y);
01719 
01720   DBG (DBG_inquiry, "# of halftones................: %d\n",
01721        dev->inquiry_halftones);
01722 
01723   DBG (DBG_inquiry, "One pass color................: %s\n",
01724        dev->inquiry_filters & INQ_ONE_PASS_COLOR ? "yes" : "no");
01725 
01726   DBG (DBG_inquiry, "Filters.......................: %s%s%s%s (%02x)\n",
01727        dev->inquiry_filters & INQ_FILTER_RED ? "Red " : "",
01728        dev->inquiry_filters & INQ_FILTER_GREEN ? "Green " : "",
01729        dev->inquiry_filters & INQ_FILTER_BLUE ? "Blue " : "",
01730        dev->inquiry_filters & INQ_FILTER_NEUTRAL ? "Neutral " : "",
01731        dev->inquiry_filters);
01732 
01733   DBG (DBG_inquiry, "Color depths..................: %s%s%s%s%s%s (%02x)\n",
01734        dev->inquiry_color_depths & INQ_COLOR_DEPTH_16 ? "16 bit " : "",
01735        dev->inquiry_color_depths & INQ_COLOR_DEPTH_12 ? "12 bit " : "",
01736        dev->inquiry_color_depths & INQ_COLOR_DEPTH_10 ? "10 bit " : "",
01737        dev->inquiry_color_depths & INQ_COLOR_DEPTH_8 ? "8 bit " : "",
01738        dev->inquiry_color_depths & INQ_COLOR_DEPTH_4 ? "4 bit " : "",
01739        dev->inquiry_color_depths & INQ_COLOR_DEPTH_1 ? "1 bit " : "",
01740        dev->inquiry_color_depths);
01741 
01742   DBG (DBG_inquiry, "Color Format..................: %s%s%s (%02x)\n",
01743        dev->inquiry_color_format & INQ_COLOR_FORMAT_INDEX ? "Indexed " : "",
01744        dev->inquiry_color_format & INQ_COLOR_FORMAT_LINE ? "Line " : "",
01745        dev->inquiry_color_format & INQ_COLOR_FORMAT_PIXEL ? "Pixel " : "",
01746        dev->inquiry_color_format);
01747 
01748   DBG (DBG_inquiry, "Image Format..................: %s%s%s%s (%02x)\n",
01749        dev->inquiry_image_format & INQ_IMG_FMT_OKLINE ? "OKLine " : "",
01750        dev->inquiry_image_format & INQ_IMG_FMT_BLK_ONE ? "BlackOne " : "",
01751        dev->inquiry_image_format & INQ_IMG_FMT_MOTOROLA ? "Motorola " : "",
01752        dev->inquiry_image_format & INQ_IMG_FMT_INTEL ? "Intel" : "",
01753        dev->inquiry_image_format);
01754 
01755   DBG (DBG_inquiry,
01756        "Scan Capability...............: %s%s%s%s%d speeds (%02x)\n",
01757        dev->inquiry_scan_capability & INQ_CAP_PWRSAV ? "PowerSave " : "",
01758        dev->inquiry_scan_capability & INQ_CAP_EXT_CAL ? "ExtCal " : "",
01759        dev->inquiry_scan_capability & INQ_CAP_FAST_PREVIEW ? "FastPreview" :
01760        "",
01761        dev->inquiry_scan_capability & INQ_CAP_DISABLE_CAL ? "DisCal " : "",
01762        dev->inquiry_scan_capability & INQ_CAP_SPEEDS,
01763        dev->inquiry_scan_capability);
01764 
01765   DBG (DBG_inquiry, "Optional Devices..............: %s%s%s%s (%02x)\n",
01766        dev->inquiry_optional_devices & INQ_OPT_DEV_MPCL ? "MultiPageLoad " :
01767        "",
01768        dev->inquiry_optional_devices & INQ_OPT_DEV_TP1 ? "TransModule1 " : "",
01769        dev->inquiry_optional_devices & INQ_OPT_DEV_TP ? "TransModule " : "",
01770        dev->inquiry_optional_devices & INQ_OPT_DEV_ADF ? "ADF " : "",
01771        dev->inquiry_optional_devices);
01772 
01773   DBG (DBG_inquiry, "Enhancement...................: %02x\n",
01774        dev->inquiry_enhancements);
01775   DBG (DBG_inquiry, "Gamma bits....................: %d\n",
01776        dev->inquiry_gamma_bits);
01777 
01778   DBG (DBG_inquiry, "Fast Preview Resolution.......: %d\n",
01779        dev->inquiry_fast_preview_res);
01780   DBG (DBG_inquiry, "Min Highlight.................: %d\n",
01781        dev->inquiry_min_highlight);
01782   DBG (DBG_inquiry, "Max Shadow....................: %d\n",
01783        dev->inquiry_max_shadow);
01784   DBG (DBG_inquiry, "Cal Eqn.......................: %d\n",
01785        dev->inquiry_cal_eqn);
01786   DBG (DBG_inquiry, "Min Exposure..................: %d\n",
01787        dev->inquiry_min_exp);
01788   DBG (DBG_inquiry, "Max Exposure..................: %d\n",
01789        dev->inquiry_max_exp);
01790 }
01791 
01792 
01793 /* ------------------------------ PIE GET INQUIRY VALUES -------------------- */
01794 
01795 
01796 static void
01797 pie_get_inquiry_values (Pie_Device * dev, unsigned char *buffer)
01798 {
01799   DBG (DBG_proc, "get_inquiry_values\n");
01800 
01801   dev->inquiry_len = get_inquiry_additional_length (buffer) + 5;
01802 
01803   dev->inquiry_x_res = get_inquiry_max_x_res (buffer);
01804   dev->inquiry_y_res = get_inquiry_max_y_res (buffer);
01805 
01806   if (dev->inquiry_y_res < 256)
01807     {
01808       /* y res is a multiplier */
01809       dev->inquiry_pixel_resolution = dev->inquiry_x_res;
01810       dev->inquiry_x_res *= dev->inquiry_y_res;
01811       dev->inquiry_y_res = dev->inquiry_x_res;
01812     }
01813   else
01814     {
01815       /* y res really is resolution */
01816       dev->inquiry_pixel_resolution =
01817         min (dev->inquiry_x_res, dev->inquiry_y_res);
01818     }
01819 
01820   dev->inquiry_fb_width =
01821     (double) get_inquiry_fb_max_scan_width (buffer) /
01822     dev->inquiry_pixel_resolution;
01823   dev->inquiry_fb_length =
01824     (double) get_inquiry_fb_max_scan_length (buffer) /
01825     dev->inquiry_pixel_resolution;
01826 
01827   dev->inquiry_trans_top_left_x = get_inquiry_trans_x1 (buffer);
01828   dev->inquiry_trans_top_left_y = get_inquiry_trans_y1 (buffer);
01829 
01830   dev->inquiry_trans_width =
01831     (double) (get_inquiry_trans_x2 (buffer) -
01832               get_inquiry_trans_x1 (buffer)) / dev->inquiry_pixel_resolution;
01833   dev->inquiry_trans_length =
01834     (double) (get_inquiry_trans_y2 (buffer) -
01835               get_inquiry_trans_y1 (buffer)) / dev->inquiry_pixel_resolution;
01836 
01837   dev->inquiry_halftones = get_inquiry_halftones (buffer) & 0x0f;
01838 
01839   dev->inquiry_filters = get_inquiry_filters (buffer);
01840   dev->inquiry_color_depths = get_inquiry_color_depths (buffer);
01841   dev->inquiry_color_format = get_inquiry_color_format (buffer);
01842   dev->inquiry_image_format = get_inquiry_image_format (buffer);
01843 
01844   dev->inquiry_scan_capability = get_inquiry_scan_capability (buffer);
01845   dev->inquiry_optional_devices = get_inquiry_optional_devices (buffer);
01846   dev->inquiry_enhancements = get_inquiry_enhancements (buffer);
01847   dev->inquiry_gamma_bits = get_inquiry_gamma_bits (buffer);
01848   dev->inquiry_fast_preview_res = get_inquiry_fast_preview_res (buffer);
01849   dev->inquiry_min_highlight = get_inquiry_min_highlight (buffer);
01850   dev->inquiry_max_shadow = get_inquiry_max_shadow (buffer);
01851   dev->inquiry_cal_eqn = get_inquiry_cal_eqn (buffer);
01852   dev->inquiry_min_exp = get_inquiry_min_exp (buffer);
01853   dev->inquiry_max_exp = get_inquiry_max_exp (buffer);
01854 
01855   pie_print_inquiry (dev);
01856 
01857   return;
01858 }
01859 
01860 /* ----------------------------- PIE DO INQUIRY ---------------------------- */
01861 
01862 
01863 static void
01864 pie_do_inquiry (Pie_Device * dev, int sfd, unsigned char *buffer)
01865 {
01866   size_t size;
01867   SANE_Status status;
01868 
01869   DBG (DBG_proc, "do_inquiry\n");
01870   memset (buffer, '\0', 256);   /* clear buffer */
01871 
01872   size = 5;
01873 
01874   set_inquiry_return_size (inquiry.cmd, size);  /* first get only 5 bytes to get size of inquiry_return_block */
01875   status = (*dev->scsi_cmd) (sfd, inquiry.cmd, inquiry.size, buffer, &size);
01876   if (status)
01877     {
01878       DBG (DBG_error, "pie_do_inquiry: command returned status %s\n",
01879            sane_strstatus (status));
01880     }
01881 
01882   size = get_inquiry_additional_length (buffer) + 5;
01883 
01884   set_inquiry_return_size (inquiry.cmd, size);  /* then get inquiry with actual size */
01885   status = (*dev->scsi_cmd) (sfd, inquiry.cmd, inquiry.size, buffer, &size);
01886   if (status)
01887     {
01888       DBG (DBG_error, "pie_do_inquiry: command returned status %s\n",
01889            sane_strstatus (status));
01890     }
01891 }
01892 
01893 /* ---------------------- PIE IDENTIFY SCANNER ---------------------- */
01894 
01895 
01896 static int
01897 pie_identify_scanner (Pie_Device * dev, int sfd, int is_USB)
01898 {
01899   char *vendor, *product, *version;
01900   char *pp;
01901   int j, i = 0;
01902   SANE_Byte usb_model_id = 0;
01903   unsigned char inquiry_block[256];
01904 
01905   DBG (DBG_proc, "identify_scanner\n");
01906 
01907   pie_do_inquiry (dev, sfd, inquiry_block);     /* get inquiry */
01908 
01909   if (get_inquiry_periph_devtype (inquiry_block) != IN_periph_devtype_scanner)
01910     {
01911       return 1;
01912     }                           /* no scanner */
01913 
01914   vendor = dup_inquiry_vendor ((char *) inquiry_block);
01915   product = dup_inquiry_product ((char *) inquiry_block);
01916   version = dup_inquiry_version ((char *) inquiry_block);
01917 
01918   pp = &vendor[8];
01919   vendor[8] = ' ';
01920   while (*pp == ' ')
01921     {
01922       *pp-- = '\0';
01923     }
01924 
01925   pp = &product[0x10];
01926   product[0x10] = ' ';
01927   while (*pp == ' ')
01928     {
01929       *pp-- = '\0';
01930     }
01931 
01932   pp = &version[4];
01933 
01934   version[4] = ' ';
01935   while (*pp == ' ')
01936     {
01937       *pp-- = '\0';
01938     }
01939 
01940   DBG (DBG_info, "Found %s scanner %s version %s on device %s\n", vendor,
01941        product, version, dev->devicename);
01942 
01943   while (strncmp ("END_OF_LIST", scanner_str[2 * i], 11) != 0)  /* Now identify full supported scanners */
01944     {
01945       if (!strncmp (vendor, scanner_str[2 * i], strlen (scanner_str[2 * i])))
01946         {
01947           if (!strncmp
01948               (product, scanner_str[2 * i + 1],
01949                strlen (scanner_str[2 * i + 1])))
01950             {
01951               /* different types of PIE USB scanners use the same USB id and inquiry name
01952                  so we need to do some subtyping here */
01953               if (is_USB)
01954                 {
01955                   for (j = 0; pie_usb_device_list[j].model != 0; j++)
01956                     {
01957                       usb_model_id = get_inquiry_model (inquiry_block);
01958                       if (pie_usb_device_list[j].model->model_id == usb_model_id)
01959                         dev->model = pie_usb_device_list[j].model;
01960                     }
01961                   if (dev->model == NULL)
01962                     continue;
01963                 }
01964 
01965               DBG (DBG_info, "found supported scanner\n");
01966 
01967               if (dev->model == NULL)
01968                 {
01969                   dev->vendor = vendor;
01970                   dev->product = product;
01971                 }
01972               else
01973                 {
01974                   free (vendor);
01975                   free (product);
01976                   dev->vendor = dev->model->vendor;
01977                   dev->product = dev->model->model;
01978                 }
01979               dev->version = version;
01980               pie_get_inquiry_values (dev, inquiry_block);
01981               return 0;
01982             }
01983         }
01984       i++;
01985     }
01986 
01987   /* A new USB model was recognized, we wish to know about it */
01988   if (usb_model_id)
01989     {
01990       DBG (DBG_info, "You have a scanner which is recognized but not yet\n");
01991       DBG (DBG_info, "supported by this backend. The model id is %d\n", usb_model_id);
01992       if (DBG_LEVEL == 197)
01993         {
01994           DBG (DBG_info, "You are now working at your own risk!!!\n");
01995           dev->model = pie_usb_device_list[0].model;
01996           free (vendor);
01997           free (product);
01998           dev->vendor = dev->model->vendor;
01999           dev->product = dev->model->model;
02000         }
02001       else
02002         {
02003           DBG (DBG_info, "Please post this output at the sane-devel list.\n");
02004           dev->vendor = vendor;
02005           dev->product = product;
02006         }
02007       dev->version = version;
02008       pie_get_inquiry_values (dev, inquiry_block);
02009       if (DBG_LEVEL == 197)
02010         return 0;
02011     }
02012   return 1;                     /* NO SUPPORTED SCANNER: short inquiry-block and unknown scanner */
02013 }
02014 
02015 
02016 /* ------------------------------- GET SPEEDS ----------------------------- */
02017 
02018 static void
02019 pie_get_speeds (Pie_Device * dev)
02020 {
02021   int speeds = dev->inquiry_scan_capability & INQ_CAP_SPEEDS;
02022 
02023   DBG (DBG_proc, "get_speeds\n");
02024 
02025   if (speeds == 3)
02026     {
02027       dev->speed_list[0] = strdup ("Normal");
02028       dev->speed_list[1] = strdup ("Fine");
02029       dev->speed_list[2] = strdup ("Pro");
02030       dev->speed_list[3] = NULL;
02031     }
02032   else
02033     {
02034       int i;
02035       char buf[2];
02036 
02037       buf[1] = '\0';
02038 
02039       for (i = 0; i < speeds; i++)
02040         {
02041           buf[0] = '1' + i;
02042           dev->speed_list[i] = strdup (buf);
02043         }
02044 
02045       dev->speed_list[i] = NULL;
02046     }
02047 }
02048 
02049 /* ------------------------------- GET HALFTONES ----------------------------- */
02050 
02051 static void
02052 pie_get_halftones (Pie_Device * dev, int sfd)
02053 {
02054   int i;
02055   size_t size;
02056   SANE_Status status;
02057   unsigned char *data;
02058   unsigned char buffer[128];
02059 
02060   DBG (DBG_proc, "get_halftones\n");
02061 
02062   for (i = 0; i < dev->inquiry_halftones; i++)
02063     {
02064       size = 6;
02065 
02066       set_write_length (swrite.cmd, size);
02067 
02068       memcpy (buffer, swrite.cmd, swrite.size);
02069 
02070       data = buffer + swrite.size;
02071       memset (data, 0, size);
02072 
02073       set_command (data, READ_HALFTONE);
02074       set_data_length (data, 2);
02075       data[4] = i;
02076 
02077       status = (*dev->scsi_cmd) (sfd, buffer, swrite.size + size, NULL, NULL);
02078       if (status)
02079         {
02080           DBG (DBG_error,
02081                "pie_get_halftones: write command returned status %s\n",
02082                sane_strstatus (status));
02083         }
02084       else
02085         {
02086           /* now read the halftone data */
02087           memset (buffer, '\0', sizeof buffer); /* clear buffer */
02088 
02089           size = 128;
02090           set_read_length (sread.cmd, size);
02091 
02092           DBG (DBG_info, "doing read\n");
02093           status =
02094             (*dev->scsi_cmd) (sfd, sread.cmd, sread.size, buffer, &size);
02095           if (status)
02096             {
02097               DBG (DBG_error,
02098                    "pie_get_halftones: read command returned status %s\n",
02099                    sane_strstatus (status));
02100             }
02101           else
02102             {
02103               unsigned char *s;
02104 
02105               s = buffer + 8 + buffer[6] * buffer[7];
02106 
02107               DBG (DBG_info, "halftone %d: %s\n", i, s);
02108 
02109               dev->halftone_list[i] = strdup ((char *) s);
02110             }
02111         }
02112     }
02113   dev->halftone_list[i] = NULL;
02114 }
02115 
02116 /* ------------------------------- GET CAL DATA ----------------------------- */
02117 
02118 static void
02119 pie_get_cal_info (Pie_Device * dev, int sfd)
02120 {
02121   size_t size;
02122   SANE_Status status;
02123   unsigned char *data;
02124   unsigned char buffer[280];
02125 
02126   DBG (DBG_proc, "get_cal_info\n");
02127 
02128   if (!(dev->inquiry_scan_capability & INQ_CAP_EXT_CAL))
02129     return;
02130 
02131   size = 6;
02132 
02133   set_write_length (swrite.cmd, size);
02134 
02135   memcpy (buffer, swrite.cmd, swrite.size);
02136 
02137   data = buffer + swrite.size;
02138   memset (data, 0, size);
02139 
02140   set_command (data, READ_CAL_INFO);
02141 
02142   status = (*dev->scsi_cmd) (sfd, buffer, swrite.size + size, NULL, NULL);
02143   if (status)
02144     {
02145       DBG (DBG_error, "pie_get_cal_info: write command returned status %s\n",
02146            sane_strstatus (status));
02147     }
02148   else
02149     {
02150       /* now read the cal data */
02151       memset (buffer, '\0', sizeof buffer);     /* clear buffer */
02152 
02153       size = 128;
02154       set_read_length (sread.cmd, size);
02155 
02156       DBG (DBG_info, "doing read\n");
02157       status = (*dev->scsi_cmd) (sfd, sread.cmd, sread.size, buffer, &size);
02158       if (status)
02159         {
02160           DBG (DBG_error,
02161                "pie_get_cal_info: read command returned status %s\n",
02162                sane_strstatus (status));
02163         }
02164       else
02165         {
02166           int i;
02167 
02168           dev->cal_info_count = buffer[4];
02169           dev->cal_info =
02170             malloc (sizeof (struct Pie_cal_info) * dev->cal_info_count);
02171 
02172           for (i = 0; i < dev->cal_info_count; i++)
02173             {
02174               dev->cal_info[i].cal_type = buffer[8 + i * buffer[5]];
02175               dev->cal_info[i].send_bits = buffer[9 + i * buffer[5]];
02176               dev->cal_info[i].receive_bits = buffer[10 + i * buffer[5]];
02177               dev->cal_info[i].num_lines = buffer[11 + i * buffer[5]];
02178               dev->cal_info[i].pixels_per_line =
02179                 (buffer[13 + i * buffer[5]] << 8) + buffer[12 +
02180                                                            i * buffer[5]];
02181 
02182               DBG (DBG_info2, "%02x %2d %2d %2d %d\n",
02183                    dev->cal_info[i].cal_type, dev->cal_info[i].send_bits,
02184                    dev->cal_info[i].receive_bits, dev->cal_info[i].num_lines,
02185                    dev->cal_info[i].pixels_per_line);
02186             }
02187         }
02188     }
02189 }
02190 
02191 
02192 /* ----------------------------- PIE_USB_ATTACH_OPEN ----------------------------- */
02205 static SANE_Status
02206 pie_usb_attach_open (SANE_String_Const devname, SANE_Int * dn)
02207 {
02208   SANE_Status status;
02209   SANE_Int vendor, product;
02210   SANE_Int model = 0;
02211   int i;
02212 
02213   DBG (DBG_proc, "pie_usb_attach_open: opening `%s'\n", devname);
02214   status = sanei_usb_open (devname, dn);
02215   if (status != SANE_STATUS_GOOD)
02216     {
02217       DBG (DBG_error, "pie_usb_attach_open: sanei_usb_open failed\n");
02218       return status;
02219     }
02220   DBG (DBG_info, "pie_usb_attach_open: USB device `%s' successfully opened\n",
02221        devname);
02222 
02223   status = sanei_usb_get_vendor_product (*dn, &vendor, &product);
02224   if (status != SANE_STATUS_GOOD)
02225     {
02226       DBG (DBG_error,
02227            "pie_usb_attach_open: couldn't get vendor and product ids of device `%s': %s\n",
02228            devname, sane_strstatus (status));
02229       return status;
02230     }
02231 
02232   for (i = 0; pie_usb_device_list[i].model != 0; i++)
02233     {
02234       if (vendor == pie_usb_device_list[i].vendor &&
02235           product == pie_usb_device_list[i].product)
02236         {
02237           model++;
02238           break;
02239         }
02240     }
02241   if (model == 0)
02242     {
02243       DBG (DBG_error,
02244            "pie_usb_attach_open: vendor 0x%04x product 0x%04x is not supported by this backend\n",
02245            vendor, product);
02246       status = SANE_STATUS_INVAL;
02247     }
02248 
02249   return status;
02250 }
02251 
02252 
02253 /* ----------------------------- PIE_USB_TRY_ATTACH ----------------------------- */
02262 static SANE_Status
02263 pie_usb_try_attach (const char *name)
02264 {
02265   sanei_usb_attach_matching_devices (name, pie_attach_one);
02266   return SANE_STATUS_GOOD;
02267 }
02268 
02269 
02270 /* ------------------------------- ATTACH SCANNER ----------------------------- */
02271 
02272 static SANE_Status
02273 pie_attach_scanner (const char *devicename, Pie_Device ** devp)
02274 {
02275   SANE_Status status;
02276   SANE_Int USB_model = 1;       /* assume USB scanner */
02277   Pie_Device *dev;
02278   int sfd;
02279   int bufsize;
02280 
02281   DBG (DBG_sane_proc, "pie_attach_scanner: %s\n", devicename);
02282 
02283   for (dev = first_dev; dev; dev = dev->next)
02284     {
02285       if (strcmp (dev->sane.name, devicename) == 0)
02286         {
02287           if (devp)
02288             {
02289               *devp = dev;
02290             }
02291           return SANE_STATUS_GOOD;
02292         }
02293     }
02294 
02295   dev = malloc (sizeof (*dev));
02296   if (!dev)
02297     {
02298       return SANE_STATUS_NO_MEM;
02299     }
02300 
02301   status = pie_usb_attach_open (devicename, &sfd);      /* try USB scanners first */
02302   if (status != SANE_STATUS_GOOD)
02303     {
02304       USB_model = 0;            /* if failed try SCSI */
02305 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
02306   bufsize = 16384;              /* 16KB */
02307 
02308   if (sanei_scsi_open_extended
02309       (devicename, &sfd, pie_sense_handler, dev, &bufsize) != 0)
02310     {
02311       DBG (DBG_error, "pie_attach_scanner: open failed\n");
02312       free (dev);
02313       return SANE_STATUS_INVAL;
02314     }
02315 
02316   if (bufsize < 4096)           /* < 4KB */
02317     {
02318       DBG (DBG_error,
02319            "pie_attach_scanner: sanei_scsi_open_extended returned too small scsi buffer (%d)\n",
02320            bufsize);
02321       sanei_scsi_close (sfd);
02322       free (dev);
02323       return SANE_STATUS_NO_MEM;
02324     }
02325   DBG (DBG_info,
02326        "pie_attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n",
02327        bufsize);
02328 #else
02329   bufsize = sanei_scsi_max_request_size;
02330 
02331   if (sanei_scsi_open (devicename, &sfd, pie_sense_handler, dev) != 0)
02332     {
02333       DBG (DBG_error, "pie_attach_scanner: open failed\n");
02334       free (dev);
02335 
02336       return SANE_STATUS_INVAL;
02337     }
02338 #endif
02339     }
02340 
02341   pie_init (dev, USB_model);    /* preset values in structure dev */
02342 
02343   dev->devicename = strdup (devicename);
02344 
02345   if (pie_identify_scanner (dev, sfd, USB_model) != 0)
02346     {
02347       DBG (DBG_error, "pie_attach_scanner: scanner-identification failed\n");
02348       if (USB_model == 0)
02349       sanei_scsi_close (sfd);
02350       else
02351         sanei_usb_close (sfd);
02352       free (dev);
02353       return SANE_STATUS_INVAL;
02354     }
02355 
02356   if (USB_model == 0)
02357     {
02358       pie_get_halftones (dev, sfd);
02359       pie_get_cal_info (dev, sfd);
02360       pie_get_speeds (dev);
02361 
02362       dev->scan_mode_list[0] = COLOR_STR;
02363       dev->scan_mode_list[1] = GRAY_STR;
02364       dev->scan_mode_list[2] = LINEART_STR;
02365       dev->scan_mode_list[3] = HALFTONE_STR;
02366       dev->scan_mode_list[4] = 0;
02367 
02368       dev->bpp_list[0] = 1;
02369       dev->bpp_list[1] = 8;
02370       dev->bpp_list[2] = 0;
02371 
02372       dev->sane.type = "flatbed scanner";
02373 
02374       sanei_scsi_close (sfd);
02375     }
02376   else
02377     {
02378       dev->scan_mode_list[0] = COLOR_STR;
02379       dev->scan_mode_list[1] = COLOR_IR_STR;
02380       dev->scan_mode_list[2] = 0;
02381 
02382       dev->sane.type = "film scanner";
02383 
02384       dev->bpp_list[0] = 2;
02385       dev->bpp_list[1] = 16;
02386       dev->bpp_list[2] = 8;
02387       dev->bpp_list[3] = 0;
02388 
02389       sanei_usb_close (sfd);
02390     }
02391 
02392   dev->ir_sw_list[0] = THE_NONE_STR;
02393   dev->ir_sw_list[1] = IR_SPECT_STR;
02394   dev->ir_sw_list[2] = IR_CLEAN_STR;
02395   dev->ir_sw_list[3] = 0;
02396 
02397   dev->grain_sw_list[0] = 4;
02398   dev->grain_sw_list[1] = 0;
02399   dev->grain_sw_list[2] = 1;
02400   dev->grain_sw_list[3] = 2;
02401   dev->grain_sw_list[4] = 3;
02402   dev->grain_sw_list[5] = 0;
02403 
02404   dev->crop_sw_list[0] = THE_NONE_STR;
02405   dev->crop_sw_list[1] = CROP_OUTER_STR;
02406   dev->crop_sw_list[2] = CROP_INNER_STR;
02407   dev->crop_sw_list[3] = 0;
02408 
02409   dev->sane.name = dev->devicename;
02410   dev->sane.vendor = dev->vendor;
02411   dev->sane.model = dev->product;
02412 
02413   dev->x_range.min = SANE_FIX (0);
02414   dev->x_range.quant = SANE_FIX (0);
02415   dev->x_range.max = SANE_FIX (dev->inquiry_fb_width * MM_PER_INCH);
02416 
02417   dev->y_range.min = SANE_FIX (0);
02418   dev->y_range.quant = SANE_FIX (0);
02419   dev->y_range.max = SANE_FIX (dev->inquiry_fb_length * MM_PER_INCH);
02420 
02421   dev->dpi_range.min = SANE_FIX (25);
02422   dev->dpi_range.quant = SANE_FIX (1);
02423   dev->dpi_range.max =
02424     SANE_FIX (max (dev->inquiry_x_res, dev->inquiry_y_res));
02425 
02426   dev->shadow_range.min = SANE_FIX (0);
02427   dev->shadow_range.quant = SANE_FIX (1);
02428   dev->shadow_range.max = SANE_FIX (dev->inquiry_max_shadow);
02429 
02430   dev->highlight_range.min = SANE_FIX (dev->inquiry_min_highlight);
02431   dev->highlight_range.quant = SANE_FIX (1);
02432   dev->highlight_range.max = SANE_FIX (100);
02433 
02434   dev->exposure_range.min = SANE_FIX (dev->inquiry_min_exp);
02435   dev->exposure_range.quant = SANE_FIX (1);
02436   dev->exposure_range.max = SANE_FIX (dev->inquiry_max_exp);
02437 
02438 #if 0
02439   dev->analog_gamma_range.min = SANE_FIX (1.0);
02440   dev->analog_gamma_range.quant = SANE_FIX (0.01);
02441   dev->analog_gamma_range.max = SANE_FIX (2.0);
02442 
02443 #endif
02444 
02445   dev->next = first_dev;
02446   first_dev = dev;
02447 
02448   if (devp)
02449     {
02450       *devp = dev;
02451     }
02452 
02453   return SANE_STATUS_GOOD;
02454 }
02455 
02456 /* --------------------------- MAX STRING SIZE ---------------------------- */
02457 
02458 
02459 static size_t
02460 max_string_size (SANE_String_Const strings[])
02461 {
02462   size_t size, max_size = 0;
02463   int i;
02464 
02465   for (i = 0; strings[i]; ++i)
02466     {
02467       size = strlen (strings[i]) + 1;
02468       if (size > max_size)
02469         {
02470           max_size = size;
02471         }
02472     }
02473 
02474   return max_size;
02475 }
02476 
02477 
02478 /* --------------------------- INIT OPTIONS ------------------------------- */
02479 
02480 
02481 static SANE_Status
02482 pie_init_options (Pie_Scanner * scanner)
02483 {
02484   int i;
02485 
02486   DBG (DBG_sane_proc, "pie_init_options\n");
02487 
02488   memset (scanner->opt, 0, sizeof (scanner->opt));
02489   memset (scanner->val, 0, sizeof (scanner->val));
02490 
02491   for (i = 0; i < NUM_OPTIONS; ++i)
02492     {
02493       scanner->opt[i].size = sizeof (SANE_Word);
02494       scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
02495     }
02496 
02497   scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
02498   scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
02499   scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
02500   scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
02501   scanner->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
02502 
02503   /* "Mode" group: */
02504   scanner->opt[OPT_MODE_GROUP].title = "Scan Mode";
02505   scanner->opt[OPT_MODE_GROUP].desc = "";
02506   scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
02507   scanner->opt[OPT_MODE_GROUP].cap = 0;
02508   scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
02509 
02510   /* scan mode */
02511   scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
02512   scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
02513   scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
02514   scanner->opt[OPT_MODE].type = SANE_TYPE_STRING;
02515   scanner->opt[OPT_MODE].size =
02516     max_string_size ((SANE_String_Const *)(void*) scanner->device->scan_mode_list);
02517   scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
02518   scanner->opt[OPT_MODE].constraint.string_list =
02519     (SANE_String_Const *)(void*) scanner->device->scan_mode_list;
02520   scanner->val[OPT_MODE].s =
02521     (SANE_Char *) strdup (scanner->device->scan_mode_list[1]);
02522 
02523   /* bit depth */
02524   scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
02525   scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
02526   scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
02527   scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
02528   scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
02529   scanner->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word);
02530   scanner->opt[OPT_BIT_DEPTH].constraint.word_list =
02531     scanner->device->bpp_list;
02532   scanner->val[OPT_BIT_DEPTH].w = scanner->device->bpp_list[1];
02533   if (scanner->opt[OPT_BIT_DEPTH].constraint.word_list[0] < 2)
02534     scanner->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
02535 
02536   /* x-resolution */
02537   scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
02538   scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
02539   scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
02540   scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED;
02541   scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
02542   scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
02543   scanner->opt[OPT_RESOLUTION].constraint.range = &scanner->device->dpi_range;
02544   scanner->val[OPT_RESOLUTION].w = 1200 << SANE_FIXED_SCALE_SHIFT;
02545 
02546   /* "Geometry" group: */
02547 
02548   scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
02549   scanner->opt[OPT_GEOMETRY_GROUP].desc = "";
02550   scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
02551   scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
02552   scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
02553 
02554   /* top-left x */
02555   scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
02556   scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
02557   scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
02558   scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
02559   scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM;
02560   scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
02561   scanner->opt[OPT_TL_X].constraint.range = &(scanner->device->x_range);
02562   scanner->val[OPT_TL_X].w = 0;
02563 
02564   /* top-left y */
02565   scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
02566   scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
02567   scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
02568   scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
02569   scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
02570   scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
02571   scanner->opt[OPT_TL_Y].constraint.range = &(scanner->device->y_range);
02572   scanner->val[OPT_TL_Y].w = 0;
02573 
02574   /* bottom-right x */
02575   scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
02576   scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
02577   scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
02578   scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
02579   scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM;
02580   scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
02581   scanner->opt[OPT_BR_X].constraint.range = &(scanner->device->x_range);
02582   scanner->val[OPT_BR_X].w = scanner->device->x_range.max;
02583 
02584   /* bottom-right y */
02585   scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
02586   scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
02587   scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
02588   scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
02589   scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
02590   scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
02591   scanner->opt[OPT_BR_Y].constraint.range = &(scanner->device->y_range);
02592   scanner->val[OPT_BR_Y].w = scanner->device->y_range.max;
02593 
02594   /* "enhancement" group: */
02595 
02596   scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
02597   scanner->opt[OPT_ENHANCEMENT_GROUP].desc = "";
02598   scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
02599   scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
02600   scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
02601 
02602   /* reduce spectal overlap from infrared plane */
02603   scanner->opt[OPT_SW_IRED].name = IR_NAME_STR;
02604   scanner->opt[OPT_SW_IRED].title = IR_TITLE_STR;
02605   scanner->opt[OPT_SW_IRED].desc = IR_DESC_STR;
02606   scanner->opt[OPT_SW_IRED].type = SANE_TYPE_STRING;
02607   scanner->opt[OPT_SW_IRED].size =
02608     max_string_size ((SANE_String_Const *)(void*) scanner->device->ir_sw_list);
02609   scanner->opt[OPT_SW_IRED].constraint_type = SANE_CONSTRAINT_STRING_LIST;
02610   scanner->opt[OPT_SW_IRED].constraint.string_list =
02611     (SANE_String_Const *)(void*) scanner->device->ir_sw_list;
02612   scanner->val[OPT_SW_IRED].s =
02613     (SANE_Char *) strdup (scanner->device->ir_sw_list[2]);
02614 
02615   /* strength of grain filtering */
02616   scanner->opt[OPT_SW_GRAIN].name = "swgrain";
02617   scanner->opt[OPT_SW_GRAIN].title = "Attenuate film grain";
02618   scanner->opt[OPT_SW_GRAIN].desc = "Amount of smothening";
02619   scanner->opt[OPT_SW_GRAIN].type = SANE_TYPE_INT;
02620   scanner->opt[OPT_SW_GRAIN].constraint_type = SANE_CONSTRAINT_WORD_LIST;
02621   scanner->opt[OPT_SW_GRAIN].size = sizeof (SANE_Word);
02622   scanner->opt[OPT_SW_GRAIN].constraint.word_list =
02623     scanner->device->grain_sw_list;
02624   scanner->val[OPT_SW_GRAIN].w = scanner->device->grain_sw_list[1];
02625   if (scanner->opt[OPT_SW_GRAIN].constraint.word_list[0] < 2)
02626     scanner->opt[OPT_SW_GRAIN].cap |= SANE_CAP_INACTIVE;
02627 
02628   /* gamma correction, to make image sRGB like */
02629   scanner->opt[OPT_SW_SRGB].name = "swsrgb";
02630   scanner->opt[OPT_SW_SRGB].title = "sRGB colors";
02631   scanner->opt[OPT_SW_SRGB].desc = "Transform image to approximate sRGB color space";
02632   scanner->opt[OPT_SW_SRGB].type = SANE_TYPE_BOOL;
02633   scanner->opt[OPT_SW_SRGB].unit = SANE_UNIT_NONE;
02634   scanner->val[OPT_SW_SRGB].w = SANE_TRUE;
02635 
02636   /* color correction for generic negative film */
02637   scanner->opt[OPT_SW_NEGA].name = "swnega";
02638   scanner->opt[OPT_SW_NEGA].title = "Invert colors";
02639   scanner->opt[OPT_SW_NEGA].desc = "Correct for generic negative film";
02640   scanner->opt[OPT_SW_NEGA].type = SANE_TYPE_BOOL;
02641   scanner->opt[OPT_SW_NEGA].unit = SANE_UNIT_NONE;
02642 
02643   /* crop image */
02644   scanner->opt[OPT_SW_CROP].name = CROP_NAME_STR;
02645   scanner->opt[OPT_SW_CROP].title = CROP_TITLE_STR;
02646   scanner->opt[OPT_SW_CROP].desc = CROP_DESC_STR;
02647   scanner->opt[OPT_SW_CROP].type = SANE_TYPE_STRING;
02648   scanner->opt[OPT_SW_CROP].size =
02649     max_string_size ((SANE_String_Const *)(void*) scanner->device->crop_sw_list);
02650   scanner->opt[OPT_SW_CROP].constraint_type = SANE_CONSTRAINT_STRING_LIST;
02651   scanner->opt[OPT_SW_CROP].constraint.string_list =
02652     (SANE_String_Const *)(void*) scanner->device->crop_sw_list;
02653   scanner->val[OPT_SW_CROP].s =
02654     (SANE_Char *) strdup (scanner->device->crop_sw_list[2]);
02655 
02656 /* grayscale gamma vector */
02657   scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
02658   scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
02659   scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
02660   scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
02661   scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
02662   scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
02663   scanner->val[OPT_GAMMA_VECTOR].wa = scanner->gamma_table[0];
02664   scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &scanner->gamma_range;
02665   scanner->opt[OPT_GAMMA_VECTOR].size =
02666     scanner->gamma_length * sizeof (SANE_Word);
02667   scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
02668 
02669   /* red gamma vector */
02670   scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
02671   scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
02672   scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
02673   scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
02674   scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
02675   scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
02676   scanner->val[OPT_GAMMA_VECTOR_R].wa = scanner->gamma_table[1];
02677   scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(scanner->gamma_range);
02678   scanner->opt[OPT_GAMMA_VECTOR_R].size =
02679     scanner->gamma_length * sizeof (SANE_Word);
02680 
02681   /* green gamma vector */
02682   scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
02683   scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
02684   scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
02685   scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
02686   scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
02687   scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
02688   scanner->val[OPT_GAMMA_VECTOR_G].wa = scanner->gamma_table[2];
02689   scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(scanner->gamma_range);
02690   scanner->opt[OPT_GAMMA_VECTOR_G].size =
02691     scanner->gamma_length * sizeof (SANE_Word);
02692 
02693 
02694   /* blue gamma vector */
02695   scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
02696   scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
02697   scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
02698   scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
02699   scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
02700   scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
02701   scanner->val[OPT_GAMMA_VECTOR_B].wa = scanner->gamma_table[3];
02702   scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(scanner->gamma_range);
02703   scanner->opt[OPT_GAMMA_VECTOR_B].size =
02704     scanner->gamma_length * sizeof (SANE_Word);
02705 
02706   if (scanner->device->model != NULL)
02707     {
02708       scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
02709       scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
02710       scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
02711       scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
02712     }
02713   else
02714     {
02715       scanner->opt[OPT_SW_SRGB].cap |= SANE_CAP_INACTIVE;
02716       scanner->opt[OPT_SW_NEGA].cap |= SANE_CAP_INACTIVE;
02717       scanner->opt[OPT_SW_IRED].cap |= SANE_CAP_INACTIVE;
02718       scanner->opt[OPT_SW_CROP].cap |= SANE_CAP_INACTIVE;
02719       scanner->opt[OPT_SW_GRAIN].cap |= SANE_CAP_INACTIVE;
02720     }
02721 
02722   /* halftone pattern */
02723   scanner->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
02724   scanner->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
02725   scanner->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
02726   scanner->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
02727   scanner->opt[OPT_HALFTONE_PATTERN].size =
02728     max_string_size ((SANE_String_Const *)(void*) scanner->device->halftone_list);
02729   scanner->opt[OPT_HALFTONE_PATTERN].constraint_type =
02730     SANE_CONSTRAINT_STRING_LIST;
02731   scanner->opt[OPT_HALFTONE_PATTERN].constraint.string_list =
02732     (SANE_String_Const *)(void*) scanner->device->halftone_list;
02733   scanner->val[OPT_HALFTONE_PATTERN].s =
02734     (SANE_Char *) strdup (scanner->device->halftone_list[0]);
02735   scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
02736 
02737   /* speed */
02738   scanner->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED;
02739   scanner->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED;
02740   scanner->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED;
02741   scanner->opt[OPT_SPEED].type = SANE_TYPE_STRING;
02742   scanner->opt[OPT_SPEED].size =
02743     max_string_size ((SANE_String_Const *)(void*) scanner->device->speed_list);
02744   scanner->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST;
02745   scanner->opt[OPT_SPEED].constraint.string_list =
02746     (SANE_String_Const *)(void*) scanner->device->speed_list;
02747   scanner->val[OPT_SPEED].s =
02748     (SANE_Char *) strdup (scanner->device->speed_list[1]);
02749 
02750   /* lineart threshold */
02751   scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
02752   scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
02753   scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
02754   scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
02755   scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
02756   scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
02757   scanner->opt[OPT_THRESHOLD].constraint.range = &percentage_range_100;
02758   scanner->val[OPT_THRESHOLD].w = SANE_FIX (50);
02759   scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
02760 
02761   /* "advanced" group: */
02762 
02763   scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced";
02764   scanner->opt[OPT_ADVANCED_GROUP].desc = "";
02765   scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
02766   scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
02767   scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
02768 
02769   /* preview */
02770   scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
02771   scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
02772   scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
02773   scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
02774   scanner->val[OPT_PREVIEW].w = SANE_FALSE;
02775 
02776 
02777 
02778   return SANE_STATUS_GOOD;
02779 }
02780 
02781 /*
02782  * @@ Mid level USB functions
02783  */
02784 
02785 /* ---------------------------- PIE_USB_WAIT_SCANNER ----------------------------- */
02799 static SANE_Status
02800 pie_usb_wait_scanner (Pie_Scanner * scanner, int secs)
02801 {
02802   SANE_Status status;
02803   int cnt = secs * 16;
02804 
02805   DBG (DBG_proc, "pie_usb_wait_scanner\n");
02806 
02807   do
02808     {
02809       status = pie_usb_scsi_wrapper (scanner->sfd, test_unit_ready.cmd,
02810                                      test_unit_ready.size, NULL, NULL);
02811       if (status == SANE_STATUS_GOOD)
02812         return status;
02813       if (cnt == 0)
02814         {
02815           DBG (DBG_warning, "pie_usb_wait_scanner timed out\n");
02816           return status;
02817         }
02818       usleep (62500);
02819       cnt--;
02820 
02821     }
02822   while (status == SANE_STATUS_DEVICE_BUSY);
02823 
02824   DBG (DBG_error,
02825        "pie_usb_wait_scanner failed: %s\n", sane_strstatus (status));
02826   return status;
02827 }
02828 
02829 
02830 /* -------------------------- PIE_USB_RELEASE_SCANNER ---------------------------- */
02851 static int
02852 pie_usb_release_scanner (void * passed)
02853 {
02854   unsigned char buffer[16];
02855   unsigned char *data;
02856   SANE_Status status;
02857   size_t size = release_scanC[4];
02858   Pie_Scanner * scanner;
02859   int cnt = 0;
02860 
02861   DBG (DBG_proc, "pie_usb_release_scanner\n");
02862 
02863   scanner = (Pie_Scanner *) passed;
02864 
02865   /* wait upto 15 secs */
02866   status = pie_usb_wait_scanner (scanner, 15);
02867   if (status != SANE_STATUS_GOOD)
02868     return status;
02869 
02870   /* prepare to issue vendor specific 0xd2 command */
02871   memcpy (buffer, release_scanC, sizeof (release_scanC));
02872   data = buffer + sizeof (release_scanC);
02873   memset (data, 0, size);
02874   data[0] = 2;
02875   size += sizeof (release_scanC);
02876 
02877   /* try command for maximally 20 * 0.5 = 10 sec */
02878   do
02879     {
02880       status = pie_usb_scsi_wrapper (scanner->sfd, buffer, size, NULL, NULL);
02881 
02882       if (status != SANE_STATUS_DEVICE_BUSY)
02883         break;
02884 
02885       if (cnt == 1)
02886         DBG (DBG_info2,
02887              "pie_usb_release_scanner: scanner reports %s, waiting ...\n",
02888              sane_strstatus (status));
02889 
02890       usleep (TUR_WAIT_TIME);
02891       cnt++;
02892     }
02893   while (cnt < 20);
02894 
02895   if (status != SANE_STATUS_GOOD)
02896     return status;
02897 
02898   pie_power_save (scanner, 15);
02899 
02900   return status;
02901 }
02902 
02903 /* ---------------------- PIE_USB_IS_SCANNER_RELEASED ------------------------- */
02913 static SANE_Status
02914 pie_usb_is_scanner_released (Pie_Scanner * scanner)
02915 {
02916   SANE_Status status = SANE_STATUS_DEVICE_BUSY;
02917   int cnt = 0;
02918 
02919   DBG (DBG_proc, "pie_usb_is_scanner_released: pid %d\n",
02920       (int) scanner->parking_pid);
02921 
02922   if (scanner->parking_pid == NO_PID)
02923     return SANE_STATUS_GOOD;
02924   else
02925     do
02926       {
02927         status = sanei_thread_get_status (scanner->parking_pid);
02928         if (status == SANE_STATUS_GOOD)
02929           break;
02930 
02931         if (cnt == 1)
02932           DBG (DBG_info2, "pie_usb_is_scanner_released: waiting ...\n");
02933 
02934         cnt++;
02935         usleep (TUR_WAIT_TIME);
02936       }
02937     while (cnt < 20);
02938 
02939   if (status == SANE_STATUS_GOOD)
02940     {
02941       scanner->parking_pid = NO_PID;
02942       DBG (DBG_proc, "pie_usb_is_scanner_released: success\n");
02943       return status;
02944     }
02945   else
02946     return SANE_STATUS_IO_ERROR;
02947 }
02948 
02949 
02950 /* --------------------- PIE_USB_IS_SCANNER_INITIALZED ----------------------- */
02968 static SANE_Status
02969 pie_usb_is_scanner_initialized (int dn)
02970 {
02971   unsigned char buffer[16];
02972   SANE_Status status, state;
02973   uint32_t sense_kascq;
02974   int wait_cnt = 240;           /* 240 * 0.5 = 120 seconds */
02975   DBG (DBG_proc, "pie_usb_is_scanner_initialized\n");
02976   do
02977     {
02978       status =
02979         pie_usb_scsi_wrapper (dn, test_unit_ready.cmd,
02980                               test_unit_ready.size, NULL, NULL);
02981       if (status == SANE_STATUS_IO_ERROR)       /* Not Ready - Warming Up ? */
02982         {
02983           state = pie_usb_request_sense (dn, &sense_kascq);
02984           if (state != SANE_STATUS_GOOD)
02985             return state;
02986           if (sense_kascq != 0x020401)
02987             return status;
02988           else
02989             status = SANE_STATUS_DEVICE_BUSY;
02990         }
02991 
02992       if (status == SANE_STATUS_DEVICE_BUSY)
02993         {
02994           usleep (TUR_WAIT_TIME);
02995           wait_cnt--;
02996         }
02997 
02998       memset (buffer, 0, 11);
02999       status = pie_usb_read_status (dn, buffer);
03000       if (status == SANE_STATUS_IO_ERROR)       /* Not Ready - Warming Up ? */
03001         {
03002           state = pie_usb_request_sense (dn, &sense_kascq);
03003           if (state != SANE_STATUS_GOOD)
03004             return state;
03005           if (sense_kascq != 0x020401)
03006             return status;
03007           else
03008             status = SANE_STATUS_DEVICE_BUSY;
03009         }
03010 
03011       if (status == SANE_STATUS_GOOD)
03012         {
03013           DBG_DUMP (DBG_info, buffer, 11);
03014 /*        if ((buffer[5] != 0) || (buffer[9] != 0) || (buffer[10] != 0))*/
03015           if (buffer[5] != 0)
03016             status = SANE_STATUS_DEVICE_BUSY;
03017         }
03018 
03019       if (status == SANE_STATUS_DEVICE_BUSY)
03020         {
03021           usleep (TUR_WAIT_TIME);
03022           wait_cnt--;
03023         }
03024     }
03025   while ((status == SANE_STATUS_DEVICE_BUSY) && (wait_cnt > 0));
03026   return status;
03027 }
03028 
03029 
03030 /* -------------------------- PIE_USB_COPY_SENSORS ---------------------------- */
03049 static SANE_Status
03050 pie_usb_copy_sensors (Pie_Scanner * scanner)
03051 {
03052   size_t size_read;
03053   int cnt = 0;
03054   SANE_Status status;
03055 
03056   DBG (DBG_proc, "pie_usb_copy_sensors\n");
03057 
03058   do
03059     {
03060       size_read = scanner->device->cal_info[0].pixels_per_line;
03061       status =
03062         pie_usb_scsi_wrapper (scanner->sfd, pie_copyC, sizeof (pie_copyC),
03063                               scanner->cal_data->sensors, &size_read);
03064       if (status == SANE_STATUS_GOOD)
03065         return status;
03066 
03067       if (cnt == 1)
03068         DBG (DBG_info2,
03069              "pie_usb_copy_sensors: scanner reports %s, waiting ...\n",
03070              sane_strstatus (status));
03071 
03072       usleep (TUR_WAIT_TIME);
03073       cnt++;
03074     }
03075   while (cnt < 10);             /* maximally 10 * 0.5 = 5 sec */
03076 
03077   return status;
03078 }
03079 
03080 /* ------------------------------ PIE_USB_SCAN -------------------------------- */
03097 static SANE_Status
03098 pie_usb_scan (Pie_Scanner * scanner, int start)
03099 {
03100   SANE_Status status, state;
03101   uint32_t sense_kascq;
03102 
03103   DBG (DBG_proc, "pie_usb_scan: %d\n", start);
03104 
03105   set_scan_cmd (scan.cmd, start);
03106   if (start)
03107     {
03108       /* wait upto X seconds until returned to start position */
03109       status = pie_usb_wait_scanner (scanner, 15);
03110       if (status != SANE_STATUS_GOOD)
03111         return status;
03112       do
03113         {
03114           status =
03115             pie_usb_scsi_wrapper (scanner->sfd, scan.cmd, scan.size,
03116                                   NULL, NULL);
03117           if (status)
03118             {
03119               DBG (DBG_error, "pie_usb_scan: received %s\n",
03120                    sane_strstatus (status));
03121               if (status == SANE_STATUS_IO_ERROR)
03122                 {
03123                   state = pie_usb_request_sense (scanner->sfd, &sense_kascq);
03124                   if (state != SANE_STATUS_GOOD)
03125                     return state;
03126                   if (sense_kascq == 0x020401)  /* Not Ready - Warming Up */
03127                     status = SANE_STATUS_DEVICE_BUSY;
03128                   else if (sense_kascq == 0x068200)     /* calibration disable not granted */
03129                     status = SANE_STATUS_GOOD;
03130                 }
03131               if (status == SANE_STATUS_DEVICE_BUSY)
03132                 usleep (SCAN_WARMUP_WAIT_TIME);
03133             }
03134         }
03135       while (status == SANE_STATUS_DEVICE_BUSY);
03136       return status;
03137     }
03138   else
03139     {
03140       status =
03141         pie_usb_scsi_wrapper (scanner->sfd, scan.cmd, scan.size, NULL, NULL);
03142       if (status == SANE_STATUS_IO_ERROR)
03143         {
03144           state = pie_usb_request_sense (scanner->sfd, &sense_kascq);
03145           if (state != SANE_STATUS_GOOD)
03146             return state;
03147           if (sense_kascq != 0x0b0006)  /* ABORT message from initiator */
03148             return status;
03149         }
03150       return SANE_STATUS_GOOD;
03151     }
03152 }
03153 
03154 
03155 /*----------------------- PIE_USB_SET_WINDOW --------------------------- */
03169 static SANE_Status
03170 pie_usb_set_window (Pie_Scanner * scanner)
03171 {
03172   unsigned char buffer[128];
03173   size_t size;
03174   SANE_Status status;
03175   unsigned char *data;
03176   double x, dpmm;
03177 
03178   DBG (DBG_proc, "pie_usb_set_window\n");
03179 
03180   size = 14;
03181   set_write_length (swrite.cmd, size);
03182   memcpy (buffer, swrite.cmd, swrite.size);
03183   data = buffer + swrite.size;
03184   memset (data, 0, size);
03185   set_command (data, SET_SCAN_FRAME);
03186   set_data_length (data, size - 4);
03187 
03188   data[4] = 0x80;
03189 
03190   dpmm = (double) scanner->device->inquiry_pixel_resolution / MM_PER_INCH;
03191 
03192   if (scanner->device->model->flags & PIE_USB_FLAG_MIRROR_IMAGE)
03193     {
03194       x =
03195         SANE_UNFIX (scanner->device->x_range.max -
03196                     scanner->val[OPT_BR_X].w) * dpmm;
03197       set_data (data, 6, (int) x, 2);
03198       DBG (DBG_info, "TL_X: %d\n", (int) x);
03199 
03200       x =
03201         SANE_UNFIX (scanner->device->x_range.max -
03202                     scanner->val[OPT_TL_X].w) * dpmm;
03203       set_data (data, 10, (int) x, 2);
03204       DBG (DBG_info, "BR_X: %d\n", (int) x);
03205     }
03206   else
03207     {
03208       x = SANE_UNFIX (scanner->val[OPT_TL_X].w) * dpmm;
03209       set_data (data, 6, (int) x, 2);
03210       DBG (DBG_info, "TL_X: %d\n", (int) x);
03211 
03212       x = SANE_UNFIX (scanner->val[OPT_BR_X].w) * dpmm;
03213       set_data (data, 10, (int) x, 2);
03214       DBG (DBG_info, "BR_X: %d\n", (int) x);
03215     }
03216   x = SANE_UNFIX (scanner->val[OPT_TL_Y].w) * dpmm;
03217   set_data (data, 8, (int) x, 2);
03218   DBG (DBG_info, "TL_Y: %d\n", (int) x);
03219 
03220   x = SANE_UNFIX (scanner->val[OPT_BR_Y].w) * dpmm;
03221   set_data (data, 12, (int) x, 2);
03222   DBG (DBG_info, "BR_Y: %d\n", (int) x);
03223 
03224   status =
03225     pie_usb_scsi_wrapper (scanner->sfd, buffer, swrite.size + size, NULL,
03226                           NULL);
03227   if (status)
03228     {
03229       DBG (DBG_error,
03230            "pie_usb_set_window: write command returned status %s\n",
03231            sane_strstatus (status));
03232     }
03233 
03234   return status;
03235 }
03236 
03237 
03238 /*-------------------------- PIE_USB_MODE_SELECT ------------------------------- */
03255 static SANE_Status
03256 pie_usb_mode_select (Pie_Scanner * scanner)
03257 {
03258   PIE_USB_Model *model = scanner->device->model;
03259   SANE_Status status;
03260   unsigned char buffer[128];
03261   size_t size;
03262   unsigned char *data;
03263   int i, cal;
03264 
03265   DBG (DBG_proc, "pie_usb_mode_select\n");
03266 
03267   size = 16;
03268   set_mode_length (smode.cmd, size);
03269   memcpy (buffer, smode.cmd, smode.size);
03270   data = buffer + smode.size;
03271   memset (data, 0, size);
03272   /* size of data */
03273   data[1] = size - 2;
03274   /* set resolution required */
03275   set_data (data, 2, scanner->resolution, 2);
03276   /* set color filter and color depth */
03277   data[4] = 0;
03278   scanner->cal_filter = 0;
03279   switch (scanner->colormode)
03280     {
03281     case RGBI:
03282       data[4] = INQ_FILTER_IRED;
03283       scanner->cal_filter = INQ_FILTER_IRED;    /* fall through */
03284     case RGB:
03285       if (scanner->device->inquiry_filters & INQ_ONE_PASS_COLOR)
03286         {
03287           data[4] |= INQ_ONE_PASS_COLOR;
03288           scanner->cal_filter |= FILTER_RED | FILTER_GREEN | FILTER_BLUE;
03289         }
03290       else
03291         {
03292           DBG (DBG_error,
03293                "pie_usb_mode_select: support for multipass color not yet implemented\n");
03294           return SANE_STATUS_UNSUPPORTED;
03295         }
03296       if (scanner->val[OPT_BIT_DEPTH].w == 16)
03297         data[5] = INQ_COLOR_DEPTH_16;
03298       else
03299         data[5] = INQ_COLOR_DEPTH_8;
03300       break;
03301     default:
03302       DBG (DBG_error, "pie_usb_mode_select: wrong colour format!\n");
03303       return SANE_STATUS_UNSUPPORTED;
03304     }
03305 
03306   /* choose color packing method */
03307   if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX)
03308     data[6] = INQ_COLOR_FORMAT_INDEX;
03309 #if 0
03310   /* possible TODO: The scanner can do INQ_COLOR_FORMAT_LINE but our
03311    * reader routine for it has been neglected */
03312   else if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_LINE)
03313     data[6] = INQ_COLOR_FORMAT_LINE;
03314 #endif
03315   else
03316     {
03317       DBG (DBG_error,
03318            "pie_usb_mode_select: support for pixel packing not yet implemented\n");
03319       return SANE_STATUS_UNSUPPORTED;
03320     }
03321 
03322   /* choose data format */
03323   if (scanner->device->inquiry_image_format & INQ_IMG_FMT_INTEL)
03324     data[8] = INQ_IMG_FMT_INTEL;
03325   else
03326     {
03327       DBG (DBG_error,
03328            "pie_usb_mode_select: support for Motorola format not yet implemented\n");
03329       return SANE_STATUS_UNSUPPORTED;
03330     }
03331 
03332   /* set required calibration and quality */
03333   i = 0;
03334   while (scanner->device->speed_list[i] != NULL)
03335     {
03336       if (strcmp
03337           (scanner->device->speed_list[i], scanner->val[OPT_SPEED].s) == 0)
03338         break;
03339       i++;
03340     }
03341 
03342   if (scanner->device->speed_list[i] == NULL)
03343     i = 0;                      /* neither should happen */
03344   if (i > 2)
03345     i = 2;
03346   cal = i;
03347   if (cal == 1)
03348     {
03349       if (scanner->val[OPT_PREVIEW].w == SANE_TRUE)
03350         cal = model->op_mode[OPM_PREVIEW];      /*CAL_MODE_FILM_NORMAL; */
03351       else
03352         cal = model->op_mode[OPM_QUALITY];      /*CAL_MODE_FILM_HIQUAL; */
03353     }
03354   /* skip calibration if no quality in this or last scan */
03355   if ((cal != model->op_mode[OPM_QUALITY]) &&
03356       (scanner->cal_mode != model->op_mode[OPM_QUALITY]))
03357     cal = model->op_mode[OPM_SKIPCAL];
03358   data[9] = cal;
03359   scanner->cal_mode = cal;
03360 
03361   /* unsupported for USB film scanners: halftone, threshold */
03362   /* 12: halftone pattern 0 */
03363   data[13] = 0x80;              /* lineart threshold */
03364   data[14] = 0x10;              /* ?? */
03365 
03366   DBG (DBG_info, "pie_usb_mode_select: speed %02x\n", data[9]);
03367   DBG (DBG_info, "pie_usb_mode_select sending:\n");
03368   DBG_DUMP (DBG_info, data, size);
03369   status =
03370     pie_usb_scsi_wrapper (scanner->sfd, buffer, smode.size + size,
03371                           NULL, NULL);
03372   if (status)
03373     {
03374       DBG (DBG_error,
03375            "pie_usb_mode_select: write command returned status %s\n",
03376            sane_strstatus (status));
03377     }
03378 
03379   return status;
03380 }
03381 
03382 
03383 /* ------------------------------------ PIE_USB_GET_PARAMS ------------------------ */
03400 static SANE_Status
03401 pie_usb_get_params (Pie_Scanner * scanner)
03402 {
03403   unsigned char buffer[128];
03404   SANE_Status status;
03405   size_t size = 18;
03406 
03407   DBG (DBG_proc, "pie_usb_get_params\n");
03408 
03409   status = pie_usb_wait_scanner (scanner, 5);
03410   if (status)
03411     return status;
03412 
03413   set_param_length (param.cmd, size);
03414 
03415   status =
03416     pie_usb_scsi_wrapper (scanner->sfd, param.cmd, param.size, buffer, &size);
03417   if (status)
03418     {
03419       DBG (DBG_error, "pie_usb_get_params: command returned status %s\n",
03420            sane_strstatus (status));
03421     }
03422   else
03423     {
03424       DBG (DBG_info, "Scan Width:  %d\n", get_param_scan_width (buffer));
03425       DBG (DBG_info, "Scan Lines:  %d\n", get_param_scan_lines (buffer));
03426       DBG (DBG_info, "Scan bytes:  %d\n", get_param_scan_bytes (buffer));
03427 
03428       DBG (DBG_info, "Offset 1:    %d\n",
03429            get_param_scan_filter_offset1 (buffer));
03430       DBG (DBG_info, "Offset 2:    %d\n",
03431            get_param_scan_filter_offset2 (buffer));
03432       DBG (DBG_info, "Scan period: %d\n", get_param_scan_period (buffer));
03433       DBG (DBG_info, "Xfer rate:   %d\n", get_param_scsi_xfer_rate (buffer));
03434       DBG (DBG_info, "Avail lines: %d\n",
03435            get_param_scan_available_lines (buffer));
03436 
03437       scanner->filter_offset1 = get_param_scan_filter_offset1 (buffer);
03438       scanner->filter_offset2 = get_param_scan_filter_offset2 (buffer);
03439       scanner->bytes_per_line = get_param_scan_bytes (buffer);
03440 
03441       scanner->params.pixels_per_line = get_param_scan_width (buffer);
03442       scanner->params.lines = get_param_scan_lines (buffer);
03443 
03444       if (scanner->colormode == RGBI)
03445         {
03446 #ifdef SANE_FRAME_RGBI
03447           scanner->params.format = SANE_FRAME_RGBI;
03448           scanner->params.bytes_per_line = 4 * get_param_scan_bytes (buffer);
03449 #else
03450           scanner->params.format = SANE_FRAME_RGB;
03451           scanner->params.bytes_per_line = 3 * get_param_scan_bytes (buffer);
03452 #endif
03453           scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w;
03454         }
03455       else if ((scanner->colormode == RGB) || (scanner->processing & POST_SW_DIRT))
03456         {
03457           scanner->params.format = SANE_FRAME_RGB;
03458           scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w;
03459           scanner->params.bytes_per_line = 3 * get_param_scan_bytes (buffer);
03460         }
03461       else
03462         {
03463           DBG (DBG_error, "pie_usb_get_params: wrong colour format!\n");
03464           return SANE_STATUS_UNSUPPORTED;
03465         }
03466       scanner->params.last_frame = 0;
03467     }
03468   return status;
03469 }
03470 
03471 /*
03472  * @@ USB calibration functions
03473  */
03474 
03475 /* ------------------------ PIE_USB_CALICALC_HIQUAL ---------------------------- */
03491 static void
03492 pie_usb_calicalc_hiqual (Pie_Scanner * scanner,
03493                          PIE_USB_Calibration_Read * d7cal)
03494 {
03495   PIE_USB_Model *model = scanner->device->model;
03496   PIE_USB_Calibration *caldat = scanner->cal_data;
03497   double fact, dgain;
03498   int i, tg, tt, tmax;
03499 
03500   SANE_Status status;
03501   int brightnesses[3];
03502   int pokebuf[4];
03503   int pokesiz = 3;
03504 
03505   DBG (DBG_proc, "pie_usb_calicalc_hiqual\n");
03506 
03507   for (i = 0; i < 3; i++)
03508     brightnesses[i] = caldat->brightness[i];
03509   status = pie_usb_poke_ints ("/tmp/bright.txt", pokebuf, &pokesiz);
03510   if (status == SANE_STATUS_GOOD && pokesiz)
03511     {
03512       for (i = 0; i < 3; i++)
03513         brightnesses[i] = pokebuf[i];
03514       DBG (DBG_info,
03515            "pie_usb_calicalc_hiqual poked brightness %d, %d, %d\n",
03516            brightnesses[0], brightnesses[1], brightnesses[2]);
03517     }
03518 
03519   tmax = 0;
03520   for (i = 0; i < 3; i++)
03521     {
03522       /* overall illumination correction factor
03523          fact = I / I0 = exp (c * (g^2 - g0^2)) * t / t0 */
03524       fact = (double) brightnesses[i] / (double) caldat->mean_shade[i];
03525       /* calculate gain from f^(1/p) = exp (c * (g^2 - g0^2)), the part done by gain */
03526       dgain =
03527         log (fact) / (model->gain_const[i] *
03528                       (double) model->gain_hiqual_part) +
03529         (double) d7cal->gain[i] * (double) d7cal->gain[i];
03530       if (dgain < 0)
03531         tg = model->gain_min;
03532       else
03533         {
03534           tg = sqrt (dgain) + 0.5;
03535           if (tg < model->gain_min)
03536             tg = model->gain_min;
03537           if (tg > model->gain_hiqual_max)
03538             tg = model->gain_hiqual_max;
03539         }
03540       caldat->cal_hiqual.gain[i] = tg;
03541       DBG (DBG_info,
03542            "pie_usb_calicalc_hiqual gain[%d] = 0x%02x = %d\n", i, tg, tg);
03543 
03544       /* the rest has to be done by exposure time */
03545       dgain = fact;
03546       if (tg != d7cal->gain[i])
03547         dgain *=
03548           exp (model->gain_const[i] *
03549                ((double) d7cal->gain[i] * (double) d7cal->gain[i] -
03550                 (double) tg * (double) tg));
03551       tt = dgain * (double) d7cal->texp[i] + 0.5;
03552 
03553       /* if exposure time is too short try to redo the gain,
03554          should not happen very often as "fact" is usually > 1 */
03555       if (tt < d7cal->t_min)
03556         {
03557           tt = d7cal->t_min;
03558           fact *= (double) tt / (double) d7cal->texp[i];
03559           dgain =
03560             log (fact) / model->gain_const[i] +
03561             (double) d7cal->gain[i] * (double) d7cal->gain[i];
03562           if (dgain < 0)
03563             tg = model->gain_min;
03564           else
03565             {
03566               tg = sqrt (dgain) + 0.5;
03567               if (tg < model->gain_min)
03568                 tg = model->gain_min;
03569             }
03570           caldat->cal_hiqual.gain[i] = tg;
03571           DBG (DBG_info,
03572                "pie_usb_calicalc_hiqual regain[%d] = 0x%02x = %d\n",
03573                i, tg, tg);
03574         }
03575       caldat->cal_hiqual.texp[i] = tt;
03576       if (tt > tmax)
03577         tmax = tt;
03578       DBG (DBG_info,
03579            "pie_usb_calicalc_hiqual texp[%d] = 0x%02x = %d\n", i, tt, tt);
03580     }
03581   caldat->cal_hiqual.texp_max = tmax;
03582 }
03583 
03584 /* ------------------------ PIE_USB_CALICALC_NORMAL ----------------------------
03585  *
03586  * @brief Calculate gain and exposure for normal mode
03587  *
03588  * @param[in] scanner points to structure of opened scanner
03589  * @param[in] d7cal points to calibration data read by a PIE_READ_CALIBRATION command
03590  *
03591  * @note
03592  * In normal mode we have to fight nasty offsets with some types of scanners and
03593  * a rather narrow window for exposure time. Here for a color (j) the illumination
03594  * (Ij) reached with certain gain (gj) and exposure time (tj) settings can be described
03595  * by (II)  I = n * aj * exp(c * gj^2) * tj - (n - 1) * 65536 . The gain constant c, offset
03596  * factor n and desired brightness have to be provided. Gain may be really maximal here,
03597  * i.e. 0x3f, the exposure time has to be larger than t_min.
03598  * The result of this routine is stored in scanner->cal_data.
03599  */
03600 static void
03601 pie_usb_calicalc_normal (Pie_Scanner * scanner,
03602                          PIE_USB_Calibration_Read * d7cal)
03603 {
03604   PIE_USB_Model *model = scanner->device->model;
03605   PIE_USB_Calibration *caldat = scanner->cal_data;
03606   int tg, tt, i, tmax;
03607 
03608   SANE_Status status;
03609   int brightnesses[3];
03610   int pokebuf[4];
03611   int pokesiz = 3;
03612 
03613   DBG (DBG_proc, "pie_usb_calicalc_normal\n");
03614 
03615   for (i = 0; i < 3; i++)
03616     brightnesses[i] = caldat->brightness[i];
03617   status = pie_usb_poke_ints ("/tmp/bright.txt", pokebuf, &pokesiz);
03618   if (status == SANE_STATUS_GOOD && pokesiz)
03619     {
03620       for (i = 0; i < 3; i++)
03621         brightnesses[i] = pokebuf[i];
03622       DBG (DBG_info,
03623            "pie_usb_calicalc_normal poked brightness %d, %d, %d\n",
03624            brightnesses[0], brightnesses[1], brightnesses[2]);
03625     }
03626 
03627   tmax = 0;
03628   for (i = 0; i < 3; i++)
03629     {
03630       /* start calculating gain for default texp rounding down.
03631          Following horrible expression is obtained by setting up equation (II) for the desired
03632          brightness, setting up quality mode equation (I) using the information from the
03633          0xd7 read together with the achieved brightness of read calibration lines and solving
03634          that system for the gain required in normal mode */
03635       tg = sqrt (log ((((double) brightnesses[i] +
03636                         ((model->offs_factor[i] -
03637                           1.0) * 65536)) * (double) d7cal->texp[i]) /
03638                       (model->offs_factor[i] *
03639                        (double) model->default_normal.texp[i] *
03640                        (double) caldat->mean_shade[i])) /
03641                  model->gain_const[i] +
03642                  (double) d7cal->gain[i] * (double) d7cal->gain[i]);
03643       if (tg > 0x3f)
03644         tg = 0x3f;
03645       /* here the gain (tg) is smaller than for what it was calculated, so we need
03646          a longer exposure time. Using the same set of equations as above exposure time is
03647          calculated for the given gain */
03648       tt = (((double) brightnesses[i] + ((model->offs_factor[i] -
03649                                           1.0) * 65536.0)) *
03650             (double) d7cal->texp[i]) / (model->offs_factor[i] *
03651                                         (double) caldat->mean_shade[i]) *
03652         exp (model->gain_const[i] *
03653              ((double) d7cal->gain[i] * (double) d7cal->gain[i] - tg * tg)) +
03654         0.5;
03655       if (tt < d7cal->t_min)
03656         tt = d7cal->t_min;
03657       if (tt > model->texp_normal_max)
03658         tt = model->texp_normal_max;
03659 
03660       caldat->cal_normal.gain[i] = tg;
03661       caldat->cal_normal.texp[i] = tt;
03662       if (tt > tmax)
03663         tmax = tt;
03664       DBG (DBG_info,
03665            "pie_usb_calicalc_normal gain[%d] = 0x%02x = %d, texp[%d] = 0x%02x = %d\n",
03666            i, tg, tg, i, tt, tt);
03667     }
03668   caldat->cal_normal.texp_max = tmax;
03669 }
03670 
03671 
03672 /* ---------------------- PIE_USB_CALICALC_SLOW_DOWN --------------------------- */
03686 static unsigned char
03687 pie_usb_calicalc_slow_down (Pie_Scanner * scanner)
03688 {
03689   double width, x_dpmm;
03690   int slow_down;
03691 
03692   DBG (DBG_proc, "pie_usb_calicalc_slow_down\n");
03693 
03694   slow_down = 0;
03695   width = SANE_UNFIX (scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w);
03696   x_dpmm = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w) / MM_PER_INCH;
03697   if ((width > 0) && (x_dpmm > 0))
03698     {
03699       width *= 3 * x_dpmm;      /* calculate for RGB */
03700       if (scanner->val[OPT_BIT_DEPTH].w > 8)
03701         width *= 2;             /* bytes per line */
03702 
03703       if (width > SLOW_START)
03704         {                       /* slow down value */
03705           width = (width - SLOW_START) * SLOW_HEIGHT / SLOW_LENGTH;
03706           if (scanner->cal_mode ==      /* correct for exposure time */
03707               scanner->device->model->op_mode[OPM_QUALITY])
03708             width *=
03709               (double) scanner->device->model->default_hiqual.texp_max /
03710               (double) scanner->cal_data->cal_hiqual.texp_max;
03711           else
03712             width *=
03713               (double) scanner->device->model->default_normal.texp_max /
03714               (double) scanner->cal_data->cal_normal.texp_max;
03715           slow_down = (int) (width + 0.5);
03716           if (scanner->colormode == RGBI)       /* correct for infrared */
03717             slow_down -= 2;
03718           if ((slow_down < 0) || (slow_down >= 16))
03719             slow_down = 0;
03720         }
03721     }
03722   DBG (DBG_info, "pie_usb_calicalc_slow_down: %d\n", slow_down);
03723   return slow_down;
03724 }
03725 
03726 
03727 /* ------------------------ PIE_USB_CALIBRATION_SEND -------------------------- */
03748 static SANE_Status
03749 pie_usb_calibration_send (Pie_Scanner * scanner, int calc_cal)
03750 {
03751   PIE_USB_Calibration_Read calD7in;
03752   PIE_USB_Calibration_Send calDCout;
03753   size_t size_read = 103;
03754   size_t size_write = 23;
03755   SANE_Status status;
03756   unsigned char pokebuf[64];
03757   int i, pokesiz;
03758 
03759   DBG (DBG_proc, "pie_usb_calibration_send\n");
03760 
03761   status =                      /* 103 bytes */
03762     pie_usb_scsi_wrapper (scanner->sfd, read_calibrationC,
03763                           sizeof (read_calibrationC), &calD7in, &size_read);
03764   if (status != SANE_STATUS_GOOD)
03765     return status;
03766 
03767   DBG (DBG_info, "pie_usb_calibration_send received:\n");
03768   DBG_DUMP (DBG_info, (unsigned char *) &calD7in, 103);
03769 
03770   if (calD7in.illumination[0] == 0)     /* assume same target as for blue */
03771     calD7in.illumination[0] = calD7in.illumination[2];
03772   if (calD7in.illumination[1] == 0)     /* assume same target as for blue */
03773     calD7in.illumination[1] = calD7in.illumination[2];
03774   for (i = 0; i < 3; i++)
03775     scanner->cal_data->target_shade[i] = calD7in.illumination[i];
03776   scanner->cal_data->target_shade[3] = calD7in.illumination[2]; /* ired ?? */
03777 
03778   /* now we have all data to calculate calibration */
03779   if (calc_cal)
03780     {
03781       pie_usb_calicalc_hiqual (scanner, &calD7in);
03782       pie_usb_calicalc_normal (scanner, &calD7in);
03783     }
03784   /* load vector to be sent */
03785   size_write += 6;
03786   memcpy (&(calDCout.scsi_cmd), write_calibrationC, 6);
03787   /* first with what we have/had calculated */
03788   if (scanner->cal_mode != scanner->device->model->op_mode[OPM_QUALITY])        /* normal mode */
03789     {
03790       for (i = 0; i < 3; i++)
03791         calDCout.texp[i] = scanner->cal_data->cal_normal.texp[i];
03792       for (i = 0; i < 3; i++)
03793         calDCout.gain[i] = scanner->cal_data->cal_normal.gain[i];
03794     }
03795   else                          /* quality mode */
03796     {
03797       for (i = 0; i < 3; i++)
03798         calDCout.texp[i] = scanner->cal_data->cal_hiqual.texp[i];
03799       for (i = 0; i < 3; i++)
03800         calDCout.gain[i] = scanner->cal_data->cal_hiqual.gain[i];
03801     }
03802 
03803   /* then with values which are usully copied */
03804   memcpy (calDCout.offset, calD7in.offset, 6);  /* offsets, zero_2 */
03805 
03806   calDCout.some_time[0] = calD7in.some_time;
03807   /* slow down at high resolutions */
03808   if (calc_cal
03809       || (scanner->cal_mode == scanner->device->model->op_mode[OPM_SKIPCAL]))
03810     calDCout.some_time[1] = pie_usb_calicalc_slow_down (scanner);
03811   else
03812     calDCout.some_time[1] = 0;
03813   calDCout.some_time[2] = 0;
03814 
03815   memcpy (&calDCout.infrared, &calD7in.infrared, sizeof (PIE_USB_cal_ired));
03816   pokesiz = 12;
03817   status = pie_usb_poke_bytes ("/tmp/calbytes.txt", pokebuf, &pokesiz);
03818   if (status == SANE_STATUS_GOOD)
03819     {
03820       memcpy (calDCout.texp, &pokebuf[0], 6);
03821       memcpy (calDCout.gain, &pokebuf[6], 6);
03822     }
03823 
03824   DBG (DBG_info, "pie_usb_calibration_send sending:\n");
03825   DBG_DUMP (DBG_info, (unsigned char *) &calDCout, size_write);
03826   status =
03827     pie_usb_scsi_wrapper (scanner->sfd, &calDCout, size_write, NULL, NULL);
03828   return status;
03829 }
03830 
03831 
03832 /* ---------------------------- PIE_USB_CALIBRATE ----------------------------- */
03858 static SANE_Status
03859 pie_usb_calibrate (Pie_Scanner * scanner)
03860 {
03861   unsigned int val;
03862   unsigned char *rcv_buffer, *src;
03863   int rcv_length, rcv_lines, rcv_bits;
03864   int pixels_per_line, average_lines;
03865   int i, j, k, l;
03866   int n[4];
03867   int *dest;
03868   double dval;
03869   size_t size;
03870   SANE_Status status;
03871 
03872   DBG (DBG_proc, "pie_usb_calibrate\n");
03873 
03874   rcv_lines = scanner->device->cal_info[0].num_lines;
03875   average_lines = rcv_lines - 1;
03876   if (AVERAGE_CAL_LINES < average_lines)
03877     average_lines = AVERAGE_CAL_LINES;
03878   pixels_per_line = scanner->device->cal_info[0].pixels_per_line;
03879   rcv_length = pixels_per_line;
03880   rcv_bits = scanner->device->cal_info[0].receive_bits;
03881   if (rcv_bits > 8)
03882     rcv_length *= 2;
03883   if ((scanner->colormode == RGB) || (scanner->colormode == RGBI))
03884     rcv_length = (rcv_length + 2) * 4;
03885   else
03886     return SANE_STATUS_INVAL;
03887 
03888   rcv_buffer = (unsigned char *) malloc (rcv_length);
03889   if (!rcv_buffer)
03890     return SANE_STATUS_NO_MEM;
03891 
03892   status = pie_usb_wait_scanner (scanner, 6);
03893   if (status != SANE_STATUS_GOOD)
03894     goto freend;
03895   set_read_length (sread.cmd, 4);       /* a test line */
03896   size = rcv_length;
03897   status =
03898     pie_usb_scsi_wrapper (scanner->sfd, sread.cmd, sread.size,
03899                           rcv_buffer, &size);
03900   if (status != SANE_STATUS_GOOD)       /* should not happen */
03901     {
03902       status = SANE_STATUS_GOOD;        /* try to recover */
03903       goto freend;
03904     }
03905   rcv_lines--;
03906   /* this gets the data */
03907   memset (scanner->cal_data->shades, 0, pixels_per_line * 4 * sizeof (int));
03908   scanner->cal_data->shades[0] = 0;
03909   for (i = 0; i < 4; i++)
03910     n[i] = 0;
03911   for (k = 0; k < average_lines; k++)
03912     {
03913       size = rcv_length;
03914       status =
03915         pie_usb_scsi_wrapper (scanner->sfd, sread.cmd, sread.size,
03916                               rcv_buffer, &size);
03917       if (status != SANE_STATUS_GOOD)
03918         goto freend;
03919       for (i = 0; i < 4; i++)
03920         {
03921           if (rcv_bits > 8)
03922             src = rcv_buffer + i * (pixels_per_line + 1) * 2;
03923           else
03924             src = rcv_buffer + i * (pixels_per_line + 2);
03925           if (*src == 'R')
03926             l = 0;
03927           else if (*src == 'G')
03928             l = 1;
03929           else if (*src == 'B')
03930             l = 2;
03931           else if (*src == 'I')
03932             l = 3;
03933           else
03934             {
03935               DBG (DBG_error,
03936                    "pie_usb_calibrate: invalid index byte (%02x)\n", *src);
03937               DBG_DUMP (DBG_error, src, 32);
03938               status = SANE_STATUS_INVAL;
03939               goto freend;
03940             }
03941           src += 2;
03942           dest = scanner->cal_data->shades + l * pixels_per_line;
03943           if (rcv_bits > 8)
03944             {
03945               for (j = 0; j < pixels_per_line; j++)
03946                 {
03947                   val = *src++;
03948                   val += (*src++) << 8;
03949                   *dest++ += val;
03950                 }
03951             }
03952           else
03953             {
03954               for (j = 0; j < pixels_per_line; j++)
03955                 *dest++ += *src++;
03956             }
03957           n[l]++;
03958         }
03959       rcv_lines--;
03960     }
03961   for (l = 0; l < 4; l++)
03962     {
03963       dest = scanner->cal_data->shades + l * pixels_per_line;
03964       dval = 0;
03965       for (j = pixels_per_line; j > 0; j--)
03966         {
03967           dval += *dest;
03968           *dest++ /= n[l];
03969         }
03970       scanner->cal_data->mean_shade[l] =
03971         dval / (double) (n[l] * pixels_per_line) + 0.5;
03972       DBG (DBG_info,
03973            "pie_usb_calibrate: color %d, mean %d = %04x\n", l,
03974            scanner->cal_data->mean_shade[l],
03975            scanner->cal_data->mean_shade[l]);
03976     }
03977   if (DBG_LEVEL >= DBG_image)
03978     pie_usb_shades_to_pnm (scanner, "/tmp/pieshading", 64);
03979   /* get, calculate and send calibration */
03980   status = pie_usb_calibration_send (scanner, 1);
03981   if (status != SANE_STATUS_GOOD)
03982     goto freend;
03983   /* we have to read all lines, discard the rest */
03984   while (rcv_lines > 0)
03985     {
03986       size = rcv_length;
03987       status =
03988         pie_usb_scsi_wrapper (scanner->sfd, sread.cmd, sread.size,
03989                               rcv_buffer, &size);
03990       if (status != SANE_STATUS_GOOD)
03991         goto freend;
03992       rcv_lines--;
03993     }
03994 
03995 freend:                 /* ugly, but this may be one of the cases ... */
03996   free (rcv_buffer);
03997   return status;
03998 }
03999 
04000 
04001 /* ------------------------- PIE_USB_CORRECT_SHADING -------------------------- */
04017 static void
04018 pie_usb_correct_shading (Pie_Scanner * scanner,
04019                          unsigned char *in_buf[4], SANEI_IR_bufptr out_buf[4],
04020                          int pixels, int bits, int start_plane, int end_plane)
04021 {
04022   SANEI_IR_bufptr buf[4];
04023   unsigned char *sensors;
04024   unsigned int val;
04025   int *shade[4];
04026   int target[4];
04027   int cal_pixels;
04028   int cal_idx = 0;
04029   int mirror;
04030   int i, j, k;
04031 
04032   DBG (DBG_proc, "pie_usb_correct_shading: %d to %d\n", start_plane,
04033        end_plane);
04034 
04035   mirror = scanner->device->model->flags & PIE_USB_FLAG_MIRROR_IMAGE;
04036   cal_pixels = scanner->device->cal_info[0].pixels_per_line;
04037   sensors = scanner->cal_data->sensors;
04038   for (k = start_plane; k <= end_plane; k++)
04039     {
04040       shade[k] = scanner->cal_data->shades + k * cal_pixels;
04041       /* we can take means or targets here,
04042          targets may lead to values larger than 16 bit */
04043       target[k] = scanner->cal_data->mean_shade[k];
04044       if (mirror == 0)
04045         buf[k] = out_buf[k];
04046       else if (bits > 8)
04047         buf[k].b16 = out_buf[k].b16 + pixels - 1;
04048       else
04049         buf[k].b8 = out_buf[k].b8 + pixels - 1;
04050     }
04051 
04052   j = 0;
04053   for (i = 0; i < pixels; i++)
04054     {
04055       while (sensors[j] != 0 && j < cal_pixels)
04056         j++;
04057       if (j < cal_pixels)
04058         {
04059           cal_idx = j;
04060           j++;
04061         }
04062       if (mirror == 0)
04063         {
04064           if (bits > 8)
04065             for (k = start_plane; k <= end_plane; k++)
04066               {
04067                 val = *in_buf[k]++;
04068                 val += (*in_buf[k]++) << 8;
04069                 if (val > 4096)
04070                   {
04071                     val = (val * target[k]) / shade[k][cal_idx];
04072                     if (val > 0xffff)
04073                       val = 0xffff;
04074                   }
04075                 *buf[k].b16++ = val;
04076               }
04077           else
04078             for (k = start_plane; k <= end_plane; k++)
04079               {
04080                 val = *in_buf[k]++;
04081                 if (val > 16)
04082                   {
04083                     val = (val * target[k]) / shade[k][cal_idx];
04084                     if (val > 0xff)
04085                       val = 0xff;
04086                   }
04087                 *buf[k].b8++ = val;
04088               }
04089         }
04090       else
04091         {
04092           if (bits > 8)
04093             for (k = start_plane; k <= end_plane; k++)
04094               {
04095                 val = *in_buf[k]++;
04096                 val += (*in_buf[k]++) << 8;
04097                 if (val > 4096)
04098                   {
04099                     val = (val * target[k]) / shade[k][cal_idx];
04100                     if (val > 0xffff)
04101                       val = 0xffff;
04102                   }
04103                 *buf[k].b16-- = val;
04104               }
04105           else
04106             for (k = start_plane; k <= end_plane; k++)
04107               {
04108                 val = *in_buf[k]++;
04109                 if (val > 16)
04110                   {
04111                     val = (val * target[k]) / shade[k][cal_idx];
04112                     if (val > 0xff)
04113                       val = 0xff;
04114                   }
04115                 *buf[k].b8-- = val;
04116               }
04117         }
04118     }
04119 }
04120 
04121 
04122 /*
04123  * @@ USB image reading and processing
04124  */
04125 
04126 /* ------------------------- PIE_USB_READER_REORDER --------------------------- */
04136 static void
04137 pie_usb_reader_reorder (Pie_Scanner * scanner, SANEI_IR_bufptr * in_img,
04138                         SANEI_IR_bufptr out_img, int planes, int pixels)
04139 {
04140   SANEI_IR_bufptr dest;
04141   SANEI_IR_bufptr cptr[4];
04142   uint16_t *gamma_lut;
04143   int i, k;
04144 
04145   DBG (DBG_proc,
04146        "pie_usb_reader_reorder:  %d pixels\n", pixels);
04147 
04148   for (i = 0; i < planes; i++)
04149     cptr[i] = in_img[i];
04150 
04151   dest = out_img;
04152   if (scanner->processing & POST_SW_COLORS)
04153     {
04154       if (scanner->val[OPT_SW_NEGA].w == SANE_TRUE)
04155         {
04156           if (scanner->params.depth > 8)
04157             {
04158               gamma_lut = scanner->gamma_lut16;
04159               for (i = pixels; i > 0; i--)
04160                 for (k = 0; k < planes; k++)
04161                   *dest.b16++ = (uint16_t) (65535 - gamma_lut[*cptr[k].b16++]);
04162             }
04163           else
04164             {
04165               gamma_lut = scanner->gamma_lut8;
04166               for (i = pixels; i > 0; i--)
04167                 for (k = 0; k < planes; k++)
04168                   *dest.b8++ = (uint8_t) (255 - gamma_lut[*cptr[k].b8++]);
04169             }
04170         }
04171       else
04172         {
04173           if (scanner->params.depth > 8)
04174             {
04175               gamma_lut = scanner->gamma_lut16;
04176               for (i = pixels; i > 0; i--)
04177                 for (k = 0; k < planes; k++)
04178                   *dest.b16++ = (uint16_t) gamma_lut[*cptr[k].b16++];
04179             }
04180           else
04181             {
04182               gamma_lut = scanner->gamma_lut8;
04183               for (i = pixels; i > 0; i--)
04184                 for (k = 0; k < planes; k++)
04185                   *dest.b8++ = (uint8_t) gamma_lut[*cptr[k].b8++];
04186             }
04187         }
04188     }
04189   else
04190     {
04191       if (scanner->params.depth > 8)
04192         {
04193           for (i = pixels; i > 0; i--)
04194             for (k = 0; k < planes; k++)
04195               *dest.b16++ = *cptr[k].b16++;
04196         }
04197       else
04198         {
04199           for (i = pixels; i > 0; i--)
04200             for (k = 0; k < planes; k++)
04201               *dest.b8++ = *cptr[k].b8++;
04202         }
04203     }
04204 }
04205 
04206 
04207 /* ---------------------------- PIE_USB_SW_STORE ------------------------------ */
04219 static SANE_Status
04220 pie_usb_sw_store (Pie_Scanner * scanner,
04221     SANEI_IR_bufptr * in_img, int planes)
04222 {
04223   SANE_Status status = SANE_STATUS_GOOD;
04224   size_t size;
04225 
04226   DBG (DBG_proc,
04227        "pie_usb_sw_store:  %d lines of %d bytes/line\n",
04228        scanner->params.lines, scanner->params.bytes_per_line);
04229 
04230   if (scanner->img_buffer.b8)
04231     free (scanner->img_buffer.b8);
04232   size = scanner->params.bytes_per_line * scanner->params.lines;
04233   scanner->img_buffer.b8 = malloc (size);
04234   if (scanner->img_buffer.b8)
04235     {
04236       pie_usb_reader_reorder (scanner, in_img, scanner->img_buffer, planes,
04237                               scanner->params.pixels_per_line * scanner->params.lines);
04238       if (DBG_LEVEL >= DBG_image)
04239         {
04240           pie_usb_write_pnm_file ("/tmp/RGBi-img.pnm", scanner->img_buffer.b8,
04241                                   scanner->params.depth, planes,
04242                                   scanner->params.pixels_per_line,
04243                                   scanner->params.lines);
04244         }
04245     }
04246   else
04247     {
04248       DBG (DBG_error, "pie_usb_sw_store: no buffer\n");
04249       status = SANE_STATUS_NO_MEM;
04250     }
04251 
04252   return status;
04253 }
04254 
04255 
04256 /* -------------------------- PIE_USB_READER_WRITE ---------------------------- */
04271 static SANE_Status
04272 pie_usb_reader_write (Pie_Scanner * scanner, FILE * fp,
04273                       SANEI_IR_bufptr * in_img, int planes, int lines)
04274 {
04275   SANE_Status status = SANE_STATUS_GOOD;
04276   SANEI_IR_bufptr reorder;
04277   size_t size, nwrite;
04278 
04279   DBG (DBG_proc,
04280        "pie_usb_reader_write:  %d lines of %d bytes/line\n",
04281        lines, scanner->params.bytes_per_line);
04282 
04283   size = scanner->params.bytes_per_line * lines;
04284   reorder.b8 = malloc (size);
04285   if (reorder.b8)
04286     {
04287       pie_usb_reader_reorder (scanner, in_img, reorder, planes,
04288                               scanner->params.pixels_per_line * lines);
04289 
04290       nwrite = fwrite (reorder.b8, 1, size, fp);
04291       if (nwrite < size)        /* abort */
04292         {
04293           DBG (DBG_error, "pie_usb_reader_write: pipe error\n");
04294           status = SANE_STATUS_IO_ERROR;
04295         }
04296 
04297       free (reorder.b8);
04298     }
04299   else
04300     {
04301       DBG (DBG_error, "pie_usb_reader_write: no buffer\n");
04302       status = SANE_STATUS_NO_MEM;
04303     }
04304 
04305   return status;
04306 }
04307 
04308 
04309 /* -------------------------- PIE_USB_SMOOTHEN RGB ---------------------------- */
04326 static SANE_Status
04327 pie_usb_smoothen_rgb (const SANE_Parameters * params,
04328                       SANEI_IR_bufptr * the_img, int win_size)
04329 {
04330   SANEI_IR_bufptr cplane[3];    /* R, G, B, (I) gray scale planes */
04331   SANEI_IR_bufptr plane;
04332   int depth, i;
04333   size_t itop;
04334   SANE_Status ret = SANE_STATUS_NO_MEM;
04335 
04336   for (i = 0; i < 3; i++)
04337     cplane[i] = the_img[i];
04338 
04339   depth = params->depth;
04340   itop = params->lines * params->pixels_per_line;
04341   if (depth > 8)
04342     plane.b8 = malloc (itop * sizeof (uint16_t));
04343   else
04344     plane.b8 = malloc (itop * sizeof (uint8_t));
04345   if (!plane.b8)
04346     DBG (5, "pie_usb_smoothen_rgb: Cannot allocate buffer\n");
04347   else
04348     {
04349       for (i = 0; i < 3; i++)
04350         {
04351           ret =
04352             sanei_ir_filter_mean (params, cplane[i], plane, win_size, win_size);
04353           if (ret != SANE_STATUS_GOOD)
04354             break;
04355           ret =
04356             sanei_ir_filter_mean (params, plane, cplane[i], win_size, win_size);
04357           if (ret != SANE_STATUS_GOOD)
04358             break;
04359         }
04360       free (plane.b8);
04361     }
04362   return ret;
04363 }
04364 
04365 /* ------------------------ PIE_USB_SW_FINAL_CROP ----------------------------- */
04381 static SANE_Status
04382 pie_usb_sw_crop_planes (SANE_Parameters * parameters, Pie_Scanner * scanner,
04383     SANEI_IR_bufptr * in_img, int top, int bot, int left, int right, int planes)
04384 {
04385   SANEI_IR_bufptr cplane[4];    /* R, G, B, I gray scale planes */
04386   SANE_Parameters params;
04387   SANE_Status status;
04388   int i;
04389 
04390   for (i = 0; i < planes; i++)
04391     cplane[i] = in_img[i];
04392 
04393   for (i = 0; i < planes; i++)
04394     {
04395       memcpy (&params, parameters, sizeof (SANE_Parameters));
04396       status =
04397         sanei_magic_crop(&params, cplane[i].b8, top, bot, left, right);
04398       if (status != SANE_STATUS_GOOD)
04399         return status;
04400     }
04401   memcpy (parameters, &params, sizeof (SANE_Parameters));
04402   scanner->params.bytes_per_line /= scanner->params.pixels_per_line;
04403   scanner->params.pixels_per_line = params.pixels_per_line;
04404   scanner->params.bytes_per_line *= params.pixels_per_line;
04405   scanner->params.lines = params.lines;
04406 
04407   return SANE_STATUS_GOOD;
04408 }
04409 
04410 
04411 /* ------------------------ PIE_USB_SW_FINAL_CROP ----------------------------- */
04426 static SANE_Status
04427 pie_usb_sw_final_crop (Pie_Scanner * scanner)
04428 {
04429   SANEI_IR_bufptr tmp_img;
04430   SANE_Parameters params;
04431   SANE_Status status;
04432   int resol = scanner->resolution / 16;
04433   int top, bot, left, right;
04434 
04435   DBG (DBG_sane_proc, "pie_usb_sw_final_crop\n");
04436 
04437   /* reduce image depth for edge detection */
04438   status =
04439       sane_ir_to_8bit (&scanner->params, scanner->img_buffer,
04440           &params, &tmp_img);
04441   if (status != SANE_STATUS_GOOD)
04442       return status;
04443 
04444   status = sanei_magic_findEdges(&params, tmp_img.b8,
04445       resol, resol, &top, &bot, &left, &right);
04446   if (status != SANE_STATUS_GOOD)
04447       return status;
04448 
04449   if (strcmp (scanner->val[OPT_SW_CROP].s, CROP_INNER_STR) == 0)
04450     {
04451       int width = scanner->params.pixels_per_line;
04452       int height = scanner->params.lines;
04453       int it = top;
04454       int ib = bot;
04455       int il = left;
04456       int ir = right;
04457 
04458       resol = scanner->resolution / 100;
04459       if (it > 2)
04460         it += resol;
04461       if (height - ib > 2)
04462         ib -= resol;
04463       if (il > 2)
04464         il += resol;
04465       if (width - ir > 2)
04466         ir -= resol;
04467 
04468       if (ib - it > 0)
04469         {
04470           top = it;
04471           bot = ib;
04472         }
04473       if (ir - il > 0)
04474         {
04475           left = il;
04476           right = ir;
04477         }
04478       DBG (DBG_info, "pie_usb_sw_final_crop: suggested cropping:\n \
04479           top %d, bot %d, left %d, right %d\n", top, bot, left, right);
04480     }
04481 
04482   status =
04483     sanei_magic_crop(&scanner->params, scanner->img_buffer.b8, top, bot, left, right);
04484 
04485   free (tmp_img.b8);
04486   return status;
04487 }
04488 
04489 
04490 /* -------------------------- PIE_USB_SW_POST --------------------------------- */
04515 static SANE_Status
04516 pie_usb_sw_post (Pie_Scanner * scanner,
04517     SANEI_IR_bufptr * in_img, int planes, int out_planes)
04518 {
04519   SANEI_IR_bufptr cplane[4];    /* R, G, B, I gray scale planes */
04520   SANE_Parameters parameters;   /* describes the image */
04521   int winsize_smooth;           /* for adapting replaced pixels */
04522   char filename[64];
04523   SANE_Status status;
04524   int smooth, i;
04525 
04526   memcpy (&parameters, &scanner->params, sizeof (SANE_Parameters));
04527   parameters.format = SANE_FRAME_GRAY;
04528   parameters.bytes_per_line = parameters.pixels_per_line;
04529   if (parameters.depth > 8)
04530     parameters.bytes_per_line *= 2;
04531   parameters.last_frame = 0;
04532 
04533   DBG (DBG_info, "pie_usb_sw_post: %d ppl, %d lines, %d bits, %d planes, %d dpi\n",
04534        parameters.pixels_per_line, parameters.lines,
04535        planes, parameters.depth, scanner->resolution);
04536 
04537   for (i = 0; i < planes; i++)
04538     cplane[i] = in_img[i];
04539 
04540   /* dirt is rather resolution invariant, so
04541    * setup resolution dependent parameters
04542    */
04543   /* film grain reduction */
04544   smooth = scanner->val[OPT_SW_GRAIN].w;
04545   winsize_smooth = (scanner->resolution / 540) | 1;
04546   /* smoothen whole image or only replaced pixels */
04547   if (smooth)
04548     {
04549       winsize_smooth += 2 * (smooth - 3);       /* even */
04550       if (winsize_smooth < 3)
04551         smooth = 0;
04552     }
04553   if (winsize_smooth < 3)
04554     winsize_smooth = 3;
04555   DBG (DBG_info, "pie_usb_sw_post: winsize_smooth %d\n", winsize_smooth);
04556 
04557   /* RGBI post-processing if selected:
04558    * 1) remove spectral overlay from ired plane,
04559    * 2) remove dirt, smoothen if, crop if */
04560   if (scanner-> processing & POST_SW_IRED_MASK)
04561     {
04562       int winsize_filter;               /* primary size of filtering window */
04563       int size_dilate;                  /* the dirt mask */
04564       SANE_Byte *thresh_data;
04565       int static_thresh, too_thresh;    /* static thresholds */
04566 
04567       /* size of filter detecting dirt */
04568       winsize_filter = (int) (5.0 * (double) scanner->resolution / 300.0) | 1;
04569       if (winsize_filter < 3)
04570         winsize_filter = 3;
04571       /* dirt usually has smooth edges which also need correction */
04572       size_dilate = scanner->resolution / 1000 + 1;
04573 
04574       /* remove spectral overlay from ired plane */
04575       status =
04576         sane_ir_spectral_clean (&parameters, scanner->ln_lut, cplane[0],
04577                                 cplane[3]);
04578       if (status != SANE_STATUS_GOOD)
04579         return status;
04580       if (DBG_LEVEL >= DBG_image)
04581         {
04582           snprintf (filename, 63, "/tmp/ir-spectral.pnm");
04583           pie_usb_write_pnm_file (filename, cplane[3].b8,
04584                                   parameters.depth, 1,
04585                                   parameters.pixels_per_line, parameters.lines);
04586         }
04587       if (cancel_requ)          /* asynchronous cancel ? */
04588         return SANE_STATUS_CANCELLED;
04589 
04590       /* remove dirt, smoothen if, crop if */
04591       if (scanner->processing & POST_SW_DIRT)
04592         {
04593           double *norm_histo;
04594           int crop[4];
04595 
04596           /* first detect large dirt by a static threshold */
04597           status =
04598               sanei_ir_create_norm_histogram (&parameters, cplane[3], &norm_histo);
04599           if (status != SANE_STATUS_GOOD)
04600             {
04601               DBG (DBG_error, "pie_usb_sw_post: no buffer\n");
04602               return SANE_STATUS_NO_MEM;
04603             }
04604           /* generate a "bimodal" static threshold */
04605           status =
04606             sanei_ir_threshold_yen (&parameters, norm_histo, &static_thresh);
04607           if (status != SANE_STATUS_GOOD)
04608             return status;
04609           /* generate traditional static threshold */
04610           status =
04611             sanei_ir_threshold_otsu (&parameters, norm_histo, &too_thresh);
04612           if (status != SANE_STATUS_GOOD)
04613             return status;
04614           /* choose lower one */
04615           if (too_thresh < static_thresh)
04616             static_thresh = too_thresh;
04617           free (norm_histo);
04618 
04619           /* then generate dirt mask with adaptive thresholding filter
04620            * and add the dirt from the static threshold */
04621           status =                  /* last two parameters: 10, 50 detects more, 20, 75 less */
04622             sanei_ir_filter_madmean (&parameters, cplane[3], &thresh_data,
04623                                      winsize_filter, 20, 100);
04624           if (status != SANE_STATUS_GOOD)
04625             return status;
04626           sanei_ir_add_threshold (&parameters, cplane[3], thresh_data,
04627                                   static_thresh);
04628           if (DBG_LEVEL >= DBG_image)
04629             {
04630               snprintf (filename, 63, "/tmp/ir-threshold.pnm");
04631               pie_usb_write_pnm_file (filename, thresh_data,
04632                                       8, 1, parameters.pixels_per_line,
04633                                       parameters.lines);
04634             }
04635           if (cancel_requ)          /* asynchronous cancel ? */
04636             return SANE_STATUS_CANCELLED;
04637 
04638           /* replace the dirt and smoothen film grain and crop if possible */
04639           if (((scanner->processing & POST_SW_CROP) != 0) &&
04640               (scanner->val[OPT_SW_NEGA].w == SANE_FALSE))
04641             {
04642               status =
04643                   sanei_ir_dilate_mean (&parameters, cplane, thresh_data,
04644                       500, size_dilate, winsize_smooth, smooth,
04645                       (strcmp (scanner->val[OPT_SW_CROP].s, CROP_INNER_STR) == 0),
04646                       crop);
04647               if (status != SANE_STATUS_GOOD)
04648                 return status;
04649               status =
04650                   pie_usb_sw_crop_planes (&parameters, scanner, cplane,
04651                       crop[0], crop[1], crop[2], crop[3], 3);
04652               if (status != SANE_STATUS_GOOD)
04653                 return status;
04654             }
04655           else
04656             {
04657               status =
04658                   sanei_ir_dilate_mean (&parameters, cplane, thresh_data, 500,
04659                       size_dilate, winsize_smooth, smooth, 0, NULL);
04660               if (status != SANE_STATUS_GOOD)
04661                 return status;
04662             }
04663           smooth = 0;
04664           free (thresh_data);
04665         }
04666     }   /* scanner-> processing & POST_SW_IRED_MASK */
04667 
04668   /* smoothen remaining cases */
04669   if (smooth)
04670     pie_usb_smoothen_rgb (&parameters, cplane, winsize_smooth);
04671 
04672   status = pie_usb_sw_store (scanner, cplane, out_planes);
04673   if (status != SANE_STATUS_GOOD)
04674     return status;
04675 
04676   if (((scanner->processing & POST_SW_CROP) != 0) &&
04677       (((scanner->processing & POST_SW_DIRT) == 0) ||
04678           (scanner->val[OPT_SW_NEGA].w == SANE_TRUE)))
04679     status = pie_usb_sw_final_crop (scanner);
04680 
04681   return status;
04682 }
04683 
04684 
04685 /* ------------------------- PIE_USB_READER_INDEXED --------------------------- */
04705 static SANE_Status
04706 pie_usb_reader_indexed (Pie_Scanner * scanner, FILE * fp)
04707 {
04708   char idx_char[4] = {
04709     'R', 'G', 'B', 'I'
04710   };
04711   char *idx_ptr[4];
04712   char *iend_ptr[4];
04713   int idx_buf[4];
04714   int idx_found;
04715   unsigned char *src[4], *buffer;
04716   unsigned char *wrt_ptr, *end_ptr;
04717   int bytes_per_line, bytes_per_color;
04718   int chunk_lines, lines_todo;
04719   int read_lines, write_lines;
04720   SANE_Status status;
04721   int irgb;                     /* number of color planes = values per pixel */
04722   int irgb_out;                 /* limit output as long as SANE disregards infrared */
04723   SANE_Bool flag_accumulate;    /* 1 : store all data read */
04724   SANE_Bool flag_postprocess;   /* 0 : write immediately */
04725   int request_data, i, j;
04726   size_t chunk_size, size;
04727 
04728   struct timeval start_time, end_time;
04729   long int elapsed_time;
04730   SANEI_IR_bufptr color_buf[4];
04731   SANEI_IR_bufptr color_ptr[4];
04732   char filename[64];
04733 
04734   DBG (DBG_read,
04735       "pie_usb_reader_indexed reading %d lines of %d bytes/line in mode %d, processing %d\n",
04736       scanner->params.lines, scanner->params.bytes_per_line,
04737       scanner->colormode, scanner->processing);
04738 
04739   flag_postprocess = ((scanner->processing & POST_SW_ACCUM_MASK) != 0);
04740   flag_accumulate = flag_postprocess;
04741   if (DBG_LEVEL >= DBG_image)
04742     flag_accumulate = SANE_TRUE;
04743 
04744   bytes_per_color = scanner->bytes_per_line + 2;
04745   if (scanner->colormode == RGB)
04746     {
04747       irgb = 3;
04748       irgb_out = 3;
04749       bytes_per_line = scanner->params.bytes_per_line + 6;
04750     }
04751   else if (scanner->colormode == RGBI)
04752     {
04753       if (scanner->processing & POST_SW_DIRT)
04754         {
04755           irgb = 4;
04756           irgb_out = 3;
04757           bytes_per_line = scanner->params.bytes_per_line + bytes_per_color + 6;
04758         }
04759       else
04760         {
04761           irgb = 4;
04762 #ifdef SANE_FRAME_RGBI
04763           irgb_out = 4;
04764           bytes_per_line = scanner->params.bytes_per_line + 8;
04765 #else
04766           irgb_out = 3;
04767           bytes_per_line = scanner->params.bytes_per_line + bytes_per_color + 6;
04768 #endif
04769         }
04770     }
04771   else
04772     {
04773       DBG (DBG_error,
04774            "pie_usb_reader_indexed: wrong colour format!\n");
04775       return SANE_STATUS_UNSUPPORTED;
04776     }
04777 
04778   /* split the image read into reasonably sized chunks */
04779   chunk_lines = (scanner->params.lines + 7) / 8;
04780   chunk_size = chunk_lines * bytes_per_line;
04781   if (chunk_size > BUFFER_MAXSIZE)      /* hardware limitation ? */
04782     {
04783       chunk_lines = BUFFER_MAXSIZE / bytes_per_line;
04784       chunk_size = chunk_lines * bytes_per_line;
04785     }
04786 
04787   size = bytes_per_line *       /* deskewing needs a minimum */
04788     (scanner->filter_offset1 + (scanner->filter_offset2 + 3) * 2);
04789   if (chunk_size < size)
04790     {
04791       chunk_lines = (size + bytes_per_line - 1) / bytes_per_line;
04792       chunk_size = chunk_lines * bytes_per_line;
04793     }
04794 
04795   if (chunk_lines > scanner->params.lines)      /* not larger than image */
04796     {
04797       chunk_lines = scanner->params.lines;
04798       chunk_size = chunk_lines * bytes_per_line;
04799     }
04800 
04801   buffer = malloc (chunk_size * 2);
04802   if (!buffer)
04803     {
04804       DBG (DBG_error, "pie_usb_reader_indexed: no buffer\n");
04805       return SANE_STATUS_NO_MEM;
04806     }
04807 
04808   size = scanner->bytes_per_line;
04809   if (flag_accumulate)
04810     size *= scanner->params.lines;
04811   for (i = 0; i < irgb; i++)
04812     {
04813       color_buf[i].b8 = malloc (size);
04814       if (!color_buf[i].b8)
04815         {
04816           DBG (DBG_error, "pie_usb_reader_indexed: no buffers\n");
04817           for (j = 0; j < i; j++)
04818             free (color_buf[j].b8);
04819           free (buffer);
04820           return SANE_STATUS_NO_MEM;
04821         }
04822       color_ptr[i] = color_buf[i];
04823     }
04824   gettimeofday (&start_time, NULL);
04825 
04826   /* read one buffer in advance */
04827   lines_todo = chunk_lines;
04828   set_read_length (sread.cmd, lines_todo * irgb);
04829   size = lines_todo * bytes_per_line;
04830   do
04831     {
04832       status =
04833         pie_usb_scsi_wrapper (scanner->sfd, sread.cmd, sread.size,
04834                               buffer, &size);
04835     }
04836   while (status);
04837   DBG_DUMP (DBG_dump, buffer, 32);
04838   write_lines = scanner->params.lines;
04839   read_lines = write_lines - lines_todo;
04840   wrt_ptr = buffer + chunk_size;
04841   end_ptr = wrt_ptr + chunk_size;
04842   for (i = 0; i < irgb; i++)
04843     {
04844       idx_ptr[i] = (char *) buffer;
04845       iend_ptr[i] = idx_ptr[i] + chunk_size;
04846       idx_buf[i] = 1;
04847       src[i] = NULL;
04848     }
04849   request_data = 0;
04850   idx_found = 0;
04851   while (write_lines)
04852     {
04853       if (cancel_requ)
04854         {
04855           DBG (DBG_info, "pie_usb_reader_indexed: cancelled\n");
04856           status = SANE_STATUS_CANCELLED;
04857           break;
04858         }
04859       for (i = 0; i < irgb; i++)        /* find indices */
04860         {
04861           while (src[i] == NULL)
04862             {
04863               if (*idx_ptr[i] == idx_char[i])
04864                 {
04865                   src[i] = (unsigned char *) idx_ptr[i] + 2;
04866                   idx_found++;
04867                 }
04868               /* advance pointers unconditionally */
04869               idx_ptr[i] += bytes_per_color;
04870               if (idx_ptr[i] >= iend_ptr[i])
04871                 {
04872                   /* check for wrap */
04873                   if (idx_ptr[i] >= (char *) end_ptr)
04874                     idx_ptr[i] = (char *) buffer;
04875                   /* maintain private "end of buffer" */
04876                   iend_ptr[i] = idx_ptr[i] + chunk_size;
04877                   idx_buf[i]--;
04878                   /* request buffer fill if necessary */
04879                   if (idx_buf[i] == 0)
04880                     {
04881                       request_data = 1;
04882                       break;
04883                     }
04884                 }
04885             }
04886         }
04887 
04888       if (idx_found == irgb)    /* success, reorder and line(s) */
04889         {
04890           write_lines--;
04891 /*        for (i = 0; i < irgb; i++)
04892             memcpy(color_ptr[i].b8, src[i], scanner->bytes_per_line);
04893 */
04894           pie_usb_correct_shading (scanner, src, color_ptr,
04895                                    scanner->params.pixels_per_line,
04896                                    scanner->params.depth, 0, irgb - 1);
04897           if (!flag_postprocess)
04898             status =
04899                 pie_usb_reader_write (scanner, fp, color_ptr,
04900                                       irgb_out, 1);
04901           if (flag_accumulate)
04902             {
04903               if (write_lines == 0)
04904                 {
04905                   if (DBG_LEVEL >= DBG_image)
04906                     for (i = 0; i < irgb; i++)
04907                       {
04908                         snprintf (filename, 63, "/tmp/color-%d.pnm", i);
04909                         status =
04910                           pie_usb_write_pnm_file (filename, color_buf[i].b8,
04911                                                   scanner->params.depth, 1,
04912                                                   scanner->params.pixels_per_line,
04913                                                   scanner->params.lines);
04914                         if (status != SANE_STATUS_GOOD)
04915                           break;
04916                       }
04917                   if (flag_postprocess)
04918                     status =
04919                         pie_usb_sw_post (scanner, color_buf, irgb, irgb_out);
04920                 }
04921               else
04922                 for (i = 0; i < irgb; i++)
04923                   color_ptr[i].b8 += scanner->bytes_per_line;
04924             }
04925           if (status != SANE_STATUS_GOOD)
04926             {
04927               write_lines = 0;
04928               request_data = 0;
04929             }
04930 
04931           for (i = 0; i < irgb; i++)    /* setup for next line */
04932             src[i] = NULL;
04933           idx_found = 0;
04934         }
04935 
04936       if (request_data)         /* read next data */
04937         {
04938           if (read_lines)
04939             {
04940               lines_todo = chunk_lines;
04941               if (lines_todo > read_lines)
04942                 lines_todo = read_lines;
04943               set_read_length (sread.cmd, lines_todo * irgb);
04944               size = lines_todo * bytes_per_line;
04945               do
04946                 {
04947                   status =
04948                     pie_usb_scsi_wrapper (scanner->sfd, sread.cmd,
04949                                           sread.size, wrt_ptr, &size);
04950                 }
04951               while (status);
04952               DBG_DUMP (DBG_dump, wrt_ptr, 32);
04953               read_lines -= lines_todo;
04954               wrt_ptr += chunk_size;
04955               if (wrt_ptr >= end_ptr)
04956                 wrt_ptr = buffer;
04957               for (i = 0; i < irgb; i++)
04958                 idx_buf[i]++;
04959               request_data = 0;
04960             }
04961           else if (write_lines)
04962             {
04963               DBG (DBG_error,
04964                    "pie_usb_reader_indexed: deskew failed for %d lines\n",
04965                    write_lines);
04966               write_lines = 0;
04967             }
04968         }
04969     }
04970   gettimeofday (&end_time, NULL);
04971   elapsed_time = ((end_time.tv_sec * 1000000 + end_time.tv_usec)
04972                   - (start_time.tv_sec * 1000000 +
04973                      start_time.tv_usec)) / 1000;
04974   DBG (DBG_read,
04975        "pie_usb_reader_indexed finished %d bytes in %ld ms, returning %s\n",
04976        (scanner->params.lines - read_lines) * scanner->params.bytes_per_line,
04977        elapsed_time, sane_strstatus (status));
04978 
04979   for (i = 0; i < irgb; i++)
04980     free (color_buf[i].b8);
04981   free (buffer);
04982   return status;
04983 }
04984 
04985 #if 0
04986 /* ----------------------- PIE_USB_READER_PROCESS_LINE ------------------------ */
04987 
04988 /* Currently not used, and unused by the Windows programs. The scanners seem to support
04989    INQ_COLOR_FORMAT_LINE delivering ordered RGB data for one line */
04990 
04991 static int
04992 pie_usb_reader_process_line (Pie_Scanner * scanner, FILE * fp)
04993 {
04994   int status;
04995   int lines, lines_todo, chunk_lines;
04996   unsigned char *buffer, *reorder;
04997   size_t size, chunk_size;
04998   DBG (DBG_read,
04999        "pie_usb_reader_process reading %d lines of %d bytes/line\n",
05000        scanner->params.lines, scanner->params.bytes_per_line);
05001   chunk_lines = (scanner->params.lines + 7) / 8;
05002   chunk_size = chunk_lines * scanner->params.bytes_per_line;
05003   if (chunk_size > BUFFER_MAXSIZE)
05004     {
05005       chunk_lines = BUFFER_MAXSIZE / scanner->params.bytes_per_line;
05006       chunk_size = chunk_lines * scanner->params.bytes_per_line;
05007     }
05008   buffer = malloc (chunk_size);
05009   reorder = malloc (chunk_size);
05010   if (!buffer || !reorder)
05011     {
05012       free (buffer);
05013       free (reorder);
05014       return SANE_STATUS_NO_MEM;
05015     }
05016 
05017   lines = scanner->params.lines;
05018   while (lines > 0)
05019     {
05020       lines_todo = chunk_lines;
05021       if (lines_todo > lines)
05022         lines_todo = lines;
05023       set_read_length (sread.cmd, lines_todo);
05024       size = lines_todo * scanner->params.bytes_per_line;
05025       do
05026         {
05027           status =
05028             pie_usb_scsi_wrapper (scanner->sfd, sread.cmd,
05029                                   sread.size, buffer, &size);
05030         }
05031       while (status);
05032       DBG_DUMP (DBG_dump, buffer, 64);
05033       if (scanner->colormode == RGB)
05034         {
05035           int offset = scanner->bytes_per_line;
05036           unsigned char *dest = reorder;
05037           unsigned char *src = buffer;
05038           int i, j;
05039           if (scanner->params.depth > 8)
05040             {
05041               for (j = lines_todo; j > 0; j--)
05042                 {
05043                   for (i = scanner->params.pixels_per_line; i > 0; i--)
05044                     {
05045                       *dest++ = *src;
05046                       *dest++ = *(src + 1);
05047                       *dest++ = *(src + offset);
05048                       *dest++ = *(src + offset + 1);
05049                       *dest++ = *(src + 2 * offset);
05050                       *dest++ = *(src + 2 * offset + 1);
05051                       src++;
05052                       src++;
05053                     }
05054                   src += offset * 2;
05055                 }
05056             }
05057           else
05058             {
05059               for (j = lines_todo; j > 0; j--)
05060                 {
05061                   for (i = scanner->params.pixels_per_line; i > 0; i--)
05062                     {
05063                       *dest++ = *src;
05064                       *dest++ = *(src + offset);
05065                       *dest++ = *(src + 2 * offset);
05066                       src++;
05067                     }
05068                   src += offset * 2;
05069                 }
05070             }
05071           fwrite (reorder, 1, size, fp);
05072         }
05073       else
05074         {
05075           fwrite (buffer, 1, size, fp);
05076         }
05077       lines -= lines_todo;
05078     }
05079 
05080   free (buffer);
05081   free (reorder);
05082   return 0;
05083 }
05084 #endif
05085 
05086 
05087 /* ------------------------ PIE_USB_DO_CANCEL ------------------------------ */
05096 static SANE_Status
05097 pie_usb_do_cancel (Pie_Scanner * scanner, int park)
05098 {
05099 
05100   DBG (DBG_sane_proc, "pie_usb_do_cancel\n");
05101 
05102   if (scanner->scanning)
05103     {
05104       scanner->scanning = SANE_FALSE;
05105 
05106       if (scanner->processing & POST_SW_ACCUM_MASK)     /* single threaded case */
05107         {
05108           cancel_requ = 1;
05109         }
05110       else                              /* threaded or forked case */
05111         {
05112           if (scanner->pipe >= 0)   /* cancel or error */
05113             close (scanner->pipe);
05114 
05115           if (scanner->reader_pid != NO_PID)
05116             {
05117 #if defined USE_PTHREAD || defined HAVE_OS2_H || defined __BEOS__
05118               cancel_requ = 1;
05119 #else
05120               sanei_thread_kill (scanner->reader_pid);
05121 #endif
05122               sanei_thread_waitpid (scanner->reader_pid, 0);
05123               scanner->reader_pid = NO_PID;
05124               DBG (DBG_sane_info, "pie_usb_do_cancel: reader thread finished\n");
05125             }
05126 
05127           if (scanner->pipe >= 0)   /* cancel or error */
05128             {
05129               scanner->pipe = -1;
05130               pie_usb_scan (scanner, 0);
05131             }
05132         }
05133     }
05134   /* greatly improves handling when forked: watch scanner as it returns,
05135    * needs to be checked before another USB command is sent */
05136   if ((scanner->parking_pid == NO_PID) && park)
05137     scanner->parking_pid =
05138         sanei_thread_begin (pie_usb_release_scanner, (void *) scanner);
05139 
05140   return SANE_STATUS_CANCELLED;
05141 }
05142 
05143 
05144 /* ----------------------------- PIE_USB_READER_PROCESS_SIGTERM_HANDLER  -------- */
05148 static RETSIGTYPE
05149 pie_usb_reader_process_sigterm_handler (__sane_unused__ int signal)
05150 {
05151   cancel_requ = 1;
05152   return;
05153 }
05154 
05155 
05156 /* ------------------------ PIE_USB_READER_UNTHREADED ------------------------- */
05171 static SANE_Status
05172 pie_usb_reader_unthreaded (Pie_Scanner * scanner)
05173 {
05174   SANE_Status status;
05175 
05176   DBG (DBG_sane_proc, "pie_usb_reader_unthreaded\n");
05177 
05178   if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX)
05179     {
05180       cancel_requ = 0;              /* assume not canceled yet */
05181 
05182       status = pie_usb_reader_indexed (scanner, NULL);
05183       if (status != SANE_STATUS_GOOD)
05184         {
05185           pie_usb_scan (scanner, 0);
05186           scanner->scanning = SANE_FALSE;
05187         }
05188       else
05189         {
05190           scanner->total_bytes_stored = scanner->params.bytes_per_line *
05191               scanner->params.lines;
05192           scanner->total_bytes_read = 0;
05193         }
05194       return status;
05195     }
05196   else
05197     return SANE_STATUS_UNSUPPORTED;
05198 }
05199 
05200 
05201 /* ------------------------- PIE_USB_READER_PROCESS --------------------------- */
05220 static int
05221 pie_usb_reader_process (void *data)     /* executed as a child process */
05222 {
05223   int status;
05224   FILE *fp;
05225   Pie_Scanner *scanner;
05226   sigset_t ignore_set;
05227   struct SIGACTION act;
05228 
05229   scanner = (Pie_Scanner *) data;
05230 
05231   if (sanei_thread_is_forked ())
05232     {
05233 
05234       close (scanner->pipe);
05235 
05236       sigfillset (&ignore_set);
05237       sigdelset (&ignore_set, SIGTERM);
05238 #if defined (__APPLE__) && defined (__MACH__)
05239       sigdelset (&ignore_set, SIGUSR2);
05240 #endif
05241       sigprocmask (SIG_SETMASK, &ignore_set, 0);
05242 
05243       memset (&act, 0, sizeof (act));
05244       sigaction (SIGTERM, &act, 0);
05245     }
05246 
05247   DBG (DBG_sane_proc, "pie_usb_reader_process started\n");
05248 
05249   cancel_requ = 0;              /* assume not cancelled yet */
05250   memset (&act, 0, sizeof (act));       /* define SIGTERM-handler */
05251   act.sa_handler = pie_usb_reader_process_sigterm_handler;
05252   sigaction (SIGTERM, &act, 0);
05253 
05254   fp = fdopen (scanner->reader_fds, "w");
05255   if (!fp)
05256     return SANE_STATUS_IO_ERROR;
05257 
05258   if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX)
05259     status = pie_usb_reader_indexed (scanner, fp);
05260   else
05261     status = SANE_STATUS_UNSUPPORTED;
05262 
05263   close (scanner->reader_fds);
05264 
05265   DBG (DBG_sane_info, "pie_usb_reader_process: finished reading data\n");
05266 
05267   return status;
05268 }
05269 
05270 
05271 /*
05272  * @@ pie_usb_sane_xy routines replace large parts of the sane_xy functions
05273  */
05274 
05275 /* ------------------------------ PIE_USB_SANE_CONTROL_OPTION -------------------- */
05281 static SANE_Status
05282 pie_usb_sane_control_option (SANE_Handle handle, SANE_Int option,
05283                              SANE_Action action, void *val, SANE_Int * info)
05284 {
05285   Pie_Scanner *scanner = handle;
05286   SANE_Status status;
05287   SANE_Word cap;
05288   SANE_Int l_info;
05289   SANE_String_Const name;
05290 
05291   l_info = 0;
05292   if (info)
05293     *info = l_info;
05294 
05295   if (scanner->scanning)
05296     return SANE_STATUS_DEVICE_BUSY;
05297 
05298   if ((unsigned) option >= NUM_OPTIONS)
05299     return SANE_STATUS_INVAL;
05300 
05301   cap = scanner->opt[option].cap;
05302   if (!SANE_OPTION_IS_ACTIVE (cap))
05303     return SANE_STATUS_INVAL;
05304 
05305   name = scanner->opt[option].name;
05306   if (!name)
05307     name = "(no name)";
05308 
05309   if (action == SANE_ACTION_GET_VALUE)
05310     {
05311 
05312       DBG (DBG_sane_option, "get %s [#%d]\n", name, option);
05313 
05314       switch (option)
05315         {
05316           /* word options: */
05317         case OPT_NUM_OPTS:
05318         case OPT_BIT_DEPTH:
05319         case OPT_RESOLUTION:
05320         case OPT_TL_X:
05321         case OPT_TL_Y:
05322         case OPT_BR_X:
05323         case OPT_BR_Y:
05324         case OPT_PREVIEW:
05325         case OPT_SW_GRAIN:
05326         case OPT_SW_SRGB:
05327         case OPT_SW_NEGA:
05328           *(SANE_Word *) val = scanner->val[option].w;
05329           break;
05330 
05331           /* string options: */
05332         case OPT_MODE:
05333         case OPT_SPEED:
05334         case OPT_SW_IRED:
05335         case OPT_SW_CROP:
05336           strcpy (val, scanner->val[option].s);
05337         }
05338 
05339       return SANE_STATUS_GOOD;
05340     }
05341   else if (action == SANE_ACTION_SET_VALUE)
05342     {
05343       switch (scanner->opt[option].type)
05344         {
05345         case SANE_TYPE_INT:
05346           DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option,
05347                *(SANE_Word *) val);
05348           break;
05349 
05350         case SANE_TYPE_FIXED:
05351           DBG (DBG_sane_option, "set %s [#%d] to %f\n", name, option,
05352                SANE_UNFIX (*(SANE_Word *) val));
05353           break;
05354 
05355         case SANE_TYPE_STRING:
05356           DBG (DBG_sane_option, "set %s [#%d] to %s\n", name, option,
05357                (char *) val);
05358           break;
05359 
05360         case SANE_TYPE_BOOL:
05361           DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option,
05362                *(SANE_Word *) val);
05363           break;
05364 
05365         default:
05366           DBG (DBG_sane_option, "set %s [#%d]\n", name, option);
05367         }
05368 
05369       if (!SANE_OPTION_IS_SETTABLE (cap))
05370         return SANE_STATUS_INVAL;
05371 
05372       status = sanei_constrain_value (scanner->opt + option, val, &l_info);
05373       if (status != SANE_STATUS_GOOD)
05374         return status;
05375 
05376       switch (option)
05377         {
05378           /* (mostly) side-effect-free word options: */
05379         case OPT_RESOLUTION:
05380         case OPT_TL_X:
05381         case OPT_TL_Y:
05382         case OPT_BR_X:
05383         case OPT_BR_Y:
05384           l_info |= SANE_INFO_RELOAD_PARAMS;
05385           /* fall through */
05386         case OPT_NUM_OPTS:
05387         case OPT_PREVIEW:
05388         case OPT_BIT_DEPTH:
05389         case OPT_SW_GRAIN:
05390         case OPT_SW_SRGB:
05391         case OPT_SW_NEGA:
05392           scanner->val[option].w = *(SANE_Word *) val;
05393           break;
05394           /* (mostly) side-effect-free string options: */
05395         case OPT_SPEED:
05396         case OPT_SW_IRED:
05397         case OPT_SW_CROP:
05398           if (scanner->val[option].s)
05399             free (scanner->val[option].s);
05400           scanner->val[option].s = (SANE_Char *) strdup (val);
05401           break;
05402           /* options with side-effects: */
05403         case OPT_MODE:
05404           {
05405             int is_rgbi = (strcmp (val, COLOR_IR_STR) == 0);
05406 
05407             if (scanner->val[option].s)
05408               free (scanner->val[option].s);
05409             scanner->val[option].s = (SANE_Char *) strdup (val);
05410             l_info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
05411 
05412             if (is_rgbi)
05413               {
05414                 scanner->opt[OPT_SW_IRED].cap &= ~SANE_CAP_INACTIVE;
05415               }
05416             else
05417               {
05418                         scanner->opt[OPT_SW_IRED].cap |= SANE_CAP_INACTIVE;
05419               }
05420             break;
05421           }
05422         }
05423 
05424       if (info)
05425         *info = l_info;
05426       return SANE_STATUS_GOOD;
05427     }                           /* else */
05428   return SANE_STATUS_INVAL;
05429 }
05430 
05431 
05432 /* ------------------------------------ PIE_USB_SANE_START ------------------------------ */
05440 static SANE_Status
05441 pie_usb_sane_start (Pie_Scanner * scanner)
05442 {
05443   const char *mode;
05444   const char *prired;
05445   SANE_Status status;
05446   int fds[2];
05447 
05448   DBG (DBG_sane_init, "pie_usb_sane_start\n");
05449 
05450   mode = scanner->val[OPT_MODE].s;
05451   prired = scanner->val[OPT_SW_IRED].s;
05452 
05453   status = pie_usb_is_scanner_released (scanner);
05454   if (status != SANE_STATUS_GOOD)
05455     return status;
05456   pie_power_save (scanner, 0);
05457 
05458   scanner->colormode = RGB;
05459   scanner->processing = 0;
05460   if (scanner->val[OPT_PREVIEW].w != SANE_TRUE)
05461     {
05462       if (strcmp (mode, COLOR_IR_STR) == 0)
05463         {
05464           scanner->colormode = RGBI;
05465           if (strcmp (prired, IR_CLEAN_STR) == 0)
05466             scanner->processing |= POST_SW_DIRT;
05467           else
05468             if (strcmp (prired, IR_SPECT_STR) == 0)
05469               scanner->processing |= POST_SW_IRED;
05470         }
05471       if (scanner->val[OPT_SW_GRAIN].w != 0)
05472         scanner->processing |= POST_SW_GRAIN;
05473       if (strcmp (scanner->val[OPT_SW_CROP].s, THE_NONE_STR) != 0)
05474         scanner->processing |= POST_SW_CROP;
05475     }
05476   if ((scanner->val[OPT_SW_SRGB].w == SANE_TRUE) ||
05477       (scanner->val[OPT_SW_NEGA].w == SANE_TRUE))
05478     scanner->processing |= POST_SW_COLORS;
05479 
05480   /* get and set geometric values for scanning */
05481   scanner->resolution = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w);
05482 
05483   scanner->scanning = SANE_TRUE;        /* definetly ! */
05484 
05485   status = pie_send_exposure (scanner);
05486   if (status != SANE_STATUS_GOOD)
05487     return status;
05488   status = pie_send_highlight_shadow (scanner);
05489   if (status != SANE_STATUS_GOOD)
05490     return status;
05491   status = pie_usb_set_window (scanner);
05492   if (status != SANE_STATUS_GOOD)
05493     return status;
05494   status = pie_usb_calibration_send (scanner, 0);
05495   if (status != SANE_STATUS_GOOD)
05496     return status;
05497   status = pie_usb_mode_select (scanner);
05498   if (status != SANE_STATUS_GOOD)
05499     return status;
05500 
05501   status = pie_usb_scan (scanner, 1);
05502   if (status != SANE_STATUS_GOOD)
05503     return status;
05504 
05505   /* if calibration data is there !! we have to get it */
05506   if (scanner->cal_mode != scanner->device->model->op_mode[OPM_SKIPCAL])
05507     {
05508       status = pie_usb_calibrate (scanner);
05509       if (status != SANE_STATUS_GOOD)
05510         return status;
05511     }
05512   status = pie_usb_copy_sensors (scanner);
05513   if (status != SANE_STATUS_GOOD)
05514     return status;
05515 
05516   status = pie_usb_get_params (scanner);
05517   if (status != SANE_STATUS_GOOD)
05518     return status;
05519 
05520   if (scanner->processing & POST_SW_ACCUM_MASK)
05521     {
05522       if (scanner->img_buffer.b8)       /* reset buffer */
05523         free (scanner->img_buffer.b8);
05524       scanner->img_buffer.b8 = NULL;
05525       scanner->total_bytes_stored = 0;
05526       scanner->total_bytes_read = 0;
05527 
05528       if (scanner->processing & POST_SW_CROP)
05529         return pie_usb_reader_unthreaded (scanner);
05530       else
05531         return SANE_STATUS_GOOD;
05532     }
05533   else
05534     {
05535       if (pipe (fds) < 0)           /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */
05536         {
05537           DBG (DBG_error, "pie_usb_sane_start: could not create pipe\n");
05538           scanner->scanning = SANE_FALSE;
05539           pie_usb_scan (scanner, 0);
05540           return SANE_STATUS_IO_ERROR;
05541         }
05542 
05543       scanner->pipe = fds[0];
05544       scanner->reader_fds = fds[1];
05545       scanner->reader_pid =
05546         sanei_thread_begin (pie_usb_reader_process, (void *) scanner);
05547 
05548       if (scanner->reader_pid == NO_PID)
05549         {
05550           DBG (DBG_error, "pie_usb_sane_start: sanei_thread_begin failed (%s)\n",
05551                strerror (errno));
05552           return SANE_STATUS_NO_MEM;
05553         }
05554 
05555       if (sanei_thread_is_forked ())
05556         {
05557           close (scanner->reader_fds);
05558           scanner->reader_fds = -1;
05559         }
05560 
05561       return SANE_STATUS_GOOD;
05562     }
05563 }
05564 
05565 
05566 /* ---------------------------------- PIE_USB_SANE_READ ------------------------------ */
05574 static SANE_Status
05575 pie_usb_sane_read (Pie_Scanner * scanner, SANE_Byte * buf, SANE_Int max_len,
05576                    SANE_Int * len)
05577 {
05578   SANE_Status status;
05579   ssize_t nread;
05580 
05581   DBG (DBG_sane_proc, "pie_usb_sane_read\n");
05582 
05583   if (!(scanner->scanning))     /* OOPS, not scanning */
05584     return SANE_STATUS_CANCELLED;
05585 
05586   if (scanner->processing & POST_SW_ACCUM_MASK)
05587     {
05588       if (scanner->total_bytes_stored == 0)
05589         {
05590           status = pie_usb_reader_unthreaded (scanner);
05591           if (status != SANE_STATUS_GOOD)
05592             return status;
05593         }
05594 
05595       nread = max_len;
05596       if(scanner->total_bytes_read + nread > scanner->total_bytes_stored)
05597         nread = scanner->total_bytes_stored - scanner->total_bytes_read;
05598       if (nread <= 0)
05599         return SANE_STATUS_EOF;
05600 
05601       DBG (DBG_sane_info, "pie_usb_sane_read: copy %ld bytes\n", (long) nread);
05602       memcpy (buf, scanner->img_buffer.b8 + scanner->total_bytes_read, nread);
05603       scanner->total_bytes_read += nread;
05604       *len = nread;
05605       return SANE_STATUS_GOOD;
05606     }
05607   else
05608     {
05609       /* threaded or forked, read from pipe */
05610       nread = read (scanner->pipe, buf, max_len);
05611       DBG (DBG_sane_info, "pie_usb_sane_read: read %ld bytes\n", (long) nread);
05612 
05613       if (nread < 0)
05614         {
05615           if (errno == EAGAIN)
05616             {
05617               DBG (DBG_sane_info, "pie_usb_sane_read: EAGAIN\n");
05618               return SANE_STATUS_GOOD;
05619             }
05620           else
05621             {
05622               pie_usb_do_cancel (scanner, SANE_TRUE);  /* error, stop scanner */
05623               return SANE_STATUS_IO_ERROR;
05624             }
05625         }
05626 
05627       *len = nread;
05628 
05629       if (nread == 0)               /* EOF */
05630         {
05631           /* presumably normal close of pipe, tell
05632              pie_usb_do_cancel to ommit some commands */
05633           close (scanner->pipe);
05634           scanner->pipe = -1;
05635           pie_usb_do_cancel (scanner, SANE_FALSE);
05636           return SANE_STATUS_EOF;
05637         }
05638 
05639       return SANE_STATUS_GOOD;
05640     }
05641 }
05642 
05643 
05644 /* ----------------------------------- PIE_USB_SANE_OPEN ------------------------------ */
05656 static SANE_Status
05657 pie_usb_sane_open (Pie_Scanner * scanner, SANE_Handle * handle)
05658 {
05659   SANE_Status status;
05660   double di;
05661   int buf_size, i;
05662 
05663   DBG (DBG_sane_proc, "pie_usb_sane_open started\n");
05664 
05665   status = pie_usb_attach_open (scanner->device->sane.name, &(scanner->sfd));
05666   if (status != SANE_STATUS_GOOD)
05667     {
05668       DBG (DBG_error, "pie_usb_sane_open: open failed\n");
05669       return SANE_STATUS_INVAL;
05670     }
05671 
05672   /* During initial internal calibration of the scanner we can not issue all commands to
05673      complete our setup so the frontend will have to wait at some point. We have to
05674      query the scanner for initalizing options here. */
05675   status = pie_usb_is_scanner_initialized (scanner->sfd);
05676   if (status != SANE_STATUS_GOOD)
05677     return status;
05678 
05679   if (scanner->device->cal_info_count == 0)
05680     {
05681       pie_get_halftones (scanner->device, scanner->sfd);
05682       pie_get_cal_info (scanner->device, scanner->sfd);
05683       pie_get_speeds (scanner->device);
05684     }
05685   scanner->cal_mode = scanner->device->model->op_mode[OPM_QUALITY];     /* calibrate the first time */
05686   scanner->reader_pid = NO_PID;
05687   scanner->parking_pid = NO_PID;
05688 
05689   scanner->cal_data = malloc (sizeof (PIE_USB_Calibration));
05690   if (!scanner->cal_data)
05691     return SANE_STATUS_NO_MEM;
05692   buf_size = scanner->device->cal_info[0].pixels_per_line;
05693   scanner->cal_data->sensors = malloc (buf_size);
05694   if (!scanner->cal_data->sensors)
05695     return SANE_STATUS_NO_MEM;
05696   buf_size *= 4 * sizeof (int);
05697   scanner->cal_data->shades = malloc (buf_size);
05698   if (!scanner->cal_data->shades)
05699     return SANE_STATUS_NO_MEM;
05700 
05701   memcpy (&scanner->cal_data->cal_hiqual,
05702           &scanner->device->model->default_hiqual,
05703           sizeof (PIE_USB_Calibration_Set));
05704   memcpy (&scanner->cal_data->cal_normal,
05705           &scanner->device->model->default_normal,
05706           sizeof (PIE_USB_Calibration_Set));
05707   for (i = 0; i < 3; i++)
05708     scanner->cal_data->brightness[i] =
05709       scanner->device->model->default_brightness;
05710 
05711   /* gamma lookup tables */
05712   scanner->gamma_lut8 = malloc (256 * sizeof (double));
05713   if (!scanner->gamma_lut8)
05714     return SANE_STATUS_NO_MEM;
05715   di = 255.0 / pow (255.0, CONST_GAMMA);
05716   for (i = 0; i < 256; i++)
05717     scanner->gamma_lut8[i] = di * pow ((double) i, CONST_GAMMA);
05718   scanner->gamma_lut16 = malloc (65536 * sizeof (double));
05719   if (!scanner->gamma_lut16)
05720     return SANE_STATUS_NO_MEM;
05721   di = 65535.0 / pow (65535.0, CONST_GAMMA);
05722   for (i = 0; i < 65536; i++)
05723     scanner->gamma_lut16[i] = di * pow ((double) i, CONST_GAMMA);
05724 
05725   pie_init_options (scanner);
05726 
05727   /* ln lookup table for infrared cleaning */
05728   status = sane_ir_ln_table (65536, &scanner->ln_lut);
05729   if (status != SANE_STATUS_GOOD)
05730     return status;
05731 
05732   /* storage for software processing of whole image */
05733   scanner->img_buffer.b8 = NULL;
05734   scanner->total_bytes_stored = 0;
05735   scanner->total_bytes_read = 0;
05736 
05737   scanner->next = first_handle; /* insert newly opened handle into list of open handles: */
05738   first_handle = scanner;
05739   *handle = scanner;
05740 
05741   return SANE_STATUS_GOOD;
05742 }
05743 
05744 
05745 /* -------------------------------- PIE_USB_SANE_CLOSE ----------------------------- */
05751 static void
05752 pie_usb_sane_close (Pie_Scanner * scanner)
05753 {
05754   DBG (DBG_sane_proc, "pie_usb_sane_close started\n");
05755 
05756   if (scanner->scanning)        /* stop scan if still scanning */
05757     pie_usb_do_cancel (scanner, SANE_TRUE);
05758 
05759   pie_usb_is_scanner_released (scanner);    /* not yet in parking position? */
05760 
05761   if (scanner->sfd >= 0)
05762     {
05763       sanei_usb_reset (scanner->sfd);   /* close USB */
05764       sanei_usb_close (scanner->sfd);
05765     }
05766 
05767   if (scanner->cal_data)        /* free calibration data */
05768     {
05769       if (scanner->cal_data->shades)
05770         free (scanner->cal_data->shades);
05771       if (scanner->cal_data->sensors)
05772         free (scanner->cal_data->sensors);
05773       free (scanner->cal_data);
05774     }
05775 
05776   /* ln lookup table for infrared cleaning */
05777   free (scanner->ln_lut);
05778   /* gamma lookup tables */
05779   free (scanner->gamma_lut8);
05780   free (scanner->gamma_lut16);
05781 
05782   /* whole last image */
05783   if (scanner->img_buffer.b8)
05784     free (scanner->img_buffer.b8);
05785 
05786   return;
05787 }
05788 
05789 
05790 /*
05791  * @@ Original SCSI functions: Some of them call the pie_usb code
05792  *    using the (*scanner->device->scsi_cmd) function pointer.
05793  */
05794 
05795 /*------------------------- PIE POWER SAVE -----------------------------*/
05796 
05797 static SANE_Status
05798 pie_power_save (Pie_Scanner * scanner, int time)
05799 {
05800   unsigned char buffer[128];
05801   size_t size;
05802   SANE_Status status;
05803   unsigned char *data;
05804 
05805   DBG (DBG_proc, "pie_power_save: %d min\n", time);
05806 
05807   size = 6;
05808 
05809   set_write_length (swrite.cmd, size);
05810 
05811   memcpy (buffer, swrite.cmd, swrite.size);
05812 
05813   data = buffer + swrite.size;
05814   memset (data, 0, size);
05815 
05816   set_command (data, SET_POWER_SAVE_CONTROL);
05817   set_data_length (data, size - 4);
05818   data[4] = time & 0x7f;
05819 
05820   status =
05821     (*scanner->device->scsi_cmd) (scanner->sfd, buffer, swrite.size + size,
05822                                   NULL, NULL);
05823   if (status)
05824     {
05825       DBG (DBG_error, "pie_power_save: write command returned status %s\n",
05826            sane_strstatus (status));
05827     }
05828 
05829   return status;
05830 }
05831 
05832 
05833 /*------------------------- PIE SEND EXPOSURE ONE -----------------------------*/
05834 
05835 
05836 static SANE_Status
05837 pie_send_exposure_one (Pie_Scanner * scanner, int filter, int value)
05838 {
05839   unsigned char buffer[128];
05840   size_t size;
05841   SANE_Status status;
05842   unsigned char *data;
05843 
05844   DBG (DBG_proc, "pie_send_exposure_one\n");
05845 
05846   size = 8;
05847 
05848   set_write_length (swrite.cmd, size);
05849 
05850   memcpy (buffer, swrite.cmd, swrite.size);
05851 
05852   data = buffer + swrite.size;
05853   memset (data, 0, size);
05854 
05855   set_command (data, SET_EXP_TIME);
05856   set_data_length (data, size - 4);
05857 
05858   data[4] = filter;
05859 
05860   set_data (data, 6, (int) value, 2);
05861 
05862   status =
05863     (*scanner->device->scsi_cmd) (scanner->sfd, buffer, swrite.size + size,
05864                                   NULL, NULL);
05865   if (status)
05866     {
05867       DBG (DBG_error,
05868            "pie_send_exposure_one: write command returned status %s\n",
05869            sane_strstatus (status));
05870     }
05871 
05872   return status;
05873 }
05874 
05875 /*------------------------- PIE SEND EXPOSURE -----------------------------*/
05876 
05877 static SANE_Status
05878 pie_send_exposure (Pie_Scanner * scanner)
05879 {
05880   SANE_Status status;
05881 
05882   DBG (DBG_proc, "pie_send_exposure\n");
05883 
05884   status = pie_send_exposure_one (scanner, FILTER_RED, 100);
05885   if (status)
05886     return status;
05887 
05888   status = pie_send_exposure_one (scanner, FILTER_GREEN, 100);
05889   if (status)
05890     return status;
05891 
05892   status = pie_send_exposure_one (scanner, FILTER_BLUE, 100);
05893   if (status)
05894     return status;
05895 
05896   return SANE_STATUS_GOOD;
05897 }
05898 
05899 
05900 /*------------------------- PIE SEND HIGHLIGHT/SHADOW ONE -----------------------------*/
05901 
05902 static SANE_Status
05903 pie_send_highlight_shadow_one (Pie_Scanner * scanner, int filter,
05904                                int highlight, int shadow)
05905 {
05906   unsigned char buffer[128];
05907   size_t size;
05908   SANE_Status status;
05909   unsigned char *data;
05910 
05911   DBG (DBG_proc, "pie_send_highlight_shadow_one\n");
05912 
05913   size = 8;
05914 
05915   set_write_length (swrite.cmd, size);
05916 
05917   memcpy (buffer, swrite.cmd, swrite.size);
05918 
05919   data = buffer + swrite.size;
05920   memset (data, 0, size);
05921 
05922   set_command (data, SET_EXP_TIME);
05923   set_data_length (data, size - 4);
05924 
05925   data[4] = filter;
05926 
05927   data[6] = highlight;
05928   data[7] = shadow;
05929 
05930   status =
05931     (*scanner->device->scsi_cmd) (scanner->sfd, buffer, swrite.size + size,
05932                                   NULL, NULL);
05933   if (status)
05934     {
05935       DBG (DBG_error,
05936            "pie_send_highlight_shadow_one: write command returned status %s\n",
05937            sane_strstatus (status));
05938     }
05939 
05940   return status;
05941 }
05942 
05943 /*------------------------- PIE SEND HIGHLIGHT/SHADOW -----------------------------*/
05944 
05945 static SANE_Status
05946 pie_send_highlight_shadow (Pie_Scanner * scanner)
05947 {
05948   SANE_Status status;
05949 
05950   DBG (DBG_proc, "pie_send_highlight_shadow\n");
05951 
05952   status = pie_send_highlight_shadow_one (scanner, FILTER_RED, 100, 0);
05953   if (status)
05954     return status;
05955 
05956   status = pie_send_highlight_shadow_one (scanner, FILTER_GREEN, 100, 0);
05957   if (status)
05958     return status;
05959 
05960   status = pie_send_highlight_shadow_one (scanner, FILTER_BLUE, 100, 0);
05961   if (status)
05962     return status;
05963 
05964   return SANE_STATUS_GOOD;
05965 }
05966 
05967 /*------------------------- PIE PERFORM CAL ----------------------------*/
05968 
05969 static SANE_Status
05970 pie_perform_cal (Pie_Scanner * scanner, int cal_index)
05971 {
05972   long *red_result;
05973   long *green_result;
05974   long *blue_result;
05975   long *neutral_result;
05976   long *result = NULL;
05977   int rcv_length, send_length;
05978   int rcv_lines, rcv_bits, send_bits;
05979   int pixels_per_line;
05980   int i;
05981   unsigned char *rcv_buffer, *rcv_ptr;
05982   unsigned char *send_buffer, *send_ptr;
05983   size_t size;
05984   int fullscale;
05985   int cal_limit;
05986   int k;
05987   int filter;
05988   SANE_Status status;
05989 
05990   DBG (DBG_proc, "pie_perform_cal\n");
05991 
05992   pixels_per_line = scanner->device->cal_info[cal_index].pixels_per_line;
05993   rcv_length = pixels_per_line;
05994   send_length = pixels_per_line;
05995 
05996   rcv_bits = scanner->device->cal_info[cal_index].receive_bits;
05997   if (rcv_bits > 8)
05998     rcv_length *= 2;            /* 2 bytes / sample */
05999 
06000   send_bits = scanner->device->cal_info[cal_index].send_bits;
06001   if (send_bits > 8)
06002     send_length *= 2;           /* 2 bytes / sample */
06003 
06004   rcv_lines = scanner->device->cal_info[cal_index].num_lines;
06005 
06006   send_length += 2;             /* space for filter at start */
06007 
06008   if (scanner->colormode == RGB)
06009     {
06010       rcv_lines *= 3;
06011       send_length *= 3;
06012       rcv_length += 2;          /* 2 bytes for index at front of data (only in RGB??) */
06013     }
06014 
06015   send_length += 4;             /* space for header at start of data */
06016 
06017   /* alllocate buffers for the receive data, the result buffers, and for the send data */
06018   rcv_buffer = (unsigned char *) malloc (rcv_length);
06019 
06020   red_result = (long *) calloc (pixels_per_line, sizeof (long));
06021   green_result = (long *) calloc (pixels_per_line, sizeof (long));
06022   blue_result = (long *) calloc (pixels_per_line, sizeof (long));
06023   neutral_result = (long *) calloc (pixels_per_line, sizeof (long));
06024 
06025   if (!rcv_buffer || !red_result || !green_result || !blue_result
06026       || !neutral_result)
06027     {
06028       /* at least one malloc failed, so free all buffers (free accepts NULL) */
06029       free (rcv_buffer);
06030       free (red_result);
06031       free (green_result);
06032       free (blue_result);
06033       free (neutral_result);
06034       return SANE_STATUS_NO_MEM;
06035     }
06036 
06037   /* read the cal data a line at a time, and accumulate into the result arrays */
06038   while (rcv_lines--)
06039     {
06040       /* TUR */
06041       status = pie_wait_scanner (scanner);
06042       if (status)
06043         {
06044           free (rcv_buffer);
06045           free (red_result);
06046           free (green_result);
06047           free (blue_result);
06048           free (neutral_result);
06049           return status;
06050         }
06051 
06052       set_read_length (sread.cmd, 1);
06053       size = rcv_length;
06054 
06055       DBG (DBG_info, "pie_perform_cal: reading 1 line (%lu bytes)\n",
06056            (u_long) size);
06057 
06058       status =
06059         sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, rcv_buffer,
06060                         &size);
06061 
06062       if (status)
06063         {
06064           DBG (DBG_error,
06065                "pie_perform_cal: read command returned status %s\n",
06066                sane_strstatus (status));
06067           free (rcv_buffer);
06068           free (red_result);
06069           free (green_result);
06070           free (blue_result);
06071           free (neutral_result);
06072           return status;
06073         }
06074 
06075       DBG_DUMP (DBG_dump, rcv_buffer, 32);
06076 
06077       /* which result buffer does this line belong to? */
06078       if (scanner->colormode == RGB)
06079         {
06080           if (*rcv_buffer == 'R')
06081             result = red_result;
06082           else if (*rcv_buffer == 'G')
06083             result = green_result;
06084           else if (*rcv_buffer == 'B')
06085             result = blue_result;
06086           else if (*rcv_buffer == 'N')
06087             result = neutral_result;
06088           else
06089             {
06090               DBG (DBG_error, "pie_perform_cal: invalid index byte (%02x)\n",
06091                    *rcv_buffer);
06092               DBG_DUMP (DBG_error, rcv_buffer, 32);
06093               free (rcv_buffer);
06094               free (red_result);
06095               free (green_result);
06096               free (blue_result);
06097               free (neutral_result);
06098               return SANE_STATUS_INVAL;
06099             }
06100           rcv_ptr = rcv_buffer + 2;
06101         }
06102       else
06103         {
06104           /* monochrome - no bytes indicating filter here */
06105           result = neutral_result;
06106           rcv_ptr = rcv_buffer;
06107         }
06108 
06109       /* now add the values in this line to the result array */
06110       for (i = 0; i < pixels_per_line; i++)
06111         {
06112           result[i] += *rcv_ptr++;
06113           if (rcv_bits > 8)
06114             {
06115               result[i] += (*rcv_ptr++) << 8;
06116             }
06117         }
06118     }
06119 
06120   /* got all the cal data, now process it ready to send back */
06121   free (rcv_buffer);
06122   send_buffer = (unsigned char *) malloc (send_length + swrite.size);
06123 
06124   if (!send_buffer)
06125     {
06126       free (red_result);
06127       free (green_result);
06128       free (blue_result);
06129       free (neutral_result);
06130       return SANE_STATUS_NO_MEM;
06131     }
06132 
06133   rcv_lines = scanner->device->cal_info[cal_index].num_lines;
06134   fullscale = (1 << rcv_bits) - 1;
06135   cal_limit = fullscale / (1 << scanner->device->inquiry_cal_eqn);
06136   k = (1 << scanner->device->inquiry_cal_eqn) - 1;
06137 
06138   /* set up scsi command and data */
06139   size = send_length;
06140 
06141   memcpy (send_buffer, swrite.cmd, swrite.size);
06142   set_write_length (send_buffer, size);
06143 
06144   set_command (send_buffer + swrite.size, SEND_CAL_DATA);
06145   set_data_length (send_buffer + swrite.size, size - 4);
06146 
06147   send_ptr = send_buffer + swrite.size + 4;
06148 
06149   for (filter = FILTER_NEUTRAL; filter <= FILTER_BLUE; filter <<= 1)
06150     {
06151 
06152       /* only send data for filter we expect to send */
06153       if (!(filter & scanner->cal_filter))
06154         continue;
06155 
06156       set_data (send_ptr, 0, filter, 2);
06157       send_ptr += 2;
06158 
06159       if (scanner->colormode == RGB)
06160         {
06161           switch (filter)
06162             {
06163             case FILTER_RED:
06164               result = red_result;
06165               break;
06166 
06167             case FILTER_GREEN:
06168               result = green_result;
06169               break;
06170 
06171             case FILTER_BLUE:
06172               result = blue_result;
06173               break;
06174 
06175             case FILTER_NEUTRAL:
06176               result = neutral_result;
06177               break;
06178             }
06179         }
06180       else
06181         result = neutral_result;
06182 
06183       /* for each pixel */
06184       for (i = 0; i < pixels_per_line; i++)
06185         {
06186           long x;
06187 
06188           /* make average */
06189           x = result[i] / rcv_lines;
06190 
06191           /* ensure not overflowed */
06192           if (x > fullscale)
06193             x = fullscale;
06194 
06195           /* process according to required calibration equation */
06196           if (scanner->device->inquiry_cal_eqn)
06197             {
06198               if (x <= cal_limit)
06199                 x = fullscale;
06200               else
06201                 x = ((fullscale - x) * fullscale) / (x * k);
06202             }
06203 
06204           if (rcv_bits > send_bits)
06205             x >>= (rcv_bits - send_bits);
06206           else if (send_bits > rcv_bits)
06207             x <<= (send_bits - rcv_bits);
06208 
06209           /* put result into send buffer */
06210           *send_ptr++ = x;
06211           if (send_bits > 8)
06212             *send_ptr++ = x >> 8;
06213         }
06214     }
06215 
06216   /* now send the data back to scanner */
06217 
06218   /* TUR */
06219   status = pie_wait_scanner (scanner);
06220   if (status)
06221     {
06222       free (red_result);
06223       free (green_result);
06224       free (blue_result);
06225       free (neutral_result);
06226       free (send_buffer);
06227       return status;
06228     }
06229 
06230   DBG (DBG_info, "pie_perform_cal: sending cal data (%lu bytes)\n",
06231        (u_long) size);
06232   DBG_DUMP (DBG_dump, send_buffer, 64);
06233 
06234   status =
06235     sanei_scsi_cmd (scanner->sfd, send_buffer, swrite.size + size, NULL,
06236                     NULL);
06237   if (status)
06238     {
06239       DBG (DBG_error, "pie_perform_cal: write command returned status %s\n",
06240            sane_strstatus (status));
06241       free (red_result);
06242       free (green_result);
06243       free (blue_result);
06244       free (neutral_result);
06245       free (send_buffer);
06246       return status;
06247     }
06248 
06249   free (red_result);
06250   free (green_result);
06251   free (blue_result);
06252   free (neutral_result);
06253   free (send_buffer);
06254 
06255   return SANE_STATUS_GOOD;
06256 }
06257 
06258 /*------------------------- PIE DO CAL -----------------------------*/
06259 
06260 static SANE_Status
06261 pie_do_cal (Pie_Scanner * scanner)
06262 {
06263   SANE_Status status;
06264   int cal_index;
06265 
06266   DBG (DBG_proc, "pie_do_cal\n");
06267 
06268   if (scanner->device->inquiry_scan_capability & INQ_CAP_EXT_CAL)
06269     {
06270       for (cal_index = 0; cal_index < scanner->device->cal_info_count;
06271            cal_index++)
06272         if (scanner->device->cal_info[cal_index].cal_type ==
06273             scanner->cal_mode)
06274           {
06275             status = pie_perform_cal (scanner, cal_index);
06276             if (status != SANE_STATUS_GOOD)
06277               return status;
06278           }
06279     }
06280 
06281   return SANE_STATUS_GOOD;
06282 }
06283 
06284 /*------------------------- PIE DWNLD GAMMA ONE -----------------------------*/
06285 
06286 static SANE_Status
06287 pie_dwnld_gamma_one (Pie_Scanner * scanner, int filter, SANE_Int * table)
06288 {
06289   unsigned char *buffer;
06290   size_t size;
06291   SANE_Status status;
06292   unsigned char *data;
06293   int i;
06294 
06295   DBG (DBG_proc, "pie_dwnld_gamma_one\n");
06296 
06297   /* TUR */
06298   status = pie_wait_scanner (scanner);
06299   if (status)
06300     {
06301       return status;
06302     }
06303 
06304   if (scanner->device->inquiry_gamma_bits > 8)
06305     size = scanner->gamma_length * 2 + 6;
06306   else
06307     size = scanner->gamma_length + 6;
06308 
06309   buffer = malloc (size + swrite.size);
06310   if (!buffer)
06311     return SANE_STATUS_NO_MEM;
06312 
06313   set_write_length (swrite.cmd, size);
06314 
06315   memcpy (buffer, swrite.cmd, swrite.size);
06316 
06317   data = buffer + swrite.size;
06318   memset (data, 0, size);
06319 
06320   set_command (data, DWNLD_GAMMA_TABLE);
06321   set_data_length (data, size - 4);
06322 
06323   data[4] = filter;
06324 
06325   for (i = 0; i < scanner->gamma_length; i++)
06326     {
06327       if (scanner->device->inquiry_gamma_bits > 8)
06328         {
06329           set_data (data, 6 + 2 * i, table ? table[i] : i, 2);
06330         }
06331       else
06332         {
06333           set_data (data, 6 + i, table ? table[i] : i, 1);
06334         }
06335     }
06336 
06337   DBG_DUMP (DBG_dump, data, 128);
06338 
06339   status =
06340     sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
06341   if (status)
06342     {
06343       DBG (DBG_error,
06344            "pie_dwnld_gamma_one: write command returned status %s\n",
06345            sane_strstatus (status));
06346     }
06347 
06348   free (buffer);
06349 
06350   return status;
06351 }
06352 
06353 /*------------------------- PIE DWNLD GAMMA -----------------------------*/
06354 
06355 static SANE_Status
06356 pie_dwnld_gamma (Pie_Scanner * scanner)
06357 {
06358   SANE_Status status;
06359 
06360   DBG (DBG_proc, "pie_dwnld_gamma\n");
06361 
06362   if (scanner->colormode == RGB)
06363     {
06364       status =
06365         pie_dwnld_gamma_one (scanner, FILTER_RED, scanner->gamma_table[1]);
06366       if (status)
06367         return status;
06368 
06369 
06370       status =
06371         pie_dwnld_gamma_one (scanner, FILTER_GREEN, scanner->gamma_table[2]);
06372       if (status)
06373         return status;
06374 
06375       status =
06376         pie_dwnld_gamma_one (scanner, FILTER_BLUE, scanner->gamma_table[3]);
06377       if (status)
06378         return status;
06379     }
06380   else
06381     {
06382       SANE_Int *table;
06383 
06384       /* if lineart or half tone, force gamma to be one to one by passing NULL */
06385       if (scanner->colormode == GRAYSCALE)
06386         table = scanner->gamma_table[0];
06387       else
06388         table = NULL;
06389 
06390       status = pie_dwnld_gamma_one (scanner, FILTER_GREEN, table);
06391       if (status)
06392         return status;
06393     }
06394 
06395   usleep (DOWNLOAD_GAMMA_WAIT_TIME);
06396 
06397   return SANE_STATUS_GOOD;
06398 }
06399 
06400 /*------------------------- PIE SET WINDOW -----------------------------*/
06401 
06402 static SANE_Status
06403 pie_set_window (Pie_Scanner * scanner)
06404 {
06405   unsigned char buffer[128];
06406   size_t size;
06407   SANE_Status status;
06408   unsigned char *data;
06409   double x, dpmm;
06410 
06411   DBG (DBG_proc, "pie_set_window\n");
06412 
06413   size = 14;
06414 
06415   set_write_length (swrite.cmd, size);
06416 
06417   memcpy (buffer, swrite.cmd, swrite.size);
06418 
06419   data = buffer + swrite.size;
06420   memset (data, 0, size);
06421 
06422   set_command (data, SET_SCAN_FRAME);
06423   set_data_length (data, size - 4);
06424 
06425   data[4] = 0x80;
06426   if (scanner->colormode == HALFTONE)
06427     data[4] |= 0x40;
06428 
06429   dpmm = (double) scanner->device->inquiry_pixel_resolution / MM_PER_INCH;
06430 
06431   x = SANE_UNFIX (scanner->val[OPT_TL_X].w) * dpmm;
06432   set_data (data, 6, (int) x, 2);
06433   DBG (DBG_info, "TL_X: %d\n", (int) x);
06434 
06435   x = SANE_UNFIX (scanner->val[OPT_TL_Y].w) * dpmm;
06436   set_data (data, 8, (int) x, 2);
06437   DBG (DBG_info, "TL_Y: %d\n", (int) x);
06438 
06439   x = SANE_UNFIX (scanner->val[OPT_BR_X].w) * dpmm;
06440   set_data (data, 10, (int) x, 2);
06441   DBG (DBG_info, "BR_X: %d\n", (int) x);
06442 
06443   x = SANE_UNFIX (scanner->val[OPT_BR_Y].w) * dpmm;
06444   set_data (data, 12, (int) x, 2);
06445   DBG (DBG_info, "BR_Y: %d\n", (int) x);
06446 
06447   status =
06448     sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL);
06449   if (status)
06450     {
06451       DBG (DBG_error, "pie_set_window: write command returned status %s\n",
06452            sane_strstatus (status));
06453     }
06454 
06455   return status;
06456 }
06457 
06458 
06459 /*------------------------- PIE MODE SELECT -----------------------------*/
06460 
06461 static SANE_Status
06462 pie_mode_select (Pie_Scanner * scanner)
06463 {
06464 
06465   SANE_Status status;
06466   unsigned char buffer[128];
06467   size_t size;
06468   unsigned char *data;
06469   int i;
06470 
06471   DBG (DBG_proc, "pie_mode_select\n");
06472 
06473   size = 14;
06474 
06475   set_mode_length (smode.cmd, size);
06476 
06477   memcpy (buffer, smode.cmd, smode.size);
06478 
06479   data = buffer + smode.size;
06480   memset (data, 0, size);
06481 
06482   /* size of data */
06483   data[1] = size - 2;
06484 
06485   /* set resolution required */
06486   set_data (data, 2, scanner->resolution, 2);
06487 
06488   /* set color filter and color depth */
06489   switch (scanner->colormode)
06490     {
06491     case RGB:
06492       if (scanner->device->inquiry_filters & INQ_ONE_PASS_COLOR)
06493         {
06494           data[4] = INQ_ONE_PASS_COLOR;
06495           scanner->cal_filter = FILTER_RED | FILTER_GREEN | FILTER_BLUE;
06496         }
06497       else
06498         {
06499           DBG (DBG_error,
06500                "pie_mode_select: support for multipass color not yet implemented\n");
06501           return SANE_STATUS_UNSUPPORTED;
06502         }
06503       data[5] = INQ_COLOR_DEPTH_8;
06504       break;
06505 
06506     case GRAYSCALE:
06507     case LINEART:
06508     case HALFTONE:
06509       /* choose which filter to use for monochrome mode */
06510       if (scanner->device->inquiry_filters & INQ_FILTER_NEUTRAL)
06511         {
06512           data[4] = FILTER_NEUTRAL;
06513           scanner->cal_filter = FILTER_NEUTRAL;
06514         }
06515       else if (scanner->device->inquiry_filters & INQ_FILTER_GREEN)
06516         {
06517           data[4] = FILTER_GREEN;
06518           scanner->cal_filter = FILTER_GREEN;
06519         }
06520       else if (scanner->device->inquiry_filters & INQ_FILTER_RED)
06521         {
06522           data[4] = FILTER_RED;
06523           scanner->cal_filter = FILTER_RED;
06524         }
06525       else if (scanner->device->inquiry_filters & INQ_FILTER_BLUE)
06526         {
06527           data[4] = FILTER_BLUE;
06528           scanner->cal_filter = FILTER_BLUE;
06529         }
06530       else
06531         {
06532           DBG (DBG_error,
06533                "pie_mode_select: scanner doesn't appear to support monochrome\n");
06534           return SANE_STATUS_UNSUPPORTED;
06535         }
06536 
06537       if (scanner->colormode == GRAYSCALE)
06538         data[5] = INQ_COLOR_DEPTH_8;
06539       else
06540         data[5] = INQ_COLOR_DEPTH_1;
06541       break;
06542     }
06543 
06544   /* choose color packing method */
06545   if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_LINE)
06546     data[6] = INQ_COLOR_FORMAT_LINE;
06547   else if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX)
06548     data[6] = INQ_COLOR_FORMAT_INDEX;
06549   else
06550     {
06551       DBG (DBG_error,
06552            "pie_mode_select: support for pixel packing not yet implemented\n");
06553       return SANE_STATUS_UNSUPPORTED;
06554     }
06555 
06556   /* choose data format */
06557   if (scanner->device->inquiry_image_format & INQ_IMG_FMT_INTEL)
06558     data[8] = INQ_IMG_FMT_INTEL;
06559   else
06560     {
06561       DBG (DBG_error,
06562            "pie_mode_select: support for Motorola format not yet implemented\n");
06563       return SANE_STATUS_UNSUPPORTED;
06564     }
06565 
06566   /* set required speed */
06567   i = 0;
06568   while (scanner->device->speed_list[i] != NULL)
06569     {
06570       if (strcmp (scanner->device->speed_list[i], scanner->val[OPT_SPEED].s)
06571           == 0)
06572         break;
06573       i++;
06574     }
06575 
06576   if (scanner->device->speed_list[i] == NULL)
06577     data[9] = 0;
06578   else
06579     data[9] = i;
06580 
06581   scanner->cal_mode = CAL_MODE_FLATBED;
06582 
06583   /* if preview supported, ask for preview, limit resolution to max for fast preview */
06584   if (scanner->val[OPT_PREVIEW].w
06585       && (scanner->device->inquiry_scan_capability & INQ_CAP_FAST_PREVIEW))
06586     {
06587       DBG (DBG_info, "pie_mode_select: setting preview\n");
06588       scanner->cal_mode |= CAL_MODE_PREVIEW;
06589       data[9] |= INQ_CAP_FAST_PREVIEW;
06590       data[9] &= ~INQ_CAP_SPEEDS;
06591       if (scanner->resolution > scanner->device->inquiry_fast_preview_res)
06592         set_data (data, 2, scanner->device->inquiry_fast_preview_res, 2);
06593     }
06594 
06595 
06596   /* set required halftone pattern */
06597   i = 0;
06598   while (scanner->device->halftone_list[i] != NULL)
06599     {
06600       if (strcmp
06601           (scanner->device->halftone_list[i],
06602            scanner->val[OPT_HALFTONE_PATTERN].s) == 0)
06603         break;
06604       i++;
06605     }
06606 
06607   if (scanner->device->halftone_list[i] == NULL)
06608     data[12] = 0;               /* halftone pattern */
06609   else
06610     data[12] = i;
06611 
06612   data[13] = SANE_UNFIX (scanner->val[OPT_THRESHOLD].w) * 255 / 100;    /* lineart threshold */
06613 
06614   DBG (DBG_info, "pie_mode_select: speed %02x\n", data[9]);
06615   DBG (DBG_info, "pie_mode_select: halftone %d\n", data[12]);
06616   DBG (DBG_info, "pie_mode_select: threshold %02x\n", data[13]);
06617 
06618   status =
06619     sanei_scsi_cmd (scanner->sfd, buffer, smode.size + size, NULL, NULL);
06620   if (status)
06621     {
06622       DBG (DBG_error, "pie_mode_select: write command returned status %s\n",
06623            sane_strstatus (status));
06624     }
06625 
06626   return status;
06627 }
06628 
06629 
06630 /*------------------------- PIE SCAN -----------------------------*/
06631 
06632 static SANE_Status
06633 pie_scan (Pie_Scanner * scanner, int start)
06634 {
06635   SANE_Status status;
06636 
06637   DBG (DBG_proc, "pie_scan\n");
06638 
06639   /* TUR */
06640   status = pie_wait_scanner (scanner);
06641   if (status)
06642     {
06643       return status;
06644     }
06645 
06646   set_scan_cmd (scan.cmd, start);
06647 
06648   do
06649     {
06650       status = sanei_scsi_cmd (scanner->sfd, scan.cmd, scan.size, NULL, NULL);
06651       if (status)
06652         {
06653           DBG (DBG_error, "pie_scan: write command returned status %s\n",
06654                sane_strstatus (status));
06655           usleep (SCAN_WARMUP_WAIT_TIME);
06656         }
06657     }
06658   while (start && status);
06659 
06660   usleep (SCAN_WAIT_TIME);
06661 
06662   return status;
06663 }
06664 
06665 
06666 /* --------------------------------------- PIE WAIT SCANNER -------------------------- */
06667 
06668 
06669 static SANE_Status
06670 pie_wait_scanner (Pie_Scanner * scanner)
06671 {
06672   SANE_Status status;
06673   int cnt = 0;
06674 
06675   DBG (DBG_proc, "wait_scanner\n");
06676 
06677   do
06678     {
06679       if (cnt > 100)            /* maximal 100 * 0.5 sec = 50 sec */
06680         {
06681           DBG (DBG_warning, "scanner does not get ready\n");
06682           return -1;
06683         }
06684       /* test unit ready */
06685       status =
06686         sanei_scsi_cmd (scanner->sfd, test_unit_ready.cmd,
06687                         test_unit_ready.size, NULL, NULL);
06688 
06689       cnt++;
06690 
06691       if (status)
06692         {
06693           if (cnt == 1)
06694             {
06695               DBG (DBG_info2, "scanner reports %s, waiting ...\n",
06696                    sane_strstatus (status));
06697             }
06698 
06699           usleep (TUR_WAIT_TIME);
06700         }
06701     }
06702   while (status != SANE_STATUS_GOOD);
06703 
06704   DBG (DBG_info, "scanner ready\n");
06705 
06706 
06707   return status;
06708 }
06709 
06710 
06711 /* -------------------------------------- PIE GET PARAMS -------------------------- */
06712 
06713 
06714 static SANE_Status
06715 pie_get_params (Pie_Scanner * scanner)
06716 {
06717   SANE_Status status;
06718   size_t size;
06719   unsigned char buffer[128];
06720 
06721   DBG (DBG_proc, "pie_get_params\n");
06722 
06723   status = pie_wait_scanner (scanner);
06724   if (status)
06725     return status;
06726 
06727   if (scanner->device->inquiry_image_format & INQ_IMG_FMT_OKLINE)
06728     size = 16;
06729   else
06730 
06731     size = 14;
06732 
06733   set_param_length (param.cmd, size);
06734 
06735   status =
06736     sanei_scsi_cmd (scanner->sfd, param.cmd, param.size, buffer, &size);
06737 
06738   if (status)
06739     {
06740       DBG (DBG_error, "pie_get_params: command returned status %s\n",
06741            sane_strstatus (status));
06742     }
06743   else
06744     {
06745       DBG (DBG_info, "Scan Width:  %d\n", get_param_scan_width (buffer));
06746       DBG (DBG_info, "Scan Lines:  %d\n", get_param_scan_lines (buffer));
06747       DBG (DBG_info, "Scan bytes:  %d\n", get_param_scan_bytes (buffer));
06748 
06749       DBG (DBG_info, "Offset 1:    %d\n",
06750            get_param_scan_filter_offset1 (buffer));
06751       DBG (DBG_info, "Offset 2:    %d\n",
06752            get_param_scan_filter_offset2 (buffer));
06753       DBG (DBG_info, "Scan period: %d\n", get_param_scan_period (buffer));
06754       DBG (DBG_info, "Xfer rate:   %d\n", get_param_scsi_xfer_rate (buffer));
06755       if (scanner->device->inquiry_image_format & INQ_IMG_FMT_OKLINE)
06756         DBG (DBG_info, "Avail lines: %d\n",
06757              get_param_scan_available_lines (buffer));
06758 
06759       scanner->filter_offset1 = get_param_scan_filter_offset1 (buffer);
06760       scanner->filter_offset2 = get_param_scan_filter_offset2 (buffer);
06761       scanner->bytes_per_line = get_param_scan_bytes (buffer);
06762 
06763       scanner->params.pixels_per_line = get_param_scan_width (buffer);
06764       scanner->params.lines = get_param_scan_lines (buffer);
06765 
06766       switch (scanner->colormode)
06767         {
06768         case RGB:
06769           scanner->params.format = SANE_FRAME_RGB;
06770           scanner->params.depth = 8;
06771           scanner->params.bytes_per_line = 3 * get_param_scan_bytes (buffer);
06772           break;
06773 
06774         case GRAYSCALE:
06775           scanner->params.format = SANE_FRAME_GRAY;
06776           scanner->params.depth = 8;
06777           scanner->params.bytes_per_line = get_param_scan_bytes (buffer);
06778           break;
06779 
06780         case HALFTONE:
06781         case LINEART:
06782           scanner->params.format = SANE_FRAME_GRAY;
06783           scanner->params.depth = 1;
06784           scanner->params.bytes_per_line = get_param_scan_bytes (buffer);
06785           break;
06786         }
06787 
06788       scanner->params.last_frame = 0;
06789     }
06790 
06791   return status;
06792 }
06793 
06794 
06795 /* -------------------------------------- PIE GRAB SCANNER -------------------------- */
06796 
06797 
06798 static SANE_Status
06799 pie_grab_scanner (Pie_Scanner * scanner)
06800 {
06801   SANE_Status status;
06802 
06803   DBG (DBG_proc, "grab_scanner\n");
06804 
06805 
06806   status = pie_wait_scanner (scanner);
06807   if (status)
06808     return status;
06809 
06810   status =
06811     sanei_scsi_cmd (scanner->sfd, reserve_unit.cmd, reserve_unit.size, NULL,
06812                     NULL);
06813 
06814 
06815   if (status)
06816     {
06817       DBG (DBG_error, "pie_grab_scanner: command returned status %s\n",
06818            sane_strstatus (status));
06819     }
06820   else
06821     {
06822       DBG (DBG_info, "scanner reserved\n");
06823     }
06824 
06825   return status;
06826 }
06827 
06828 
06829 /* ------------------------------------ PIE GIVE SCANNER -------------------------- */
06830 
06831 
06832 static SANE_Status
06833 pie_give_scanner (Pie_Scanner * scanner)
06834 {
06835   SANE_Status status;
06836 
06837   DBG (DBG_info2, "trying to release scanner ...\n");
06838 
06839   status =
06840     sanei_scsi_cmd (scanner->sfd, release_unit.cmd, release_unit.size, NULL,
06841                     NULL);
06842   if (status)
06843     {
06844       DBG (DBG_error, "pie_give_scanner: command returned status %s\n",
06845            sane_strstatus (status));
06846     }
06847   else
06848     {
06849       DBG (DBG_info, "scanner released\n");
06850     }
06851   return status;
06852 }
06853 
06854 
06855 /* ------------------- PIE READER PROCESS INDEXED ------------------- */
06856 
06857 static int
06858 pie_reader_process_indexed (Pie_Scanner * scanner, FILE * fp)
06859 {
06860   int status;
06861   int lines;
06862   unsigned char *buffer, *reorder = NULL;
06863   unsigned char *red_buffer = NULL, *green_buffer = NULL;
06864   unsigned char *red_in = NULL, *red_out = NULL;
06865   unsigned char *green_in = NULL, *green_out = NULL;
06866   int red_size = 0, green_size = 0;
06867   int bytes_per_line;
06868   int red_count = 0, green_count = 0;
06869 
06870   size_t size;
06871 
06872   DBG (DBG_read, "reading %d lines of %d bytes/line (indexed)\n",
06873        scanner->params.lines, scanner->params.bytes_per_line);
06874 
06875   lines = scanner->params.lines;
06876   bytes_per_line = scanner->bytes_per_line;
06877 
06878   /* allocate receive buffer */
06879   buffer = malloc (bytes_per_line + 2);
06880   if (!buffer)
06881     {
06882       return SANE_STATUS_NO_MEM;
06883     }
06884 
06885   /* allocate deskew buffers for RGB mode */
06886   if (scanner->colormode == RGB)
06887     {
06888       lines *= 3;
06889 
06890       red_size = bytes_per_line * (scanner->filter_offset1 +
06891                                    scanner->filter_offset2 + 2);
06892       green_size = bytes_per_line * (scanner->filter_offset2 + 2);
06893 
06894       DBG (DBG_info2,
06895            "pie_reader_process_indexed: alloc %d lines (%d bytes) for red buffer\n",
06896            red_size / bytes_per_line, red_size);
06897       DBG (DBG_info2,
06898            "pie_reader_process_indexed: alloc %d lines (%d bytes) for green buffer\n",
06899            green_size / bytes_per_line, green_size);
06900 
06901       reorder = malloc (scanner->params.bytes_per_line);
06902       red_buffer = malloc (red_size);
06903       green_buffer = malloc (green_size);
06904 
06905       if (!reorder || !red_buffer || !green_buffer)
06906         {
06907           free (buffer);
06908           free (reorder);
06909           free (red_buffer);
06910           free (green_buffer);
06911           return SANE_STATUS_NO_MEM;
06912         }
06913 
06914       red_in = red_out = red_buffer;
06915       green_in = green_out = green_buffer;
06916     }
06917 
06918   while (lines--)
06919     {
06920       set_read_length (sread.cmd, 1);
06921       size = bytes_per_line + 2;
06922 
06923       do
06924         {
06925           status =
06926             sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer,
06927                             &size);
06928         }
06929       while (status);
06930 
06931       DBG_DUMP (DBG_dump, buffer, 64);
06932 
06933       if (scanner->colormode == RGB)
06934         {
06935           /* we're assuming that we get red before green before blue here */
06936           switch (*buffer)
06937             {
06938             case 'R':
06939               /* copy to red buffer */
06940               memcpy (red_in, buffer + 2, bytes_per_line);
06941 
06942               /* advance in pointer, and check for wrap */
06943               red_in += bytes_per_line;
06944               if (red_in >= (red_buffer + red_size))
06945                 red_in = red_buffer;
06946 
06947               /* increment red line count */
06948               red_count++;
06949               DBG (DBG_info2,
06950                    "pie_reader_process_indexed: got a red line (%d)\n",
06951                    red_count);
06952               break;
06953 
06954             case 'G':
06955               /* copy to green buffer */
06956               memcpy (green_in, buffer + 2, bytes_per_line);
06957 
06958               /* advance in pointer, and check for wrap */
06959               green_in += bytes_per_line;
06960               if (green_in >= (green_buffer + green_size))
06961                 green_in = green_buffer;
06962 
06963               /* increment green line count */
06964               green_count++;
06965               DBG (DBG_info2,
06966                    "pie_reader_process_indexed: got a green line (%d)\n",
06967                    green_count);
06968               break;
06969 
06970             case 'B':
06971               /* check we actually have red and green data available */
06972               if (!red_count || !green_count)
06973                 {
06974                   DBG (DBG_error,
06975                        "pie_reader_process_indexed: deskew buffer empty (%d %d)\n",
06976                        red_count, green_count);
06977                   return SANE_STATUS_INVAL;
06978                 }
06979               red_count--;
06980               green_count--;
06981 
06982               DBG (DBG_info2,
06983                    "pie_reader_process_indexed: got a blue line\n");
06984 
06985               {
06986                 int i;
06987                 unsigned char *red, *green, *blue, *dest;
06988 
06989                 /* now pack the pixels lines into RGB format */
06990                 dest = reorder;
06991                 red = red_out;
06992                 green = green_out;
06993                 blue = buffer + 2;
06994 
06995                 for (i = bytes_per_line; i > 0; i--)
06996                   {
06997                     *dest++ = *red++;
06998                     *dest++ = *green++;
06999                     *dest++ = *blue++;
07000                   }
07001                 fwrite (reorder, 1, scanner->params.bytes_per_line, fp);
07002 
07003                 /* advance out pointers, and check for wrap */
07004                 red_out += bytes_per_line;
07005                 if (red_out >= (red_buffer + red_size))
07006                   red_out = red_buffer;
07007                 green_out += bytes_per_line;
07008                 if (green_out >= (green_buffer + green_size))
07009                   green_out = green_buffer;
07010               }
07011               break;
07012 
07013             default:
07014               DBG (DBG_error,
07015                    "pie_reader_process_indexed: bad filter index\n");
07016             }
07017         }
07018       else
07019         {
07020           DBG (DBG_info2,
07021                "pie_reader_process_indexed: got a line (%lu bytes)\n",
07022                (u_long) size);
07023 
07024           /* just send the data on, assume filter bytes not present as per calibration case */
07025           fwrite (buffer, 1, scanner->params.bytes_per_line, fp);
07026         }
07027     }
07028 
07029   free (buffer);
07030   free (reorder);
07031   free (red_buffer);
07032   free (green_buffer);
07033   return 0;
07034 }
07035 
07036 /* ----------------------------- PIE_READER_PROCESS_FMTLINE -------------------- */
07037 
07038 static int
07039 pie_reader_process_fmtline (Pie_Scanner * scanner, FILE * fp)
07040 {
07041   int status;
07042   int lines;
07043   unsigned char *buffer, *reorder;
07044   size_t size;
07045 
07046   DBG (DBG_read, "reading %d lines of %d bytes/line\n", scanner->params.lines,
07047        scanner->params.bytes_per_line);
07048 
07049   buffer = malloc (scanner->params.bytes_per_line);
07050   reorder = malloc (scanner->params.bytes_per_line);
07051   if (!buffer || !reorder)
07052     {
07053       free (buffer);
07054       free (reorder);
07055       return SANE_STATUS_NO_MEM;
07056     }
07057 
07058   lines = scanner->params.lines;
07059 
07060   while (lines--)
07061     {
07062       set_read_length (sread.cmd, 1);
07063       size = scanner->params.bytes_per_line;
07064 
07065       do
07066         {
07067           status =
07068             sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer,
07069                             &size);
07070         }
07071       while (status);
07072 
07073       DBG_DUMP (DBG_dump, buffer, 64);
07074 
07075       if (scanner->colormode == RGB)
07076         {
07077           int i;
07078           unsigned char *src, *dest;
07079           int offset;
07080 
07081           dest = reorder;
07082           src = buffer;
07083           offset = scanner->params.pixels_per_line;
07084 
07085           for (i = scanner->params.pixels_per_line; i > 0; i--)
07086             {
07087               *dest++ = *src;
07088               *dest++ = *(src + offset);
07089               *dest++ = *(src + 2 * offset);
07090               src++;
07091             }
07092           fwrite (reorder, 1, scanner->params.bytes_per_line, fp);
07093         }
07094       else
07095         {
07096           fwrite (buffer, 1, scanner->params.bytes_per_line, fp);
07097         }
07098 
07099       fflush (fp);
07100     }
07101 
07102   free (buffer);
07103   free (reorder);
07104 
07105   return 0;
07106 }
07107 
07108 
07109 
07110 /* ------------------------------- PIE_READER_PROCESS_SIGTERM_HANDLER  ---------- */
07111 
07112 
07113 static RETSIGTYPE
07114 pie_reader_process_sigterm_handler (int signal)
07115 {
07116   DBG (DBG_sane_info, "pie_reader_process: terminated by signal %d\n", signal);
07117 
07118 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
07119   sanei_scsi_req_flush_all ();  /* flush SCSI queue */
07120 #else
07121   sanei_scsi_req_flush_all ();  /* flush SCSI queue */
07122 #endif
07123 
07124   _exit (SANE_STATUS_GOOD);
07125 }
07126 
07127 
07128 
07129 /* ---------------------------- PIE_READER_PROCESS --------------------------- */
07130 
07131 
07132 static int
07133 pie_reader_process (void *data) /* executed as a child process */
07134 {
07135   int status;
07136   FILE *fp;
07137   Pie_Scanner *scanner;
07138   sigset_t ignore_set;
07139   struct SIGACTION act;
07140 
07141   scanner = (Pie_Scanner *) data;
07142   
07143   if (sanei_thread_is_forked ())
07144     {
07145 
07146       close (scanner->pipe);
07147 
07148       sigfillset (&ignore_set);
07149       sigdelset (&ignore_set, SIGTERM);
07150 #if defined (__APPLE__) && defined (__MACH__)
07151       sigdelset (&ignore_set, SIGUSR2);
07152 #endif
07153       sigprocmask (SIG_SETMASK, &ignore_set, 0);
07154 
07155       memset (&act, 0, sizeof (act));
07156       sigaction (SIGTERM, &act, 0);
07157   }
07158   
07159   DBG (DBG_sane_proc, "pie_reader_process started\n");
07160 
07161   memset (&act, 0, sizeof (act));       /* define SIGTERM-handler */
07162   act.sa_handler = pie_reader_process_sigterm_handler;
07163   sigaction (SIGTERM, &act, 0);
07164 
07165   fp = fdopen (scanner->reader_fds, "w");
07166   if (!fp)
07167     {
07168       return SANE_STATUS_IO_ERROR;
07169     }
07170 
07171   DBG (DBG_sane_info, "pie_reader_process: starting to READ data\n");
07172 
07173   if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_LINE)
07174     status = pie_reader_process_fmtline (scanner, fp);
07175   else if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX)
07176     status = pie_reader_process_indexed (scanner, fp);
07177   else
07178     status = SANE_STATUS_UNSUPPORTED;
07179 
07180   fclose (fp);
07181 
07182   DBG (DBG_sane_info, "pie_reader_process: finished reading data\n");
07183 
07184   return status;
07185 }
07186 
07187 
07188 /* ------------------------------ PIE_ATTACH_ONE -------------------------------- */
07189 
07190 /* callback function for sanei_usb_attach_matching_devices */
07191 static SANE_Status
07192 pie_attach_one (const char *name)
07193 {
07194   pie_attach_scanner (name, 0);
07195   return SANE_STATUS_GOOD;
07196 }
07197 
07198 
07199 /* --------------------------- PIE_CLOSE_PIPE -------------------------------- */
07200 
07201 static SANE_Status
07202 pie_close_pipe (Pie_Scanner * scanner)
07203 {
07204   DBG (DBG_sane_proc, "pie_close_pipe\n");
07205 
07206   if (scanner->pipe >= 0)
07207     {
07208       close (scanner->pipe);
07209       scanner->pipe = -1;
07210     }
07211 
07212   return SANE_STATUS_EOF;
07213 }
07214 
07215 
07216 
07217 /* -------------------------- PIE_DO_CANCEL -------------------------------- */
07218 
07219 
07220 static SANE_Status
07221 pie_do_cancel (Pie_Scanner * scanner)
07222 {
07223   DBG (DBG_sane_proc, "pie_do_cancel\n");
07224 
07225   scanner->scanning = SANE_FALSE;
07226 
07227   if (scanner->reader_pid != NO_PID)
07228     {
07229       DBG (DBG_sane_info, "killing pie_reader_process\n");
07230       sanei_thread_kill (scanner->reader_pid);
07231       sanei_thread_waitpid (scanner->reader_pid, 0);
07232       scanner->reader_pid = NO_PID;
07233       DBG (DBG_sane_info, "pie_reader_process killed\n");
07234     }
07235 
07236   if (scanner->sfd >= 0)
07237     {
07238       pie_scan (scanner, 0);
07239 
07240       pie_power_save (scanner, 15);
07241 
07242       pie_give_scanner (scanner);       /* reposition and release scanner */
07243 
07244       DBG (DBG_sane_info, "closing scannerdevice filedescriptor\n");
07245       sanei_scsi_close (scanner->sfd);
07246       scanner->sfd = -1;
07247     }
07248 
07249   return SANE_STATUS_CANCELLED;
07250 }
07251 
07252 
07253 /*
07254  * @@ sane_xy functions: Most of them call their pie_usb counterparts for USB scanners
07255  */
07256 
07257 /* --------------------------------------- SANE INIT ---------------------------------- */
07258 
07259 SANE_Status
07260 sane_init (SANE_Int * version_code,
07261            SANE_Auth_Callback __sane_unused__ authorize)
07262 {
07263   char dev_name[PATH_MAX];
07264   size_t len;
07265   FILE *fp;
07266 
07267   DBG_INIT ();
07268 
07269   DBG (DBG_sane_init, "sane_init() build %d\n", BUILD);
07270 
07271   if (version_code)
07272     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
07273 
07274   /* initialize usb use */
07275   sanei_usb_init ();
07276   /* initialize infrared handling */
07277   sanei_ir_init ();
07278   /* initialize magic handling */
07279   sanei_magic_init ();
07280 
07281   fp = sanei_config_open (PIE_CONFIG_FILE);
07282   if (!fp)
07283     {
07284       pie_attach_scanner ("/dev/scanner", 0);   /* no config-file: /dev/scanner */
07285       return SANE_STATUS_GOOD;
07286     }
07287 
07288   while (sanei_config_read (dev_name, sizeof (dev_name), fp))
07289     {
07290       if (dev_name[0] == '#')
07291         {
07292           continue;
07293         }                       /* ignore line comments */
07294 
07295       len = strlen (dev_name);
07296 
07297       if (!len)                 /* ignore empty lines */
07298         {
07299           continue;
07300         }
07301 
07302       DBG (DBG_sane_proc, "sane_init() trying %s\n", dev_name);
07303       sanei_config_attach_matching_devices (dev_name, pie_usb_try_attach);
07304     }
07305 
07306   fclose (fp);
07307 
07308   return SANE_STATUS_GOOD;
07309 }
07310 
07311 
07312 /* ----------------------------------------- SANE EXIT ---------------------------------- */
07313 
07314 
07315 void
07316 sane_exit (void)
07317 {
07318   Pie_Device *dev, *next;
07319   int i;
07320 
07321   DBG (DBG_sane_init, "sane_exit()\n");
07322 
07323   for (dev = first_dev; dev; dev = next)
07324     {
07325       next = dev->next;
07326       free (dev->devicename);
07327       if (dev->model == NULL)
07328         {
07329           free (dev->vendor);
07330           free (dev->product);
07331         }
07332       free (dev->version);
07333       if (dev->cal_info)
07334       free (dev->cal_info);
07335       i = 0;
07336       while (dev->halftone_list[i] != NULL)
07337         free (dev->halftone_list[i++]);
07338       i = 0;
07339       while (dev->speed_list[i] != NULL)
07340         free (dev->speed_list[i++]);
07341 
07342       free (dev);
07343     }
07344 
07345   first_dev = NULL;
07346 
07347   if (devlist)
07348     {
07349       free (devlist);
07350       devlist = NULL;
07351     }
07352 }
07353 
07354 
07355 /* ------------------------------------------ SANE GET DEVICES --------------------------- */
07356 
07357 
07358 SANE_Status
07359 sane_get_devices (const SANE_Device *** device_list,
07360                   SANE_Bool __sane_unused__ local_only)
07361 {
07362   Pie_Device *dev;
07363   int i;
07364 
07365   DBG (DBG_sane_init, "sane_get_devices\n");
07366 
07367   i = 0;
07368   for (dev = first_dev; dev; dev = dev->next)
07369     i++;
07370 
07371   if (devlist)
07372     {
07373       free (devlist);
07374     }
07375 
07376   devlist = malloc ((i + 1) * sizeof (devlist[0]));
07377   if (!devlist)
07378     {
07379       return SANE_STATUS_NO_MEM;
07380     }
07381 
07382   i = 0;
07383 
07384   for (dev = first_dev; dev; dev = dev->next)
07385     {
07386       devlist[i++] = &dev->sane;
07387     }
07388 
07389   devlist[i] = NULL;
07390 
07391   *device_list = devlist;
07392 
07393   return SANE_STATUS_GOOD;
07394 }
07395 
07396 
07397 /* --------------------------------------- SANE OPEN ---------------------------------- */
07398 
07399 SANE_Status
07400 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
07401 {
07402   Pie_Device *dev;
07403   SANE_Status status;
07404   Pie_Scanner *scanner;
07405   int i, j;
07406 
07407   DBG (DBG_sane_init, "sane_open(%s)\n", devicename);
07408 
07409   if (devicename[0])            /* search for devicename */
07410     {
07411       for (dev = first_dev; dev; dev = dev->next)
07412         {
07413           if (strcmp (dev->sane.name, devicename) == 0)
07414             {
07415               break;
07416             }
07417         }
07418 
07419       if (!dev)
07420         {
07421           status = pie_attach_scanner (devicename, &dev);
07422           if (status != SANE_STATUS_GOOD)
07423             {
07424               return status;
07425             }
07426         }
07427     }
07428   else
07429     {
07430       dev = first_dev;          /* empty devicename -> use first device */
07431     }
07432 
07433 
07434   if (!dev)
07435     {
07436       return SANE_STATUS_INVAL;
07437     }
07438 
07439   scanner = malloc (sizeof (*scanner));
07440   if (!scanner)
07441 
07442     {
07443       return SANE_STATUS_NO_MEM;
07444     }
07445 
07446   memset (scanner, 0, sizeof (*scanner));
07447 
07448   scanner->device = dev;
07449   scanner->sfd = -1;
07450   scanner->pipe = -1;
07451 
07452   if (scanner->device->model != NULL)   /* USB film scanners */
07453     return pie_usb_sane_open (scanner, handle);
07454 
07455   scanner->gamma_length = 1 << (scanner->device->inquiry_gamma_bits);
07456 
07457   DBG (DBG_sane_info, "Using %d bits for gamma input\n",
07458        scanner->device->inquiry_gamma_bits);
07459 
07460   scanner->gamma_range.min = 0;
07461   scanner->gamma_range.max = scanner->gamma_length - 1;
07462   scanner->gamma_range.quant = 0;
07463 
07464   scanner->gamma_table[0] =
07465     (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int));
07466   scanner->gamma_table[1] =
07467     (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int));
07468   scanner->gamma_table[2] =
07469     (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int));
07470   scanner->gamma_table[3] =
07471     (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int));
07472 
07473   for (i = 0; i < 4; ++i)       /* gamma_table[0,1,2,3] */
07474     {
07475       for (j = 0; j < scanner->gamma_length; ++j)
07476         {
07477           scanner->gamma_table[i][j] = j;
07478         }
07479     }
07480 
07481   pie_init_options (scanner);
07482 
07483   scanner->next = first_handle; /* insert newly opened handle into list of open handles: */
07484   first_handle = scanner;
07485 
07486   *handle = scanner;
07487 
07488   return SANE_STATUS_GOOD;
07489 }
07490 
07491 
07492 /* ------------------------------------ SANE CLOSE --------------------------------- */
07493 
07494 
07495 void
07496 sane_close (SANE_Handle handle)
07497 {
07498   Pie_Scanner *prev, *scanner;
07499 
07500   DBG (DBG_sane_init, "sane_close\n");
07501 
07502   /* remove handle from list of open handles: */
07503   prev = 0;
07504 
07505   for (scanner = first_handle; scanner; scanner = scanner->next)
07506     {
07507       if (scanner == handle)
07508         {
07509           break;
07510         }
07511 
07512       prev = scanner;
07513     }
07514 
07515   if (!scanner)
07516     {
07517       DBG (DBG_error, "close: invalid handle %p\n", handle);
07518       return;                   /* oops, not a handle we know about */
07519     }
07520 
07521   if (prev)
07522     {
07523       prev->next = scanner->next;
07524     }
07525   else
07526     {
07527       first_handle = scanner->next;
07528     }
07529 
07530   if (scanner->device->model != NULL)   /* USB film scanners */
07531     {
07532       pie_usb_sane_close (scanner);
07533     }
07534   else
07535     {
07536       if (scanner->scanning)    /* stop scan if still scanning */
07537         {
07538           pie_do_cancel (handle);
07539         }
07540 
07541       free (scanner->gamma_table[0]);   /* free custom gamma tables */
07542       free (scanner->gamma_table[1]);
07543       free (scanner->gamma_table[2]);
07544       free (scanner->gamma_table[3]);
07545     }
07546   free (scanner->val[OPT_MODE].s);
07547   free (scanner->val[OPT_SPEED].s);
07548   free (scanner->val[OPT_HALFTONE_PATTERN].s);
07549   free (scanner->val[OPT_SW_IRED].s);
07550   free (scanner->val[OPT_SW_CROP].s);
07551 
07552   scanner->bufsize = 0;
07553 
07554   free (scanner);               /* free scanner */
07555 }
07556 
07557 
07558 /* ---------------------------------- SANE GET OPTION DESCRIPTOR ----------------- */
07559 
07560 const SANE_Option_Descriptor *
07561 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
07562 {
07563   Pie_Scanner *scanner = handle;
07564 
07565   DBG (DBG_sane_option, "sane_get_option_descriptor %d\n", option);
07566 
07567   if ((unsigned) option >= NUM_OPTIONS)
07568     {
07569       return 0;
07570     }
07571 
07572   return scanner->opt + option;
07573 }
07574 
07575 
07576 /* ---------------------------------- SANE CONTROL OPTION ------------------------ */
07577 
07578 SANE_Status
07579 sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
07580                      void *val, SANE_Int * info)
07581 {
07582   Pie_Scanner *scanner = handle;
07583   SANE_Status status;
07584   SANE_Word cap;
07585   SANE_String_Const name;
07586 
07587   if (scanner->device->model != NULL)
07588     return pie_usb_sane_control_option (handle, option, action, val, info);
07589 
07590   if (info)
07591     {
07592       *info = 0;
07593     }
07594 
07595   if (scanner->scanning)
07596     {
07597       return SANE_STATUS_DEVICE_BUSY;
07598     }
07599 
07600   if ((unsigned) option >= NUM_OPTIONS)
07601     {
07602       return SANE_STATUS_INVAL;
07603     }
07604 
07605   cap = scanner->opt[option].cap;
07606   if (!SANE_OPTION_IS_ACTIVE (cap))
07607     {
07608       return SANE_STATUS_INVAL;
07609     }
07610 
07611   name = scanner->opt[option].name;
07612   if (!name)
07613     {
07614       name = "(no name)";
07615     }
07616 
07617   if (action == SANE_ACTION_GET_VALUE)
07618     {
07619 
07620       DBG (DBG_sane_option, "get %s [#%d]\n", name, option);
07621 
07622       switch (option)
07623         {
07624           /* word options: */
07625         case OPT_NUM_OPTS:
07626         case OPT_RESOLUTION:
07627         case OPT_TL_X:
07628         case OPT_TL_Y:
07629         case OPT_BR_X:
07630         case OPT_BR_Y:
07631         case OPT_PREVIEW:
07632         case OPT_THRESHOLD:
07633           *(SANE_Word *) val = scanner->val[option].w;
07634           return SANE_STATUS_GOOD;
07635 
07636           /* word-array options: */
07637         case OPT_GAMMA_VECTOR:
07638         case OPT_GAMMA_VECTOR_R:
07639         case OPT_GAMMA_VECTOR_G:
07640         case OPT_GAMMA_VECTOR_B:
07641           memcpy (val, scanner->val[option].wa, scanner->opt[option].size);
07642           return SANE_STATUS_GOOD;
07643 
07644 #if 0
07645           /* string options: */
07646         case OPT_SOURCE:
07647 #endif
07648         case OPT_MODE:
07649         case OPT_HALFTONE_PATTERN:
07650         case OPT_SPEED:
07651           strcpy (val, scanner->val[option].s);
07652           return SANE_STATUS_GOOD;
07653         }
07654     }
07655   else if (action == SANE_ACTION_SET_VALUE)
07656     {
07657       switch (scanner->opt[option].type)
07658         {
07659         case SANE_TYPE_INT:
07660           DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option,
07661                *(SANE_Word *) val);
07662           break;
07663 
07664         case SANE_TYPE_FIXED:
07665           DBG (DBG_sane_option, "set %s [#%d] to %f\n", name, option,
07666                SANE_UNFIX (*(SANE_Word *) val));
07667           break;
07668 
07669         case SANE_TYPE_STRING:
07670           DBG (DBG_sane_option, "set %s [#%d] to %s\n", name, option,
07671                (char *) val);
07672           break;
07673 
07674         case SANE_TYPE_BOOL:
07675           DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option,
07676                *(SANE_Word *) val);
07677           break;
07678 
07679         default:
07680           DBG (DBG_sane_option, "set %s [#%d]\n", name, option);
07681         }
07682 
07683       if (!SANE_OPTION_IS_SETTABLE (cap))
07684         {
07685           return SANE_STATUS_INVAL;
07686         }
07687 
07688       status = sanei_constrain_value (scanner->opt + option, val, info);
07689       if (status != SANE_STATUS_GOOD)
07690         {
07691           return status;
07692         }
07693 
07694       switch (option)
07695         {
07696           /* (mostly) side-effect-free word options: */
07697         case OPT_RESOLUTION:
07698         case OPT_TL_X:
07699         case OPT_TL_Y:
07700         case OPT_BR_X:
07701         case OPT_BR_Y:
07702           if (info)
07703             {
07704               *info |= SANE_INFO_RELOAD_PARAMS;
07705             }
07706           /* fall through */
07707         case OPT_NUM_OPTS:
07708         case OPT_PREVIEW:
07709         case OPT_THRESHOLD:
07710           scanner->val[option].w = *(SANE_Word *) val;
07711           return SANE_STATUS_GOOD;
07712 
07713           /* side-effect-free word-array options: */
07714         case OPT_GAMMA_VECTOR:
07715         case OPT_GAMMA_VECTOR_R:
07716         case OPT_GAMMA_VECTOR_G:
07717         case OPT_GAMMA_VECTOR_B:
07718           memcpy (scanner->val[option].wa, val, scanner->opt[option].size);
07719           return SANE_STATUS_GOOD;
07720 
07721           /* options with side-effects: */
07722 
07723         case OPT_MODE:
07724           {
07725             int halftoning;
07726 
07727             if (scanner->val[option].s)
07728               {
07729                 free (scanner->val[option].s);
07730               }
07731 
07732             scanner->val[option].s = (SANE_Char *) strdup (val);
07733 
07734             if (info)
07735               {
07736                 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
07737               }
07738 
07739             scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
07740 
07741 
07742             scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
07743             scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
07744             scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
07745             scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
07746             scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
07747 
07748             halftoning = (strcmp (val, HALFTONE_STR) == 0);
07749 
07750             if (halftoning || strcmp (val, LINEART_STR) == 0)
07751               {                 /* one bit modes */
07752                 if (halftoning)
07753                   {             /* halftoning modes */
07754                     scanner->opt[OPT_HALFTONE_PATTERN].cap &=
07755                       ~SANE_CAP_INACTIVE;
07756                   }
07757                 else
07758                   {             /* lineart modes */
07759                   }
07760                 scanner->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
07761               }
07762             else
07763               {                 /* multi-bit modes(gray or color) */
07764               }
07765 
07766             if ((strcmp (val, LINEART_STR) == 0)
07767                 || (strcmp (val, HALFTONE_STR) == 0)
07768                 || (strcmp (val, GRAY_STR) == 0))
07769               {
07770                 scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
07771               }
07772             else if (strcmp (val, COLOR_STR) == 0)
07773               {
07774                 /* scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; */
07775                 scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
07776                 scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
07777                 scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
07778               }
07779             return SANE_STATUS_GOOD;
07780           }
07781 
07782         case OPT_SPEED:
07783         case OPT_HALFTONE_PATTERN:
07784           {
07785             if (scanner->val[option].s)
07786               {
07787                 free (scanner->val[option].s);
07788               }
07789 
07790             scanner->val[option].s = (SANE_Char *) strdup (val);
07791 
07792             return SANE_STATUS_GOOD;
07793           }
07794         }
07795     }                           /* else */
07796   return SANE_STATUS_INVAL;
07797 }
07798 
07799 
07800 /* ------------------------------------ SANE GET PARAMETERS ------------------------ */
07801 
07802 
07803 SANE_Status
07804 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
07805 {
07806   Pie_Scanner *scanner = handle;
07807   const char *mode;
07808 
07809   DBG (DBG_sane_info, "sane_get_parameters\n");
07810 
07811   if (!scanner->scanning)
07812     {                           /* not scanning, so lets use recent values */
07813       double width, length, x_dpi, y_dpi;
07814 
07815       memset (&scanner->params, 0, sizeof (scanner->params));
07816 
07817       width =
07818         SANE_UNFIX (scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w);
07819       length =
07820         SANE_UNFIX (scanner->val[OPT_BR_Y].w - scanner->val[OPT_TL_Y].w);
07821       x_dpi = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w);
07822       y_dpi = x_dpi;
07823 
07824 #if 0
07825       if ((scanner->val[OPT_RESOLUTION_BIND].w == SANE_TRUE)
07826           || (scanner->val[OPT_PREVIEW].w == SANE_TRUE))
07827         {
07828           y_dpi = x_dpi;
07829         }
07830 #endif
07831       if (x_dpi > 0.0 && y_dpi > 0.0 && width > 0.0 && length > 0.0)
07832         {
07833           double x_dots_per_mm = x_dpi / MM_PER_INCH;
07834           double y_dots_per_mm = y_dpi / MM_PER_INCH;
07835 
07836           scanner->params.pixels_per_line = width * x_dots_per_mm;
07837           scanner->params.lines = length * y_dots_per_mm;
07838         }
07839     }
07840 
07841   mode = scanner->val[OPT_MODE].s;
07842 
07843   if (strcmp (mode, LINEART_STR) == 0 || strcmp (mode, HALFTONE_STR) == 0)
07844     {
07845       scanner->params.format = SANE_FRAME_GRAY;
07846       scanner->params.bytes_per_line =
07847         (scanner->params.pixels_per_line + 7) / 8;
07848       scanner->params.depth = 1;
07849     }
07850   else if (strcmp (mode, GRAY_STR) == 0)
07851     {
07852       scanner->params.format = SANE_FRAME_GRAY;
07853       scanner->params.bytes_per_line = scanner->params.pixels_per_line;
07854       scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w;
07855     }
07856   else if ((strcmp (mode, COLOR_STR) == 0) ||           /* RGB */
07857           ((strcmp (mode, COLOR_IR_STR) == 0) &&        /* RGB with infrared processing */
07858            (strcmp (scanner->val[OPT_SW_IRED].s, IR_CLEAN_STR) == 0)))
07859     {
07860       scanner->params.format = SANE_FRAME_RGB;
07861       scanner->params.bytes_per_line = 3 * scanner->params.pixels_per_line;
07862       scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w;
07863     }
07864   else                          /* pure RGBI */
07865     {
07866 #ifdef SANE_FRAME_RGBI
07867       scanner->params.format = SANE_FRAME_RGBI;
07868       scanner->params.bytes_per_line = 4 * scanner->params.pixels_per_line;
07869 #else
07870       scanner->params.format = SANE_FRAME_RGB;
07871       scanner->params.bytes_per_line = 3 * scanner->params.pixels_per_line;
07872 #endif
07873       scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w;
07874     }
07875   if (scanner->params.depth > 8)
07876     scanner->params.bytes_per_line *= 2;
07877 
07878   scanner->params.last_frame = (scanner->params.format != SANE_FRAME_RED
07879                                 && scanner->params.format !=
07880                                 SANE_FRAME_GREEN);
07881 
07882   if (params)
07883     {
07884       *params = scanner->params;
07885     }
07886 
07887   return SANE_STATUS_GOOD;
07888 }
07889 
07890 
07891 /* ----------------------------------------- SANE START --------------------------------- */
07892 
07893 
07894 SANE_Status
07895 sane_start (SANE_Handle handle)
07896 {
07897   Pie_Scanner *scanner = handle;
07898   int fds[2];
07899   const char *mode;
07900   int status;
07901 
07902   DBG (DBG_sane_init, "sane_start\n");
07903 
07904   /* Check for inconsistencies */
07905 
07906   if (scanner->val[OPT_TL_X].w > scanner->val[OPT_BR_X].w)
07907     {
07908       DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) "
07909               "-- aborting\n",
07910            scanner->opt[OPT_TL_X].title,
07911            SANE_UNFIX (scanner->val[OPT_TL_X].w),
07912            scanner->opt[OPT_BR_X].title,
07913            SANE_UNFIX (scanner->val[OPT_BR_X].w));
07914       return SANE_STATUS_INVAL;
07915     }
07916   if (scanner->val[OPT_TL_Y].w > scanner->val[OPT_BR_Y].w)
07917     {
07918       DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) "
07919               "-- aborting\n",
07920            scanner->opt[OPT_TL_Y].title,
07921            SANE_UNFIX (scanner->val[OPT_TL_Y].w),
07922            scanner->opt[OPT_BR_Y].title,
07923            SANE_UNFIX (scanner->val[OPT_BR_Y].w));
07924       return SANE_STATUS_INVAL;
07925     }
07926 
07927   if (scanner->device->model != NULL)   /* USB film scanners */
07928     return pie_usb_sane_start (scanner);
07929 
07930   mode = scanner->val[OPT_MODE].s;
07931 
07932   if (scanner->sfd < 0)         /* first call, don`t run this routine again on multi frame or multi image scan */
07933     {
07934 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
07935       int scsi_bufsize = 131072;        /* 128KB */
07936 
07937       if (sanei_scsi_open_extended
07938           (scanner->device->sane.name, &(scanner->sfd), pie_sense_handler,
07939            scanner->device, &scsi_bufsize) != 0)
07940 
07941         {
07942           DBG (DBG_error, "sane_start: open failed\n");
07943           return SANE_STATUS_INVAL;
07944         }
07945 
07946       if (scsi_bufsize < 32768) /* < 32KB */
07947         {
07948           DBG (DBG_error,
07949                "sane_start: sanei_scsi_open_extended returned too small scsi buffer (%d)\n",
07950                scsi_bufsize);
07951           sanei_scsi_close ((scanner->sfd));
07952           return SANE_STATUS_NO_MEM;
07953         }
07954       DBG (DBG_info,
07955            "sane_start: sanei_scsi_open_extended returned scsi buffer size = %d\n",
07956            scsi_bufsize);
07957 
07958 
07959       scanner->bufsize = scsi_bufsize;
07960 #else
07961       if (sanei_scsi_open
07962           (scanner->device->sane.name, &(scanner->sfd), pie_sense_handler,
07963            scanner->device) != SANE_STATUS_GOOD)
07964         {
07965           DBG (DBG_error, "sane_start: open of %s failed:\n",
07966                scanner->device->sane.name);
07967           return SANE_STATUS_INVAL;
07968         }
07969 
07970       /* there is no need to reallocate the buffer because the size is fixed */
07971 #endif
07972 
07973 #if 0
07974       if (pie_check_values (scanner->device) != 0)
07975         {
07976           DBG (DBG_error, "ERROR: invalid scan-values\n");
07977           scanner->scanning = SANE_FALSE;
07978           pie_give_scanner (scanner);   /* reposition and release scanner */
07979           sanei_scsi_close (scanner->sfd);
07980           scanner->sfd = -1;
07981           return SANE_STATUS_INVAL;
07982         }
07983 #endif
07984 #if 0
07985       scanner->params.bytes_per_line = scanner->device->row_len;
07986       scanner->params.pixels_per_line = scanner->device->width_in_pixels;
07987       scanner->params.lines = scanner->device->length_in_pixels;
07988 
07989       sane_get_parameters (scanner, 0);
07990 
07991       DBG (DBG_sane_info, "x_resolution (dpi)      = %u\n",
07992            scanner->device->x_resolution);
07993       DBG (DBG_sane_info, "y_resolution (dpi)      = %u\n",
07994            scanner->device->y_resolution);
07995       DBG (DBG_sane_info, "x_coordinate_base (dpi) = %u\n",
07996            scanner->device->x_coordinate_base);
07997       DBG (DBG_sane_info, "y_coordinate_base (dpi) = %u\n",
07998            scanner->device->y_coordinate_base);
07999       DBG (DBG_sane_info, "upper_left_x (xbase)    = %d\n",
08000            scanner->device->upper_left_x);
08001       DBG (DBG_sane_info, "upper_left_y (ybase)    = %d\n",
08002            scanner->device->upper_left_y);
08003       DBG (DBG_sane_info, "scanwidth    (xbase)    = %u\n",
08004            scanner->device->scanwidth);
08005       DBG (DBG_sane_info, "scanlength   (ybase)    = %u\n",
08006            scanner->device->scanlength);
08007       DBG (DBG_sane_info, "width in pixels         = %u\n",
08008            scanner->device->width_in_pixels);
08009       DBG (DBG_sane_info, "length in pixels        = %u\n",
08010            scanner->device->length_in_pixels);
08011       DBG (DBG_sane_info, "bits per pixel/color    = %u\n",
08012            scanner->device->bits_per_pixel);
08013       DBG (DBG_sane_info, "bytes per line          = %d\n",
08014            scanner->params.bytes_per_line);
08015       DBG (DBG_sane_info, "pixels_per_line         = %d\n",
08016            scanner->params.pixels_per_line);
08017       DBG (DBG_sane_info, "lines                   = %d\n",
08018            scanner->params.lines);
08019 #endif
08020 
08021       /* grab scanner */
08022       if (pie_grab_scanner (scanner))
08023         {
08024           sanei_scsi_close (scanner->sfd);
08025           scanner->sfd = -1;
08026           DBG (DBG_warning,
08027                "WARNING: unable to reserve scanner: device busy\n");
08028           return SANE_STATUS_DEVICE_BUSY;
08029         }
08030 
08031       scanner->scanning = SANE_TRUE;
08032 
08033       pie_power_save (scanner, 0);
08034     }                           /* ------------ end of first call -------------- */
08035 
08036 
08037   if (strcmp (mode, LINEART_STR) == 0)
08038     {
08039       scanner->colormode = LINEART;
08040     }
08041   else if (strcmp (mode, HALFTONE_STR) == 0)
08042     {
08043       scanner->colormode = HALFTONE;
08044     }
08045   else if (strcmp (mode, GRAY_STR) == 0)
08046     {
08047       scanner->colormode = GRAYSCALE;
08048     }
08049   else if (strcmp (mode, COLOR_STR) == 0)
08050     {
08051       scanner->colormode = RGB;
08052     }
08053 
08054   /* get and set geometric values for scanning */
08055   scanner->resolution = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w);
08056 
08057   pie_set_window (scanner);
08058   pie_send_exposure (scanner);
08059   pie_mode_select (scanner);
08060   pie_send_highlight_shadow (scanner);
08061 
08062   pie_scan (scanner, 1);
08063 
08064   status = pie_do_cal (scanner);
08065   if (status)
08066     return status;
08067 
08068   /* send gammacurves */
08069 
08070   pie_dwnld_gamma (scanner);
08071 
08072   pie_get_params (scanner);
08073 
08074   if (pipe (fds) < 0)           /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */
08075     {
08076       DBG (DBG_error, "ERROR: could not create pipe\n");
08077       scanner->scanning = SANE_FALSE;
08078       pie_scan (scanner, 0);
08079       pie_give_scanner (scanner);       /* reposition and release scanner */
08080       sanei_scsi_close (scanner->sfd);
08081       scanner->sfd = -1;
08082       return SANE_STATUS_IO_ERROR;
08083     }
08084 
08085   scanner->pipe       = fds[0];
08086   scanner->reader_fds = fds[1];
08087   scanner->reader_pid = sanei_thread_begin (pie_reader_process, (void *) scanner);
08088 
08089   if (scanner->reader_pid == NO_PID)
08090     {
08091       DBG (1, "sane_start: sanei_thread_begin failed (%s)\n",
08092              strerror (errno));
08093       return SANE_STATUS_NO_MEM;
08094     }
08095 
08096   if (sanei_thread_is_forked ())
08097     {
08098       close (scanner->reader_fds);
08099       scanner->reader_fds = -1;
08100     }
08101 
08102   return SANE_STATUS_GOOD;
08103 }
08104 
08105 
08106 /* -------------------------------------- SANE READ ---------------------------------- */
08107 
08108 
08109 SANE_Status
08110 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
08111            SANE_Int * len)
08112 {
08113   Pie_Scanner *scanner = handle;
08114   ssize_t nread;
08115 
08116   *len = 0;
08117 
08118   if (scanner->device->model != NULL)   /* USB film scanners */
08119     return pie_usb_sane_read (scanner, buf, max_len, len);
08120 
08121   nread = read (scanner->pipe, buf, max_len);
08122   DBG (DBG_sane_info, "sane_read: read %ld bytes\n", (long) nread);
08123 
08124   if (!(scanner->scanning))     /* OOPS, not scanning */
08125     {
08126       return pie_do_cancel (scanner);
08127     }
08128 
08129   if (nread < 0)
08130     {
08131       if (errno == EAGAIN)
08132         {
08133           DBG (DBG_sane_info, "sane_read: EAGAIN\n");
08134           return SANE_STATUS_GOOD;
08135         }
08136       else
08137         {
08138           pie_do_cancel (scanner);      /* we had an error, stop scanner */
08139           return SANE_STATUS_IO_ERROR;
08140         }
08141     }
08142 
08143   *len = nread;
08144 
08145   if (nread == 0)               /* EOF */
08146     {
08147       pie_do_cancel (scanner);
08148 
08149       return pie_close_pipe (scanner);  /* close pipe */
08150     }
08151 
08152   return SANE_STATUS_GOOD;
08153 }
08154 
08155 
08156 /* ------------------------------------- SANE CANCEL -------------------------------- */
08157 
08158 
08159 void
08160 sane_cancel (SANE_Handle handle)
08161 {
08162   Pie_Scanner *scanner = handle;
08163 
08164   DBG (DBG_sane_init, "sane_cancel\n");
08165 
08166   if (scanner->device->model == NULL)
08167     {
08168       if (scanner->scanning)
08169         pie_do_cancel (scanner);
08170     }
08171   else                  /* USB film scanners */
08172     pie_usb_do_cancel (scanner, SANE_TRUE);
08173 }
08174 
08175 
08176 /* -------------------------------------- SANE SET IO MODE --------------------------- */
08177 
08178 
08179 SANE_Status
08180 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
08181 {
08182   Pie_Scanner *scanner = handle;
08183 
08184   DBG (DBG_sane_init, "sane_set_io_mode: non_blocking=%d\n", non_blocking);
08185 
08186   if (!scanner->scanning)
08187     {
08188       return SANE_STATUS_INVAL;
08189     }
08190 
08191   if (fcntl (scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
08192     {
08193       return SANE_STATUS_IO_ERROR;
08194     }
08195 
08196   return SANE_STATUS_GOOD;
08197 }
08198 
08199 
08200 /* --------------------------------------- SANE GET SELECT FD ------------------------- */
08201 
08202 
08203 SANE_Status
08204 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
08205 {
08206   Pie_Scanner *scanner = handle;
08207 
08208   DBG (DBG_sane_init, "sane_get_select_fd\n");
08209 
08210   if (!scanner->scanning)
08211     {
08212       return SANE_STATUS_INVAL;
08213     }
08214   *fd = scanner->pipe;
08215 
08216   return SANE_STATUS_GOOD;
08217 }
08218 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines