Chapter 9. Generic Scanner Interface

This chapter describes the interface between a scanner driver and an application program.

The major topics discussed are:

Overview

The generic interface between a scanner driver and an application program is flexible enough to accommodate a wide range of scanners and application programs. Application programs that use this interface can use any scanner that has a driver that supports this interface. Providing a driver for a particular scanner allows it to be accessed by any program written to use this interface.

The interface is implemented by a run-time library and a driver program. All drivers must provide the entry points necessary for the run-time library to provide the interface described in this document. In order to provide access to scanner-specific capabilities, scanner drivers are free to expand the interface, which is then accessed by scanner-specific programs that have standard ways of being invoked by application programs. (See Chapter 8, "Scanner-Specific Options." )

For more details on the functions described in this chapter, see the online manual pages.

Coordinate System for Scanning

When describing an area to be scanned, a coordinate system with the origin (0,0) in the upper left corner of the scannable area is used. The x-coordinate increases from left to right, and the y-coordinate increases from top to bottom.

Note that this is the upper left corner of the document being scanned; in the case of a flatbed scanner where the document is placed face down in the bed, this is the upper right corner or lower left corner of the bed.

When functions in the interface specify measurements along the horizontal and vertical axes of the scan area, the following units can be used to specify distance:

  • SC_INCHES—measurements specified in inches

  • SC_CENTIM—measurements specified in centimeters

  • SC_PIXELS—measurements specified in pixels

Data Structures

This section describes the generic scanner interface data structures.

SCANNER Data Structure

typedef struct tag_scanner {
      ...
} SCANNER;

The application maintains a pointer to a SCANNER data structure (obtained from SCOpen) to specify the scanner to which operations should be applied.

SCDATATYPE Data Structure

Scanners support a variety of output data types. The SCDATATYPE struct encapsulates the common output data types produced by scanners.

typedef struct tag_scdatatype {
   unsigned int packing : 4;
   unsigned int channels : 4;
   unsigned int type : 8;
   unsigned int bpp : 8;
} SCDATATYPE;

Arguments:

packing 

The packing field can take on the following values:

SC_PACKPIX

All the data for each pixel is stored together; for example., a line of 24-bit color is stored as RGBRGBRGB.

SC_PACKBAND

Each line of data is decomposed into its channels; for example, a line of 24-bit color is stored as RRRGGGBBB.

SC_PACKPLANE

All the data for a channel is stored separately from other channels. A page of color data is split into three pages of data; one for red, one for blue, and one for green.


channel 

Number of components per pixel. Legal values are 1, 3, and 4. See type below.

type 

Type of data. This parameter indicates how the data in the various channels is to be interpreted:

SC_MONO

Monochrome: 1 channel and 1 bit per pixel.

 

SC_GREY

Greyscale: 1 channel.

 

SC_RGB

Red, green, and blue: 3 channels.

 

SC_CMY

Cyan, magenta, and yellow: 3 channels.

 

SC_CMYK

Cyan, magenta, yellow, and black: 4 channels.


bpp 

Bits Per Pixel (per channel). The number of bits per pixel in each channel. For monochrome data, there is 1 bit per pixel. For 24-bit RGB color, there are 8-bits per pixel (* 3 channels == 24-bits).

Data Type Conventions

Generic scanner applications need not be written to support any particular data type. There are four basic data types that are typically used:

  1. Monochrome. ALL scanner drivers MUST support the following monochrome format:

    • packing == SC_PACKPIX

    • channels == 1

    • type == SC_MONO

    • bpp == 1

  2. 8-bit greyscale. All scanner drivers that support any type of greyscale or color output MUST support the following 8-bit greyscale format:

    • packing == SC_PACKPIX

    • channels == 1

    • type == SC_GREY

    • bpp == 8

  3. Planar 24-bit RGB color. The red, green, and blue channels are scanned in three separate passes; in this case, the data type for is:

    • packing == SC_PACKPLANE

    • channels == 3

    • type == SC_RGB

    • bpp == 8

  4. Packed 24-bit RGB color. This applies to a one-pass color scanner that gets all of the data in one pass. The data type for color data from this kind of scanner is:

    • packing == SC_PACKPIX

    • channels == 3

    • type == SC_RGB

    • bpp == 8

A scanning application that is prepared to deal with these four data types should be able to interact well with any well-behaved scanner driver.

Functions

Diagnostic Functions

Many of the functions specified here return 0 upon success and -1 in the event of a failure. If a function's return value indicates failure, the reason for the failure can be determined by examining the value of the global variable SCerrno. SCerrno will be between 0 and LASTERRNO (defined in /usr/include/sys/errno.h) if the failure was due to a failed system call, and between SCEBASE and SCELAST (defined in scanner.h) if the failure was for some other reason. #defines for the values between SCEBASE and SCELAST can be found in /usr/include/scanner.h.

Table 9-1 lists the diagnostic functions.

Table 9-1. Diagnostic Functions

Function

Description

SCPerror

Prints an error string.

SCErrorString

Returns a character string containing an error message.


SCPerror Function

void SCPerror(char *ident)

This function prints the value of ident, a colon, and a string of text corresponding to the current value of SCerrno.

SCErrorString Function

char *SCErrorString(int err)

This function returns a character string containing a useful message describing the error condition represented by err. If err is not in the range 0 to LASTERRNO or SCEBASE to SCELAST, SCErrorString returns a text string containing the words "Error code err," where err is the value passed to SCErrorString.

Application/Driver Rendezvous Functions

Users refer to scanners by names given to them at install time. The installer uses scanners(1M), which adds entries to a mapping from scanner names to (driver, device, options) tuples. The mapping is contained in the file /var/scan/scanners. The driver and device components are used to start the right driver on the device to access the scanner given by name, and options is the scanner-specific options program. scanners(1M) allows the specification of a default scanner.

The application/driver Rendezvous functions are listed in Table 9-2 and described below.

Table 9-2. Application/Driver Rendezvous Functions

Function

Description

SCOpen

Prepares to perform operations on the scanner named by name.

SCOpenScreen

Calls the screen scanner driver to scan from the specified screen.

SCOpenFile

Calls the file scanner driver to scan from the specified file.

SCClose

Breaks the connection between the application and the driver.

SCSetScanEnt

Opens the scanner configuration file and returns a pointer.

SCGetScanEnt

Gets a SCANENT structure for each installed scanner.

SCEndScanEnt

Frees the resources used to enumerate scanners.

SCScannerName

Returns the name associated with the scanner at installation.

SCScannerEnt

Returns the SCANENT structure of an open scanner.

SCDefaultScannerName

Gets the default scanner name, if any.


SCOpen Function

SCANNER *SCOpen(char *name)

The SCOpen function prepares to perform operations on the scanner named by name by starting the appropriate driver on the appropriate device. SCOpen performs the lookup in the name -> (driver, device, options) mapping. If name is NULL, the default scanner is used.

SCOpen returns a pointer to a SCANNER struct if successful, or NULL if there is an error. If name is NULL and no default scanner has been set, SCOpen opens the first scanner found in /usr/lib/scan/scanners.

SCOpenScreen Function

SCANNER *SCOpenScreen(char *screen)

This function invokes the screen scanner driver to scan from the specified screen. It returns a pointer to a SCANNER struct if successful, NULL if there is an error.

SCOpenFile Function

SCANNER *SCOpenFile(char *file)

This function invokes the file scanner driver to scan from the specified file. It returns a pointer to a SCANNER struct if successful, NULL if there is an error.

SCClose Function

int SCClose(SCANNER *s)

This function breaks the connection between the application and the driver program. It returns 0 on success, -1 if there is an error.

SCSetScanEnt Function

FILE *SCSetScanEnt(void)

This function opens the scanner configuration file. It returns a pointer to the open FILE structure on success, NULL if there is an error.

SCGetScanEnt Function

typedef struct tag_scanent {
   char *name;
   char *driver;
   char *device;
   char *options;
} SCANENT;

SCANENT *SCGetScanEnt(FILE *fp)

To get a SCANENT structure for each scanner installed on the system, this function should be called repeatedly until it returns NULL. The contents of the memory pointed to by the return value of SCGetScanEnt are undefined after any subsequent calls to this function, so copy the return value if you need to preserve it across calls to SCGetScanEnt.

SCEndScanEnt Function

int SCEndScanEnt(FILE *fp)

This function frees the resources used to enumerate scanners. It returns 0 on success, -1 if there is an error.

SCScannerName Function

char *SCScannerName(SCANNER *s)

This function returns the name associated with the scanner at installation. Applications can use this to get at the name of the default scanner being used if SCOpen was called with NULL. It returns a pointer to a character string on success, NULL if there is an error. The memory pointed to by the return value of SCScannerName belongs to libscan and should not be modified or freed.

SCScannerEnt Function

SCANENT *SCScannerEnt(SCANNER *s)

This function returns the a SCANENT structure describing an open scanner. The memory pointed to by the returned value of SCScannerEnt belongs to libscan and should not be modified or freed.

SCDefaultScannerName Function

char *SCDefaultScannerName(void)

This function gets the default scanner name, if any. It returns the name of the default scanner, or NULL if no default scanner has been set. The memory pointed to by the returned value of SCDefaultScannerName belongs to libscan and should not be modified or freed.

Scanning Resolution Functions

Scanners typically support a range of resolutions (pixels per inch). Scanner drivers should support any resolution between the minimum and maximum resolutions supported by the scanner, decimating or replicating pixels as necessary to support the requested resolution. This gives the application the opportunity to preview the scanning area in an arbitrarily sized window.

It is not the scanner driver's responsibility to perform higher quality scaling of the image data. SCGetScannerRes can be used by the scanner application to determine which resolutions are supported directly by the scanner without decimation or replication by the driver.

SCGetScannerRes Function

int SCGetScannerRes(SCANNER *s, int metric, 
    float **xres, float **yres, int *nres)

This function returns arrays of hardware-supported resolutions. The xres and yres arrays specify supported horizontal and vertical resolutions. metric should be one of SC_INCHES or SC_CENTIM. nres sets the number of resolution pairs in the xres and yres arrays. SCGetScannerRes returns 0 if successful, -1 if there is an error.

SCGetMinMaxRes Function

int SCGetMinMaxRes(SCANNER *s, int metric, 
    float *minx, float *miny, float *maxx, float *maxy);

This function determines the resolution bounds; that is, the minimum and maximum horizontal and vertical resolutions that the scanner supports. It is an error to call SCGetMinMaxRes with "metric == SC_PIXELS." SCGetMinMaxRes returns 0 if successful, -1 if there is an error.

Scanning Area Functions

A scan may be limited by the application to a subset of the scannable area supported by the scanner. SCGetPageSize is provided so that applications can determine the size of the scannable area supported by the scanner.

SCGetPageSize Function

int SCGetPageSize(SCANNER *s, int metric, float *x, float *y,
                  float *width, float *height)

This function gets the entire scannable area. It is an error to call it with "metric == SC_PIXELS." SCGetPageSize returns 0 if successful, -1 if there is an error.

SCGetDataTypes Function

int SCGetDataTypes(SCANNER *s, SCDATATYPE **dt, int *ntypes)

This function sets *dt to point to an array of the data types supported by the scanner driver. ntypes gets the number of data types supported. The memory pointed to by *dt belongs to libscan and should not be modified or freed. It should also not be expected to retain its values after subsequent calls to SCGetDataTypes.

Scanning Functions

After SCOpen has been called, the scanner is idle. In order to initiate a scan, the functions SCSetup and SCScan are called. Characteristics of the data to be scanned can be determined with SCGetScanSize. A scan in progress can be aborted at any time with the function SCAbort. The scanner status can be determined by calling the function SCGetStatus.

Table 9-3 lists the available scanning functions.

Table 9-3. Scanning Functions

Function

Description

SCSetup

Prepares the scanner for a scan.

SCGetScanSize

Determines the width, height, and number of bytes per scan line.

SCScan

Starts scanning.

SCGetScanLine

Retrieves scan line data.

SCDataReady

Determines whether any data is available.

SCGetFD

Returns the file descriptor for scan data.

SCScanFD

Starts scanning (alternative call).

SCAbort

Aborts the current scan.

SCGetStatus

Gets the status of the scanner.

SCGetStatusFD

Returns a file descriptor for scan status.


SCSetup Function

SCSetup(SCANNER *s, int preview, SCDATATYPE *type,
      int rmetric, float xres, float yres,
      int wmetric, float x, float y, float width, 
      float height)

This function is used to prepare the scanner for a scan. The type of data, the resolution, and the scanning area are specified. preview is nonzero if this is a "preview" scan; that is, when the driver is faced with a trade-off between speed and image quality, it should choose speed since this is not the "real" scan. After calling SCSetup, SCScan is called to actually initiate scanning. SCSetup returns 0 if successful, -1 if there is an error.

SCGetScanSize Function

int SCGetScanSize(SCANNER *s, int *width, int *height,
                  int *bytesPerLine)

This function is called after SCSetup to determine the width, height, and number of bytes per scan line that will be returned by the driver. It returns 0 if successful, -1 if there is an error.

SCScan Function

int SCScan(SCANNER *s)

This function tells the driver to start scanning. The driver immediately starts to scan and buffer the data. SCScan does not fetch any scan data (see SCGetScanLine). SCScan returns 0 if successful, -1 if there is an error.

SCGetScanLine Function

int SCGetScanLine(SCANNER *s, void *buf, int bytes)

This function retrieves scan line data. bytes should be set to the number of bytes in a scan line as determined by SCGetScanSize.

Note that for color planar data, SCGetScanLine is called once for each line in each plane of data. For 100 lines of 24-bit RGB planar data, SCGetScanLine is called a total of 300 times, with the first 100 calls retrieving the red plane, the second 100 calls retrieving the green plane, and the third 100 calls retrieving the blue plane.

SCDataReady Function

int SCDataReady(SCANNER *s)

This function is used to determine whether any data is available for calls to SCGetScanLine; that is, whether a call to SCGetScanLine will block waiting for data to become available.

SCDataReady returns 1 if data is available (SCGetScanLine will not block), 0 if no data is available (SCGetScanLine will block), or -1 if there is an error. It is an error to call SCDataReady if scanning was started by a call to SCScanFD.

SCGetFD Function

int SCGetFD(SCANNER *s)

This function returns the file descriptor over which scan data from the scanner driver will be coming. Checking the state of this descriptor with the select(2) system call is equivalent to calling SCDataReady. If SCScanFD was called, SCGetFD returns the file descriptor that was passed to that function. SCGetFD returns -1 if there is an error.

SCScanFD Function

int SCScanFD(SCANNER *s, int fd)

This function is an alternative to calling SCScan to start scanning and SCGetLine to fetch the data. After SCScanFD is called, the driver writes the scanned data to fd; this is useful if the output data format of the scanner interface matches the input data type of another interface. SCScanFD returns 0 if successful, -1 if there is an error.

SCAbort Function

int SCAbort(SCANNER *s)

This function aborts the current scan. Data buffered by the driver is discarded. SCAbort returns 0 if successful, -1 if there is an error.

SCGetStatus Function

enum scstate { SC_READY, SC_SCANNING, SC_ERROR };
typdef struct tag_scstatus {
    enum scstate state;      /* ready, scanning, error */
    int errno;               /* only valid if state == SC_ERROR */
    long curline;            /* current line being scanned */
    int pass;                /* current scanning pass */
} SCSTATUS;

int SCGetStatus(SCANNER *s, SCSTATUS *st)

This function gets the status of the scanner. It returns 0 if successful, -1 if there is an error.

SCGetStatusFD Function

int SCGetStatusFD(SCANNER *s)

This function returns a file descriptor that can be passed to the select(2) system call. When select(2) indicates that the file descriptor is ready for reading, the scanner driver has updated the scanning status. Retrieve the status by calling SCGetStatus; do NOT pass the file descriptor returned from SCGetStatusFD to any other system call.

SCGetStatusFD provides a mechanism whereby it is not necessary for an application to periodically call SCGetStatus in a timer loop to detect changes in scanner status. SCGetStatusFD returns -1 if there is an error.

Document Feeder Functions

The scanner interface has provisions for the support of scanners that have document feeders attached. This facilitates the development of applications that can scan multiple pages without user intervention. Table 9-4 lists the document feeder functions.

Table 9-4. Document Feeder Functions

Function

Description

SCFeederGetFlags

Gets the feeder flags.

SCFeederSetFlags

Sets feeder flags.

SCFeederAdvance

Advances the feeder to the next document.

SCFeederReady

Checks if the feeder is ready for feeding.


SCFeederGetFlags Function

typedef unsigned int SCFEEDERFLAGS;

#define SC_HASFEEDER 1
#define SC_AUTOFEED  2
#define SC_PROGFEED  4

int SCFeederGetFlags(SCANNER *s, SCFEEDERFLAGS *flags);

This function fills in the flags variable with flags appropriate for the scanner associated with s. If SC_AUTOFEED and SC_PROGFEED are both set, SCFeederSetFlags should be called before any calls to SCScan to establish how the application is to interact with the feeder. The meanings of the flags are as follows:

SC_HASFEEDER

Set if there is a document feeder attached to the scanner.

SC_AUTOFEED

Set if the feeder can operate such that each call to SCScan causes the next document to be loaded.

SC_PROGFEED

Set if the feeder can operate so that SCScan can be called multiple times per document. It is necessary to call SCFeederAdvance to load the next document.

SCFeederGetFlags returns 0 if successful, -1 if there is an error.

SCFeederSetFlags Function

int SCFeederSetFlags(SCANNER *s, SCFEEDERFLAGS flags);

This function should be called before calling SCScan for scanners in which SCFeederGetFlags sets both SC_AUTOFEED and SC_PROGFEED. After calling SCFeederSetFlags(s, SC_AUTOFEED), the feeder advances to the next document after every call to SCScan. After calling SCFeederSetFlags(s, SC_PROGFEED), a call to SCFeederAdvance is necessary to advance to the next document. SCFeederSetFlags returns 0 if successful, -1 if there is an error.

SCFeederAdvance Function

int SCFeederAdvance(SCANNER *s)

This function advances the feeder to the next document. This call is valid only if the scanner supports the SC_PROGFEED mode. For scanners that support both the SC_AUTOFEED and SC_PROGFEED modes, SCFeederSetFlags(s, SC_PROGFEED) must have been called previously.

SCFeederAdvance returns 0 if successful, -1 if there is an error. When unloading the last document, this function returns -1 with SCerrno set to SCFEEDEREMPTY.

SCFeederReady Function

int SCFeederReady(SCANNER *s)

This function checks if the feeder is ready for feeding. SCFeederReady returns 0 if the feeder is ready, -1 if not. If the feeder is empty, SCerrno is set to SCFEEDEREMPTY; if any other error conditions exist, SCerrno is set appropriately.

Note that this function needs to be called before SCFeederAdvance to determine whether a document is ready to be scanned after the call to SCFeederAdvance.

Events

Scanner applications need to be aware that the configuration information about a scanner obtained from SCGetMinMaxRes, SCGetScannerRes, SCGetPageSize, and SCGetDataTypes can change. This typically happens when the user selects a new input medium using the scanner specific options panel. For example, some scanners support transparency options that have a different scanning page size than the normal scanning bed. When the user decides to scan transparencies, the driver will notify the application that it needs to call SCGetPageSize by sending an event. See Table 9-5 .

Table 9-5. Event Functions

Function

Description

SCGetEvent

Receives an event from the scanner driver.

SCEventPending

Tests whether an event is currently pending.

SCGetEventFD

Obtains an event file descriptor for passing to select(2).


SCGetEvent

typedef struct tag_infoChange {
    unsigned int pageSizeChanged : 1;
    unsigned int resolutionChanged : 1;
    unsigned int dataTypesChanged : 1;
    unsigned int feederFlagsChanged : 1;
} SCINFOCHANGE;

#define SCEVENT_INFOCHANGE 1

typedef struct tag_scevent {
    unsigned int eventType;
    union {
        SCINFOCHANGE infoChange;
    } event;
} SCEVENT;

int SCGetEvent(SCANNER *s, SCEVENT *event)

SCGetEvent is called to receive an event from the scanner driver. The event structure should be examined, and if the pageSizeChanged field is set, the application should call SCGetPageSize to query the new page size; if the resolutionChanged field is set the application should call SCGetMinMaxRes and SCGetScannerRes to query the new resolutions; if the dataTypesChanged field is set the application should call SCGetDataTypes to query the new data types, and if the feederFlagsChanged field is set the application should call SCGetFeederFlags to query the new feeder flags.

SCEventPending

int SCEventPending(SCANNER *s)

SCEventPending is called to test whether or not an event is currently pending. If an event is pending, the application should call SCGetEvent to receive it. SCEventPending returns 1 if any events are pending, and 0 if no events are pending.

SCGetEventFD

int SCGetEventFD(SCANNER *s)

SCGetEventFD returns a file descriptor which can be passed to the select system call. When select indicates that this file descriptor is ready for reading, then an event is pending and the application should call SCGetEvent to retrieve it.