P/N: 980552-001Zebra Card Solutions 6/15/2005 Page 1 of 40 www.zebracard.com
DISCLAIMER
Zebra Technologies has made every effort to document this product fully and
accurately. The software and documentation is, nevertheless, provided and
licensed “as is.” Developer acknowledges and agrees that it has no rights to any
upgrades, modifications, enhancements or revisions which Zebra Technologies
may make to the software or documentation.
Developer assumes all risk, and Zebra Technologies makes no representation,
warranty or guarantee whatsoever, express or implied, as to functionality, utility,
error free operation, absence of any virus, or any other aspect of the software’s
operation or performance, or the accuracy, completeness or adequacy of the
documentation. Developer agrees that its use of the software and
documentation is at developer’s own risk.
ZEBRA TECHNOLOGIES SPECIFICALLY DISCLAIMS ANY AND ALL
WARRANTIES OF ANY NATURE IN CONNECTION WITH THE SOFTWARE
AND DOCUMENTATION, TO INCLUDE, BUT NOT BE LIMITED TO, ANY
WARRANTY OF MERCHANTABILITY OF FITNESS FOR A PARTICULAR
PURPOSE.
Neither Zebra Technologies nor any of its agents, consultants, distributors or
dealers shall, under any circumstances, be liable for any indirect, incidental or
consequential damages arising from the use of this publication. Zebra
Technologies reserves the right to make improvements and/or changes in the
products and programs as described in this manual at any time without notice.
This document describes the programming interface to control Zebra
Technologies P640 and P640i card printers. This manual along with the code
and the reference distributed with it are known as the Zebra Technologies P640
Programmer’s Manual. This manual is intended as a reference for the developer
wishing to write drivers or applications that control a Zebra Technologies P640 or
P640i printer.
This manual is organized to assist the developer in rapidly becoming familiar with
the P640/P640i printer. The first section gives an overview describing the driver
architecture. The next section describes the programming steps necessary to
carry out specific functions. Following this is a brief discussion of the code.
Developers using this manual should have a working knowledge of printers in
general and a working knowledge of Ethernet networks, and USB and parallel
interfaces.
The user interface (UI) dll handles the display of the property sheets to the user
when the user selects either Printing Preferences… or Properties | Device
Settings. The UI gets the configuration information from the printer and displays
it to the user. It also sends commands to the printer depending on user actions.
The UI is responsible for updating the DevMode structure with driver
configuration information. The DevMode structure is stored by the operating
system in the registry, and is passed to the driver dlls whenever they are called.
2.2 Kernel/User mode dll
The kernel/user mode dll (DRV) handles the GDI (Graphical Device Interface)
calls that are made by application programs to send print data to the printer. The
DRV formats the print data for the printer performing such operations as black
extraction and image rotation. It then writes the data to the spooler.
2.3 Language Monitor
The language monitor dll (LM) is called by the spooler when a print job is sent to
the printer. The LM passes the print job along to the appropriate port monitor.
The LM then monitors the status of the job as it prints and is responsible for
communicating any errors that occur, to the user. The LM displays error dialogs
explaining the corrective action to be taken to correct the error and handles
reprinting jobs as necessary.
The language monitor also receives the GetPrinterData and SetPrinterData calls
made by application programs. It passes these commands to the printer and
passes any data returned from the printer back to the calling application.
2.4 Port Monitors
There are port monitor dlls (PMs) for each communication type that the P640
supports, parallel, USB, and Ethernet. The PMs are called by the language
monitor and are used to pass the data between the LM and the printer using the
appropriate protocol.
3 Sending Commands to the Printer through the Driver
An application program can send commands to the printer through the Language
Monitor, using the GetPrinterData function. The command sent can be either a
simple command or a request for the printer to return data. If data is to be
returned, the caller must provide a buffer to store the returned data. If the
returned data is variable in length, GetPrinterData can be called first with pData
set to NULL and nSize set to 0. The function will fail, but the buffer size needed
will be returned in pcbNeeded. See section 3.4 below for further explanation of
these parameters.
It is good practice to call SetPrinterData with a NULL text string before calling
GetPrinterData to ensure that all data from previous commands is erased.
To pass data to the printer, such as for setting the printer’s configuration (i.e.
SMARTCARD_DATA), the application must first call SetPrinterDataEx with the
data to be sent. This will store the data in the registry for retrieval by the
Language Monitor. A GetPrinterData command is then issued to tell the
Language Monitor to retrieve the data and send it to the printer.
The header file messages.h contains #defines for all of the messages that can be
send to the Language Monitor by the driver or an application program. The
header file printerdefs.h contains the data structure definitions for data being
send to the printer and data being received from the printer. The structures
make it easy to format the data correctly for the printer and to parse messages
coming back from the printer.
if(OpenPrinter(TEXT(“Zebra P640”),&hPrinter,&pd))
{
//Before Get, do dummy set to clear cached data
SetPrinterData(hPrinter,COMMAND,REG_SZ,(LPBYTE)TEXT(""),
_tcslen(TEXT(""))*sizeof(TCHAR));
// if the command’s entry in messages.h says “Data: Yes”, set Data
SetPrinterDataEx(hPrinter,ATL_MESSAGE_KEY,DATANAME,REG_SZ,
(LPBYTE)DATABUFFER, DATABUFFER_LENGTH));
// Data buffer MUST be at least ERROR_TEXT_SIZE TCHARs long
// to receive results
dwRet = GetPrinterData(hPrinter,Command,&dwType,(LPBYTE)Data,
ERROR_TEXT_SIZE*sizeof(TCHAR),&dwRead);
if (!(_tcsncmp(Data,ERROR_SUCCESS_TEXT, ERROR_TEXT_SIZE)))
{
// success
}
hPrinter
handle to a printer from OpenPrinter
pValueName
pointer to a string of TCHAR type. UNICODE should be defined in the project.
Make sure it is NUL terminated. This is the command to execute. In some
cases, an argument can come after the command. If such a command is
entered, the remainder of the string after the command will be converted to
single byte characters and sent to the printer.
pType
Type of data. This is ignored in our implementation so it should be NULL.
pData
Output Data buffer. If the command does not need data back, this may be
NULL. The data is returned exactly as returned from the printer, so no big
endian->little endian conversion is done, so if you need to cast it to something
you need to do that yourself.
nSize
size of pData. If pData is NULL, this should be 0
pcbNeeded
the number of bytes read into pData. Note that, in general if GetPrinterData
returns FALSE, the data here is invalid. It is NOT set to the number of bytes
needed. However, there is an exception to this in the GET commands for
paths and strings. In this case, it will be set to the needed number of bytes.
Return Values
ERROR_SUCCESS if the function succeeds, otherwise an error value.
3.4.1 Excerpt from messages.h header file
Listed below are the commands that can be sent to the printer. These are pulled
from the messages.h header file used by the driver and IDPrint. For further
explanation of any command’s function, see section 2 above. Each command is
defined in the following format:
Command Name (ESC Code sent to printer by Language Monitor)
#define for the command – this will be the pValueName parameter
Input = function expects arguments following the command string input arguments should be
concatenated to the command
Output = function returns data in pData
Data = Data is to be put in the registry ahead of time by the SetPrinterDataEx command
¾NOTE: The data structures listed for input and output are defined in printerdefs.h
Request Sensor Data
#define REQUEST_SENSOR_DATA TEXT("SENSORDATA")
Input: No
Output: Yes – SENSORDATA structure
Data: No
typedef struct tagSENSORDATA
{
union {
WORD wFlipLift;
struct {
// NOTE: this assumes that you will be doing a big->little endian conversion
// on this word, since wFlipLift needs it!!
// these are backwards because this compiler does bitfields backwards
struct {
BYTE iButtonDone:1; // bit 0 - Write to iButton is complete
BYTE CarriageNearHopper:1; // bit 1 - Carriage is near
// card hopper - 0 = Away, 1 = Near
BYTE HopperDoorOpen:1; // bit 2 - Hopper door open - 0 =
// Closed, 1 = Open
BYTE CardLamExit:1; // bit 3 - Card Laminator Exiting
// Sensor - 0 = No card, 1 = Card
BYTE CardLamEnter:1; // bit 4 - Card Laminator Entering
//Sensor - 0 = No card, 1 = Card
BYTE ElevatorDown:1; // bit 5 - Elevator Down - 0 = Up, 1 =
// Down
BYTE CarriageHome:1; // bit 6 - Carriage Home Position - 0
// = Out of home, 1 = At home
BYTE DoorOpen:1; // bit 7 - Door Open Sensor - 0 =
// Closed, 1 = Open
} LoByte;
// these are backwards because this compiler does bitfields backwards
struct {
BYTE JumperSelect1:1; // bit 8 - Jumper selection 1
// (reserved)
BYTE ACLoss:1; // bit 9 - Loss of AC - 0 = power, 1 = no
//power
BYTE HeadUp:1; // bit 10 - head state - 0 = down, 1 = up
BYTE Reserved11:1; // bit 11 - reserved
BYTE Reserved12:1; // bit 12 - reserved
BYTE OvlAdvButton:1; // bit 13 - overlay advance button
BYTE RibAdvButton:1; // bit 14 - ribbon advance button
BYTE PrintButton:1; // bit 15 - print button
} HiByte;
} BooleanSensorsBits;
} Sensors_FlipLift;
WORD wCardPresence;
WORD wPrintStationSyncMark;
WORD wTopLam;
WORD wBottomLam;
WORD wLamPresentThresh;
WORD wLamAbsentThresh;
WORD wReserved3;
} SENSORDATA, far *LPSENSORDATA;