IT Employment

Hardware interfacing with TWAIN

The TWAIN protocol lets you avoid low-level device driver calls when you're programming. In this Daily Drill Down, Larry Loeb shows what you can do with TWAIN.

TWAIN defines a standard software protocol and API (application programming interface) for communication between software applications and image-acquisition devices. TWAIN gives the application developer a choice: By using it, you can avoid low-level device driver calls when you’re programming and concentrate instead on user-interaction programming. While you may decide to use low-level calls for reasons related to performance, most general acquisition hardware interfacing can be accomplished simply with TWAIN. In this Daily Drill Down, I’ll take a look at TWAIN’s capabilities.

The elements of TWAIN
As shown in Figure A, the three key elements in TWAIN are:
  • The application software—An application must be modified to use TWAIN.
  • The Source Manager software—This software manages the interactions between the application and the Source. This code is provided in the TWAIN Developer's Toolkit and is included with each TWAIN application and Source.
  • The Source software—This software controls the image-acquisition device and is written by the device developer to comply with TWAIN specifications. Traditional device drivers are now included with the Source software.

Figure A
TWAIN contains three key elements.


There has been a concerted effort to implement the protocol on most major PC platforms. TWAIN is supported on all versions of the Macintosh OS as well as Microsoft Windows 3.x/ 9x/NT/2000 (it’s not available on Windows CE). TWAIN is available on IBM OS/2, but the binaries for the Source Manager weren’t built or distributed by the TWAIN Working Group. UNIX is not supported. Currently, only the raster image data type is supported, but suggestions presented to the TWAIN Working Group for future extensions include text, facsimile, and vector graphics, among others.

The transfer of data is made possible by three software elements that work together in TWAIN: the application, the Source Manager, and the Source. These elements use TWAIN’s architecture to communicate. As Figure B shows, the TWAIN architecture consists of four layers: Application, Protocol, Acquisition, and Device. Since the Application and Device layers’ APIs are usually manufacturer-specific, I’ll concentrate on the Protocol and Acquisition layers.

Figure B
The TWAIN architecture consists of four layers.


In addition, using TWAIN may well obviate the need for low-level device drivers. The Source takes user-interface information and translates it into device commands. Indeed, the Source may be thought to hide the Device layer from the application in the way a hardware Mac Manager does for its application.

Let's look at some of the simple API hooks TWAIN provides. There are two entry points, called DSM_Entry( ) and DS_Entry( ), as shown in Figure C. DSM means Data Source Manager and DS means Data Source.

Figure C
Here are the entry points of TWAIN.


Source Manager
Approximately 140 operations are defined by the TWAIN protocol. An application sends one or more of them to the Source Manager for transmission. The application has the responsibility to specify which element, Source Manager or Source, is the final destination for each requested operation. The application will talk to the Source Manager through the Source Manager's only entry point, the DSM_Entry( ) function.

The DSM_Entry( ) function contains an identifier structure that provides information about the application that originated the function call and the destination of this request (Source Manager or Source). It also contains a triplet that describes the requested operation. The triplet specifies:
  • Data Group for the Operation (DG_ )
  • Data Argument Type for the Operation (DAT_ )
  • Message for the Operation (MSG_ )
  • A pointer field to allow the transfer of data

The function call returns a value (the Return Code) that indicates the routine's completion and state of that completion (success or failure). If you wrote the above parameters in Mac C code, you’d come up with the following code:
FAR PASCAL TW_UINT16 DSM_Entry
( pTW_IDENTITY pOrigin, // source of message
pTW_IDENTITY pDest, // destination of message
TW_UINT32 DG, // data group ID: DG_xxxx
TW_UINT16 DAT, // data argument type: DAT_xxxx
 //(The data argument type may reference a data // structure or a variable.)
TW_UINT16 MSG, // message ID: MSG_xxxx
TW_MEMREF pData // pointer to data
);\


The Source Manager provides the communication path between the application and the Source, supports the user’s selection of a Source, and loads the Source for access by the application. The application talks to the Source Manager through the DSM_Entry( ) call.

If the destination in the DSM_Entry call is the Source, then the Source Manager translates the parameter list of information, removes the destination parameter, and calls the appropriate Source. Source Manager calls the Source's DS_Entry( ) function. Each Source is required to have this entry point.

The parameter call would be written in C like this:
FAR PASCAL TW_UINT16 DS_Entry
(pTW_IDENTITY pOrigin, // source of message
TW_UINT32 DG, // data group ID: DG_xxxx
TW_UINT16 DAT, // data argument type: DAT_xxxx
TW_UINT16 MSG, // message ID: MSG_xxxx
TW_MEMREF pData // pointer to data
);


In addition, the Source Manager can open and close sources by itself—without application intervention. It resides on the Mac as a PowerPC shared library.

Source
The Source receives operations from the Source Manager. (Applications talk to the Source Manager to get a message to the Source.) The Source processes the request and returns an appropriate Return Code (prefixed with TWRC_), which displays the result of the call to the Source Manager. If the originator of the operation was the application, then the Return Code is passed back to the application as the return value of its DSM_Entry( ) function call. If the operation was unsuccessful, a Condition Code (the codes again prefixed by TWCC_) containing detail information is set by the Source.

Although the Condition Code is set, it isn’t automatically passed back to the application. The application must detect failure, then invoke an operation if it wants the specific Condition Code. The Source can interrupt the application if, for example, a data transfer is ready to occur or a device event has taken place. Like the Source Manager, the Source is a PowerPC shared library on the Mac.

Capabilities
A good reason to implement TWAIN is that it allows applications to interact with a variety of acquisition devices. These devices, which provide image or audio data, may have automatic document feeders, or the ability to transfer multiple images or support a range of resolutions. To find out a device's abilities, TWAIN performs capability negotiation. This process has five steps:
  • Determine whether the selected Source supports a particular capability. Then, inquire about the current value for this capability.
  • Inquire about the capability's default value and the set of available values that are supported by the Source for that capability.
  • Request that the Source set the current value to the application's desired value. The current value appears as the current selection in the Source's user interface.
  • Limit available Source values to a desired subset. If the application wants only black and white data, it can restrict the Source to transmit only that. If a limitation affects the Source's user interface, the Source should modify the interface to reflect those changes. For example, it may gray out options that are unavailable because of the application's restrictions.
  • Verify that the new values have been accepted by the Source.

TWAIN capabilities are divided into three groups:
  • CAP_xxxx: Capabilities whose names begin with CAP are capabilities that could apply to any general Source. Such capabilities include the use of automatic document feeders, identification of the creator of the data, and so forth.
  • ICAP_xxxx: Capabilities whose names begin with ICAP are capabilities that apply to image devices. The I stands for image.
  • ACAP_xxxx: Capabilities whose names begin with ACAP are capabilities that apply to devices that support audio. The A stands for audio.

TWAIN defines four types of containers for capabilities:
  • TW_ONEVALUE: A single value whose current and default values are coincident. For example, a capability that indicates the presence of a document feeder could be of this type.
  • TW_ARRAY: A rectangular array of values that describe a logical item. It’s similar to the TW_ONEVALUE because the current and default values are the same and there are no other values to select from. For example, a list of the names, such as the supported capabilities list returned by the CAP_SUPPORTEDCAPS capability, would use this type of container.
  • TW_RANGE: Many capabilities allow users to select their current value from a range of regularly spaced values. The capability can specify the minimum and maximum acceptable values and the incremental step size between values.
  • TW_ENUMERATION: This is the most general type because it defines a list of values from which the Current Value can be chosen. The values don’t progress uniformly through a range, and there is no consistent step size between the values. For example, if a Source's resolution options didn’t occur in even step sizes, then an enumeration would be used.

In general, most capabilities can have more than one of these containers applied to them, depending on how the particular Source implements the capability.

Changing the event loop
Most Mac programs handle program events in a loop. TWAIN asks for some modification of that loop so it can pass events from the application to the Source for its response and notify the application when a device event occurs.

To make sure the source is—heh, heh—in the loop, the application must send all events that it receives in its event loop to the Source as long as the Source is enabled. Also, the application must periodically send null events to the Source to allow notifications from the Source to the application.

Let's look at some C code that will implement a TWAIN-compliant event loop:
TW_EVENT twEvent;
TW_INT16 rc;
EventRecord theEvent;
while (!Done){
 If Source is Enabled{
 //Send periodic NULL events to the Source
 twEvent.pEvent = NULL;
 twEvent.TWMessage = MSG_NULL;
 rc = (*pDSM_Entry) (pAppID,
 pSourceID,
 DG_CONTROL,
 DAT_EVENT,
 MSG_PROCESSEVENT,
 (TW_MEMREF)&twEvent);
//check for message from Source
switch (twEvent.TWMessage){
 case MSG_XFERREADY:
 SetupImage(NULL);
 break;
 case MSG_CLOSEDSREQ:
 DisableSource(NULL);
 break;
 case MSG_CLOSEDSOK:
 DisableAndCloseSource(NULL);
 GetCustomDsData();
 break;
 case MSG_NULL:
 //no message was returned from the Source
 break;
 }
}
if (GetNextEvent(everyEvent, &theEvent) ){ //or WaitNextEvent()
 If Source is Enabled{
 twEvent.pEvent = &theEvent;
 twEvent.TWMessage = MSG_NULL;
 rc = (*pDSM_Entry) (pAppID,
 pSourceID,
 DG_CONTROL,
 DAT_EVENT,
 MSG_PROCESSEVENT,
 (TW_MEMREF)&twEvent);
 //check for message from Source
 switch (twEvent.TWMessage){
 case MSG_XFERREADY:
 SetupImage(NULL);
 break;
 case MSG_CLOSEDSREQ:
 DisableSource(NULL);
 break;
 case MSG_CLOSEDSOK:
 DisableAndCloseSource(NULL);
 GetCustomDsData();
 break;
 case MSG_NULL:
 //no message was returned from the Source
 break;
 }
 if (rc == TWRC_NOTDSEVENT)
 Message=DealWithEvent(&theEvent);
 }
 } else
 Message=DealWithEvent(&theEvent);
}



As you can see, the loop modification is fairly simple. CASE statements handle each situation with a call or pass the event on.

Larry Loeb has 20 years of computer journalism experience. He was consulting editor at the late, lamented BYTE magazine, he launched WebWeek, he ran the online Macintosh section of BIX (the BYTE Information eXchange), and he wrote numerous articles for many major computer magazines. Recently, he also wrote a book on Secure Electronic Transactions, the protocol endorsed by MasterCard and Visa that allows merchants, cardholders, and banks to work together over the Internet. For banter, tips, and general screaming, send Larry an e-mail .

The authors and editors have taken care in preparation of the content contained herein, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.
0 comments

Editor's Picks