Making a Scanner Driver ======================= A scanner driver is made as an Amiga Device. The Device I/O request ---------------------- The scanner device uses a special I/O request: struct ScannerIO { struct IOStdReq IOScan; struct ScannerOptions option; } where struct IOStdReq is a standard IO request as defined in exec/io.h and struct ScannerOptions is defined in the include file scanner.h Before opening the device BetaScan places a pointer to a string containing the name of the IO unit where the scanner is connected (for instance scsi.device) in the IOScan.io_Data field. Then the open device is called: OpenDevice(scannerName,unit,(struct IORequest *)ScannerIO,0) where unit is the unit number of the IO unit. The open routine must do the necessary initializations and then set the fields in the structure option. This is to tell BetaScan what the scanner is able to do. You must set the following fields: so_vendor; so_model; so_version; so_revision; so_colorMode; so_opticResolution; so_opticResStep; so_interResolution; so_interResStep; double so_docWidth; /* Paper size in mm */ double so_docLength; All other fields are optional. Do not touch if the facility is not supported by your scanner. The structure is filled with zero before the device is opened. IO Commands ----------- The device must respond to the following commands: CMD_START - Start scanning The scanning parameters must have been set before (SCANCMD_SET). The IOScan.io_Data field contains a pointer to a structure struct ScanInformation { UWORD sv_imageWidth; /* image width in pixels */ UWORD sv_imageHeight; /* image height in pixels */ UWORD sv_bytesPerLine; /* bytes per line read (excl. color) */ UWORD sv_Flags; /* data information flags (set to 0) */ UWORD sv_xResolution; /* actual horizontal resolution */ UWORD sv_yResolution; /* actual vertical resolution */ } Most scanners must do some roundings so that your scanner parameters are not exactly the actual ones. Fill in the actual parameter values in this structure. The field sv_bytesPerLine is normally the same as sv_imageWidth (except for B/W scanning). CMD_STOP - Stop scanning This command is always send (even if the driver has send all scan lines or has reported an error). CMD_READ - Read one or more scan lines The IOScan.io_Data field contains a pointer to a data buffer and the IOScan.io_Length the buffer length. Copy scan line data to this buffer. The first byte of of a scan line must be the color: 0 = red, 1 = green and 2 = blue (0 if grey scale or B/W). The bytes 1,2,...,sv_bytesPerLine+1 are the actual scanned data. Note that you have to separate the colors (if this is not already done by the scanner). In this way it is possible to handle 3-pass scanning. Return the actual number of bytes returned (an integral multiple of sv_bytesPerLine+1). SCANCMD_SET - Set scanning parameters (command value defined in scanner.h) The field IOScan.io_Data contains a pointer to the structure (found in scanner.h): struct ScanParameters { ULONG sp_ColorNum; /* 0: halftone, >0: number of colors */ double sp_x0; /* Scanning frame in mm */ double sp_y0; double sp_x1; double sp_y1; UWORD sp_xResolution; /* Horizontal resolution */ UWORD sp_yResolution; /* Vertical resolution */ WORD sp_brightness[3]; /* Brightness for red, green and blue */ WORD sp_contrast; /* Contrast */ WORD sp_shadow; /* shadow adjust */ WORD sp_highlight; /* highlight adjust */ WORD sp_midtone; /* midtone adjust */ WORD sp_halftonePattern; /* halftomePattern */ WORD sp_exposureTime; /* Exposure time */ double sp_gamma; /* gamma value */ ULONG sp_flags; } It is up to you if you want to send the values directly to the scanner or store them until the CMD_START is send. Actual development ------------------ To avoid making all the nasty device stuff and to facilitate the testing you can use the files in the ScannerDev directory (SAS/C 6.57). By using these files you only have to make a single file with the following routines: void openScanner(char* name,int unit,struct ScannerOptions* option,BYTE* status) This is called when the scanner device is opened. input: name: name of the IO unit unit: number of the IO unit option: pointer to the option structure status: the return value (io_Error) void closeScanner(void) Close the scanner void setParameter(struct ScanParameters* param,BYTE* status) Set scanning parameters input: param: pointer to a parameter structure status: the return value void startScanning(struct ScanInformation* inform,BYTE* status) Start the scanning input: inform: a pointer to a ScanInformation structure to be filled by you. status: the return value void stopScanning(void) Stop the scanning void readScanLine(UBYTE* data,ULONG* length,BYTE* status) Read one ore more scan line(s) input: data: pointer to the data buffer length: pointer to an ULONG containing the buffer length fill with actual number at return status: the return value An example file is in ScanDev directory (in fact divided into two: ScanmakerE3.c and Scsi.c). To make a test version execute the command: smake -f smakeTest The resulting executable is called scanner. The command template for this is: scanner [options] where options are one or more of these: color=bw|gray|rgb24 default is: color=rgb24 frame=x0,y0,x1,y1 upper left and lower right corner in mm default is: frame=25,50,75,100 resolution=r resolution in dpi default is: resolution=300 brightness=b brightness in % default is scanner-default contrast=c contrast in % default is scanner-default shadow=s default is scanner-default highlight=h default is scanner-default midtone=m default is scanner-default pattern=p default is scanner-default time=t exposure time default is scanner-default gamma=g default is: gamma=1.0 compress=on|off default is: compress=on file= default is: file=ram:scanner.ilbm Example commands: scanner scanner color=grey frame=0,0,10,10 compress=off file=dh0:test.ilbm To make a device execute smake -f smakeDevice The linker will make 4 warnings about absolute addressing. Don't care.