home *** CD-ROM | disk | FTP | other *** search
- //*********************************************************************
- //
- // ScanmakerE3 Scanner device
- //
- // version 98.06.01
- //
- //*********************************************************************
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
- #include <string.h>
- #include <math.h>
-
- #include <exec/types.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include "scsi.h"
- #include "Scanner.h"
- #include "Scanner_protos.h"
-
- //
- // NOTE!!!
- //
- // The name in the following two lines (here: ScanmakerE3)
- // must be the same as the name of the device.
- //
- // Do not change the string names (DevName and DevIdName)
- //
- char DevName[] = "ScanmakerE3.device";
- char DevIdString[] = "ScanmakerE3";
-
- typedef unsigned char SCSICmd[6];
-
- // Scanner specifik defines
- #define MAX_BASE_RES 300
- #define MAX_EXT_RES 300
-
- // scanning modes
- #define SCANMODE_HALFTONE 0
- #define SCANMODE_BW 1
- #define SCANMODE_GREY 2
- #define SCANMODE_COLOR 3
-
-
- #define SCANBUFSIZE 32000
-
- #define MAX_BUSY_RETRY 5
-
-
- static UBYTE* scanBuffer = NULL;
-
- // Stored scanning parameters
- //
- static double x0; /* Scanning frame in mm */
- static double y0;
- static double x1;
- static double y1;
- static UBYTE resolutionCode; /* Resolution in % of max resolution */
- static UBYTE resolutionFlag; /* Further resolution information */
- static WORD brightness[3]; /* Brightness for red, green and blue */
- static WORD contrast; /* Contrast */
- static WORD shadow; /* shadow adjust 0..1023 (default 0) */
- static WORD highlight; /* highlight adjust 0..1023 (def. 0) */
- static WORD midtone; /* midtone adjust 0..1023 (def. 512) */
- static WORD halftonePattern;/* halftonePattern 0..255 (def. 0) */
- static WORD exposureTime; /* Exposure time */
- static double gamma; /* gamma value */
- static WORD scanMode; /* see above */
- static BOOL extendedRes; /* extended resolution */
- static BOOL parametersSet; /* parameters are set */
-
- // Actual scanning values
- //
- static UWORD imageWidth;
- static UWORD imageHeight;
- static UWORD bytesPerLine;
- static UWORD xResolution;
- static UWORD yResolution;
-
- // Parameters used during scanning
- //
- static BOOL scanning; /* Scanner is scanning */
- static int lineWidth; /* Length of one scan line including color informat. */
- static int scanLines; /* Total number of lines to read from scanner */
- static int numPlanes; /* 3 for rgb24, otherwise 1 */
- static int bufferLen; /* Length of scanBuffer in number of lines */
- static int linesRead; /* Lines already read from scanner */
- static int linesInBuf; /* Number of lines read from scanner in scanBuffer */
- static int currentLine; /* Next line from scanBuf to return to user */
- static int nextPlane; /* next plane number to return to readScanLine */
-
- //
- // Make color correction table for brightness and contrast
- //
-
- UBYTE corrTab[256];
-
- void makeCorrTab(int bright,int contrast)
- {
- int i,b,c;
- UBYTE* tab;
-
- tab = corrTab;
- bright = (bright*255)/100;
- c = 100+contrast;
- for( i = 0 ; i < 256 ; i++ )
- {
- b = ((i+bright)*c-50*contrast)/100;
- *(tab++) = b>255?255:(b<0?0:(UBYTE)b);
- }
- }
-
- static BYTE senseError(void)
- {
- BYTE error;
-
- switch( scsi_sensebuffer[0] )
- {
- case 0x00: // ????
- error = SCAN_ERR_READY;
- break;
- case 0x81: // Comand or data error
- case 0x83: // Operation error (illegal parameter values)
- error = SCAN_ERR_PARAMETER;
- break;
- case 0x82: // Hardware error
- error = SCAN_ERR_HARDWARE;
- break;
- default: // Other communication error
- error = SCAN_ERR_COMMUNICATION;
- break;
- }
- return error;
- }
-
- /*------------------------------------------------------------------------*/
- static void scannerReady(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd TEST_UNIT_READY = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- int retry = 0;
-
- while( !writeSCSI(TEST_UNIT_READY, 6, NULL, 0, NULL, 0) )
- {
- retry++;
- if (retry == 5)
- {
- *error = SCAN_ERR_READY;
- return;
- }
- Delay(3*50);
- }
- }
- }
-
-
- /*------------------------------------------------------------------------*/
- static void setScanningFrame(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd SCANNING_FRAME = { 0x04, 0x00, 0x00, 0x00, 0x09, 0x00 };
- UBYTE frame_data[9];
-
- int xf0,yf0,xf1,yf1;
- int dpi;
-
- frame_data[0] = 0x00;
- if( scanMode == SCANMODE_HALFTONE )
- frame_data[0] |= 0x01;
-
- // Unit is pixel
- //
- frame_data[0] |= 0x08;
-
- dpi = MAX_BASE_RES;
- xf0 = (int)((double)(x0*dpi)/25.4);
- yf0 = (int)((double)(y0*dpi)/25.4);
- xf1 = (int)((double)(x1*dpi)/25.4);
- yf1 = (int)((double)(y1*dpi)/25.4);
-
- frame_data[1] = (UBYTE)(xf0 & 0xff);
- frame_data[2] = (UBYTE)((xf0 & 0xff00) >> 8);
- frame_data[3] = (UBYTE)(yf0 & 0xff);
- frame_data[4] = (UBYTE)((yf0 & 0xff00) >> 8);
- frame_data[5] = (UBYTE)(xf1 & 0xff);
- frame_data[6] = (UBYTE)((xf1 & 0xff00) >> 8);
- frame_data[7] = (UBYTE)(yf1 & 0xff);
- frame_data[8] = (UBYTE)((yf1 & 0xff00) >> 8);
-
- if( !writeSCSI(SCANNING_FRAME, 6, frame_data, 9, NULL, 0) )
- *error = senseError();
- }
- }
-
-
- /*------------------------------------------------------------------------*/
- static void selectMode(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd MODE_SELECT = { 0x15, 0x00, 0x00, 0x00, 0x0B, 0x00 };
- UBYTE mode_data[11];
-
- mode_data[0] = 0x81;
-
- // Set resolution
- mode_data[0] |= 0x02;
- mode_data[1] = resolutionCode;
- mode_data[2] = (exposureTime/3)+7;
- mode_data[3] = (contrast+49)/7;
- mode_data[4] = halftonePattern;
- mode_data[5] = 0x01;
- mode_data[6] = shadow;
- mode_data[7] = highlight;
- mode_data[8] = 0x6C;
- mode_data[9] = 0x00;
- mode_data[10] = midtone;
-
- if( !writeSCSI(MODE_SELECT, 6, mode_data, 11, NULL, 0) )
- *error = senseError();
- }
- }
-
- /*------------------------------------------------------------------------*/
- void mode_sense_1(BYTE *error)
- {
-
- if( *error == 0 )
- {
- SCSICmd MODE_SELECT_1 = { 0x16, 0x00, 0x00, 0x00, 0x0a, 0x00 };
- unsigned char mode_data[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- mode_data[1] = (UBYTE)(brightness[0]);
-
- if( !writeSCSI(MODE_SELECT_1, 6, mode_data, 10, NULL, 0) )
- *error = senseError();
- }
- if( *error == 0 )
- {
- SCSICmd MODE_SENSE_1 = { 0x19, 0x00, 0x00, 0x00, 0x1e, 0x00 };
- unsigned char mode_data[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- mode_data[1] = (UBYTE)(brightness[0]);
- mode_data[2] = (UBYTE)(brightness[1]);
- mode_data[3] = (UBYTE)(brightness[2]);
- if( !writeSCSI(MODE_SENSE_1, 6, mode_data, 30, NULL, 0) )
- *error = senseError();
- }
- }
-
- /*------------------------------------------------------------------------*/
- /* int lut_download (char filter, char *gtable, int gt_entries) */
- /* Issue the LOOK-UP-TABLE DOWNLOAD command to the scanner to download */
- /* the gamma table pointed to by <gtable>. <filter> determines the color */
- /* to which the table applies (RED, GREEN, BLUE, or CLEAR; values other */
- /* than CLEAR may only be specified for one-pass color scanners). The */
- /* number of entries is determined by <entries> (256, 1024, 4096 or */
- /* 65536). The entry width is automatically assumed to be one byte if the */
- /* number of entries is 256 and two bytes otherwise. */
- /*------------------------------------------------------------------------*/
-
- void gammaTable(double g, BYTE *error)
- {
- if( *error == 0 )
- {
- UBYTE LUT_DOWNLOAD[10] = {0x55,0x00,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
- UBYTE gTable[256];
- int i;
-
- LUT_DOWNLOAD[7] = (UBYTE)((256 & 0xff00) >> 8);
- LUT_DOWNLOAD[8] = (UBYTE)(256 & 0xff);
-
- if( (g <= 0.0) || (g == 1.0) )
- {
- for( i = 0 ; i < 256 ; i++ )
- gTable[i] = (UBYTE)i;
- }
- else
- {
- for( i = 0 ; i < 256 ; i++ )
- gTable[i] = (UBYTE)(256.0*pow(((double)i)/256.0,1/g));
- }
-
- if( !writeSCSI(LUT_DOWNLOAD,10,gTable,256,NULL,0) )
- *error = senseError();
- }
- }
-
- /*------------------------------------------------------------------------*/
- static void accessory(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd ACCESSORY = { 0x10, 0x00, 0x00, 0x00, 0x9A, 0x00 };
-
- if( !writeSCSI(ACCESSORY, 6, NULL, 0, NULL, 0) )
- *error = senseError();
- }
- }
-
- /*------------------------------------------------------------------------*/
- static void startScan(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd START_SCAN = { 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00 };
-
- switch( scanMode )
- {
- case SCANMODE_HALFTONE:
- case SCANMODE_BW:
- break;
- case SCANMODE_COLOR:
- START_SCAN[4] |= 0x20; // 1-pass color
- case SCANMODE_GREY:
- START_SCAN[4] |= 0x40; // Multibit
- break;
- }
- if( extendedRes )
- START_SCAN[4] |= 0x80; // extended resolution
-
- if( !writeSCSI(START_SCAN, 6, NULL, 0, NULL, 0) )
- *error = senseError();
- }
- }
-
-
- /*------------------------------------------------------------------------*/
- static void stopScan(BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd STOP_SCAN = { 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- if( !writeSCSI(STOP_SCAN, 6, NULL, 0, NULL, 0) )
- *error = senseError();
- }
- }
-
- /*------------------------------------------------------------------------*/
- static void readScanStatus(int *busy, int *lineWidth, int *linesRemain,BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd GET_SCAN_STATUS = { 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00 };
- UBYTE status_reply[6];
- int retry = 0;
-
- do
- {
- if( !writeSCSI(GET_SCAN_STATUS,6,NULL,0,status_reply,6) )
- {
- *error = senseError();
- return;
- }
- *busy = (int)(status_reply[0] != 0);
- *lineWidth = (int)(status_reply[1] + 256 * status_reply[2]);
- *linesRemain = (int)(status_reply[3]+256*status_reply[4]+256*256*status_reply[5]);
- if( *busy )
- {
- retry++;
- Delay(3*50);
- }
- }
- while( (*busy) && (retry < MAX_BUSY_RETRY) );
- if( *busy )
- *error = SCAN_ERR_READY;
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* */
- /* Read lines from scanner */
- /* */
- /* The number of lines to read must be specified. For color scanning */
- /* the length of one line is three times line width although the lines */
- /* returned is not in correct sequence (r-g-b). */
- /* */
- /*----------------------------------------------------------------------*/
-
- static void readScanData(int nlines,UBYTE *buffer,int bsize,BYTE *error)
- {
- if( *error == 0 )
- {
- SCSICmd READ_SCANNED_DATA = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- READ_SCANNED_DATA[2] = (UBYTE)((nlines & 0xff0000) >> 16);
- READ_SCANNED_DATA[3] = (UBYTE)((nlines & 0xff00) >> 8);
- READ_SCANNED_DATA[4] = (UBYTE)(nlines & 0xff);
- if( !writeSCSI(READ_SCANNED_DATA,6,NULL,0,buffer,bsize) )
- *error = senseError();
- }
- }
-
-
- //
- //
- void closeScanner(void)
- {
- if( scanBuffer )
- {
- free(scanBuffer);
- scanBuffer = NULL;
- }
- closeSCSI();
- }
-
-
- void openScanner(char* name,int unit,struct ScannerOptions* option,BYTE* status)
- {
- scanning = FALSE;
- scanLines = 0;
- linesRead = 0;
-
- if( openSCSI(name,unit) )
- {
- if( scanBuffer = (UBYTE*)malloc(SCANBUFSIZE) )
- {
- strcpy(option->so_vendor,"Microtek");
- strcpy(option->so_model,"Scanmaker E3");
- option->so_version = 4;
- option->so_revision = 4;
-
- option->so_colorMode = COLORNUM_HALFTONE|COLORNUM_BW|COLORNUM_GREY8|COLORNUM_RGB24;
- option->so_opticResolution = MAX_BASE_RES;
- option->so_opticResStep = MAX_BASE_RES/100;
- option->so_interResolution = MAX_EXT_RES;
- option->so_interResStep = MAX_EXT_RES/100;
-
- option->so_brightnessMin = 0; //-100;
- option->so_brightnessMax = 100;
- option->so_brightnessStep = 1;
- option->so_brightnessDefault = 0;
-
- option->so_contrastMin = -50; //-42;
- option->so_contrastMax = 50; //49;
- option->so_contrastStep = 1; //7;
- option->so_contrastDefault = 0;
-
- // These three do not work well with Phantom 4800
-
- //option->so_shadowMin = 0;
- //option->so_shadowMax = 255;
- //option->so_shadowStep = 1;
- //option->so_shadowDefault = 0;
-
- //option->so_highlightMin = 0;
- //option->so_highlightMax = 255;
- //option->so_highlightStep = 1;
- //option->so_highlightDefault = 255;
-
- //option->so_midtoneMin = 0;
- //option->so_midtoneMax = 255;
- //option->so_midtoneStep = 1;
- //option->so_midtoneDefault = 128;
-
- option->so_exposureTimeMin = -18;
- option->so_exposureTimeMax = 21;
- option->so_exposureTimeStep = 3;
- option->so_exposureTimeDefault = 0;
-
- option->so_velocityMin = 1;
- option->so_velocityMax = 7;
- option->so_velocityStep = 1;
- option->so_velocityDefault = 1;
-
- option->so_halftonePatternMin = 0;
- option->so_halftonePatternMax = 11;
- option->so_halftonePatternStep = 1;
- option->so_halftonePatternDefault = 0;
-
- option->so_maxLookupTableSize = 256;
- option->so_docWidth = 215.9;
- option->so_docLength = 296.9;
-
- *status = 0;
- }
- else
- {
- closeScanner();
- *status = SCAN_ERR_MEMORY;
- }
- }
- else
- *status = SCAN_ERR_DEVICEOPEN;
- }
-
- void setParameter(struct ScanParameters* param,BYTE* status)
- {
- switch( param->sp_ColorNum )
- {
- case COLORNUM_HALFTONE:
- scanMode = SCANMODE_HALFTONE;
- break;
- case COLORNUM_BW:
- scanMode = SCANMODE_BW;
- break;
- case COLORNUM_GREY8:
- scanMode = SCANMODE_GREY;
- break;
- case COLORNUM_RGB24:
- scanMode = SCANMODE_COLOR;
- break;
- default:
- *status = SCAN_ERR_PARAMETER;
- parametersSet = FALSE;
- return;
- }
-
- // Frame in mm
- x0 = param->sp_x0;
- y0 = param->sp_y0;
- x1 = param->sp_x1;
- y1 = param->sp_y1;
-
- // Resolution code and actual resolution
- if( param->sp_xResolution > MAX_BASE_RES )
- {
- resolutionCode = (param->sp_xResolution*100)/MAX_EXT_RES;
- resolutionFlag = 0;
- extendedRes = TRUE;
- xResolution = (resolutionCode*MAX_EXT_RES)/100;
- yResolution = (resolutionCode*MAX_EXT_RES)/100;
- }
- else
- {
- resolutionCode = (param->sp_xResolution*100)/MAX_BASE_RES;
- resolutionFlag = 0;
- extendedRes = FALSE;
- xResolution = (resolutionCode*MAX_BASE_RES)/100;
- yResolution = (resolutionCode*MAX_BASE_RES)/100;
- }
-
- // Brightness, contrast and exposure time
- brightness[0] = 0; //param->sp_brightness[0];
- brightness[1] = 0; //param->sp_brightness[1];
- brightness[2] = 0; //param->sp_brightness[2];
- shadow = 0; //param->sp_shadow;
- highlight = 255; //param->sp_highlight;
- midtone = 128; //param->sp_midtone;
- halftonePattern = param->sp_halftonePattern;
- contrast = 0; //param->sp_contrast;
- exposureTime = param->sp_exposureTime;
- gamma = param->sp_gamma;
- // extendedRes = 0;
-
- *status = 0;
- scannerReady(status);
- selectMode(status);
- mode_sense_1(status);
- setScanningFrame(status);
- gammaTable(gamma,status);
- accessory(status);
-
- //
- // brightness and contrast is simulated by this driver
- //
- makeCorrTab(param->sp_brightness[0],param->sp_contrast);
-
- if( *status )
- parametersSet = FALSE;
- else
- parametersSet = TRUE;
- }
-
- void startScanning(struct ScanInformation* inform,BYTE* status)
- {
- if( parametersSet )
- {
- int busy;
-
- *status = 0;
- startScan(status);
- readScanStatus(&busy,&lineWidth,&scanLines,status);
-
- if( lineWidth <= 0 )
- *status = SCAN_ERR_MISC;
-
- if( *status == 0 )
- {
- switch( scanMode )
- {
- case SCANMODE_HALFTONE:
- case SCANMODE_BW:
- bytesPerLine = lineWidth;
- imageWidth = lineWidth*8;
- imageHeight = scanLines;
- numPlanes = 1;
- break;
- case SCANMODE_GREY:
- if( extendedRes )
- bytesPerLine = lineWidth*2-1;
- else
- bytesPerLine = lineWidth;
- imageWidth = bytesPerLine;
- imageHeight = scanLines;
- numPlanes = 1;
- break;
- case SCANMODE_COLOR:
- if( extendedRes )
- bytesPerLine = (lineWidth-2)*2-1;
- else
- bytesPerLine = lineWidth-2;
- imageWidth = bytesPerLine;
- imageHeight = scanLines;
- numPlanes = 3;
- break;
-
- }
- bufferLen = SCANBUFSIZE/lineWidth/numPlanes;
- linesRead = 0;
- linesInBuf = 0;
- currentLine = 0;
- nextPlane = 0;
-
- inform->sv_imageWidth = imageWidth;
- inform->sv_imageHeight = imageHeight;
- inform->sv_bytesPerLine = bytesPerLine;
- inform->sv_Flags = 0;
- inform->sv_xResolution = xResolution;
- inform->sv_yResolution = yResolution;
-
- scanning = TRUE;
- }
- }
- else
- *status = SCAN_ERR_PARAMETER;
- }
-
- void stopScanning(void)
- {
- BYTE status = 0;
-
- if( scanLines != linesRead )
- stopScan(&status);
- scanning = FALSE;
- }
-
- void readScanLine(UBYTE* data,ULONG* length,BYTE* status)
- {
- if( !scanning )
- *status = SCAN_ERR_NOTSCANNING;
- else if( *length < bytesPerLine+1 )
- *status = SCAN_ERR_MISC;
- else if( (scanLines == linesRead) && (currentLine == linesInBuf) )
- *status = SCAN_STATUS_EOF;
- else
- {
- UBYTE* bptr;
-
- if( currentLine == linesInBuf )
- {
- if( bufferLen < scanLines-linesRead )
- linesInBuf = bufferLen;
- else
- linesInBuf = scanLines-linesRead;
-
- readScanData(linesInBuf,scanBuffer,linesInBuf*lineWidth*numPlanes,status);
-
- if( *status )
- {
- *length = 0;
- return;
- }
-
- linesRead += linesInBuf;
- currentLine = 0;
- }
-
- bptr = scanBuffer + (numPlanes*currentLine+nextPlane)*lineWidth;
-
- if( scanMode == SCANMODE_COLOR )
- {
- *(data++) = (bptr[1] == 'R') ? 0 : ((bptr[1] == 'G') ? 1 : 2);
- bptr += 2;
- }
- else
- *(data++) = 0;
-
- if( !extendedRes )
- {
- int i;
-
- for( i = 0 ; i < bytesPerLine ; i++ )
- {
- *(data++) = corrTab[*(bptr++)];
- }
-
- *length = bytesPerLine+1;
- }
- else
- {
- int i;
-
- *(data++) = corrTab[*bptr];
- for( i = 1 ; i < (bytesPerLine+1)/2 ; i++ )
- {
- *(data++) = (corrTab[*(bptr++)]+corrTab[(*bptr)])/2;
- *(data++) = corrTab[*bptr];
- }
-
- *length = bytesPerLine+1;
- }
-
- if( ++nextPlane == numPlanes )
- {
- nextPlane = 0;
- currentLine++;
- }
- }
- if( *status )
- *length = 0;
- }
-