Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
TestPrinterClass.c
// File TestPrinterClass.c |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <types.h> |
#include <gestalt.h> |
#include <errors.h> |
#ifndef __DIALOGS__ |
#include <Dialogs.h> |
#endif |
#ifndef __EVENTS__ |
#include <Events.h> |
#endif |
#ifndef __FILES__ |
#include <Files.h> |
#endif |
#ifndef __DEVICES__ |
#include <Devices.h> |
#endif |
#include <textedit.h> |
#ifndef __NUMBERFORMATTING__ |
#include <numberformatting.h> |
#endif |
#include "TestPrinterClass.h" |
#include "SafeNameRegistry.h" |
enum { |
kUSBNoErr = 0, |
kUSBNoTran = 0, |
kUSBNoDelay = 0, |
kUSBPending = 1, /* */ |
/* USB assigned error numbers in range -6900 .. -6999 */ |
kUSBBaseError = -7000, /* */ |
/* USB Services Errors */ |
kUSBInternalErr = -6999, /* Internal error */ |
kUSBUnknownDeviceErr = -6998, /* device ref not recognised */ |
kUSBUnknownPipeErr = -6997, /* Pipe ref not recognised */ |
kUSBTooManyPipesErr = -6996, /* Too many pipes */ |
kUSBIncorrectTypeErr = -6995, /* Incorrect type */ |
kUSBRqErr = -6994, /* Request error */ |
kUSBUnknownRequestErr = -6993, /* Unknown request */ |
kUSBTooManyTransactionsErr = -6992, /* Too many transactions */ |
kUSBAlreadyOpenErr = -6991, /* Already open */ |
kUSBNoDeviceErr = -6990, /* No device */ |
kUSBDeviceErr = -6989, /* Device error */ |
kUSBOutOfMemoryErr = -6988, /* Out of memory */ |
kUSBNotFound = -6987, /* Not found */ |
kUSBPBVersionError = -6986, /* Wrong pbVersion */ |
kUSBPBLengthError = -6985, /* pbLength too small */ |
kUSBCompletionError = -6984, /* no completion routine specified */ |
kUSBFlagsError = -6983, /* Flags not zeroed */ |
kUSBAbortedError = -6982, /* Pipe aborted */ |
kUSBNoBandwidthError = -6981, /* Not enough bandwidth available */ |
kUSBPipeIdleError = -6980, /* Pipe is Idle, it will not accept transactions */ |
kUSBPipeStalledError = -6979, /* Pipe has stalled, error needs to be cleared */ |
kUSBUnknownInterfaceErr = -6978, /* Interface ref not recognised */ |
/* */ |
/* USB Manager Errors */ |
kUSBBadDispatchTable = -6950, /* Improper driver dispatch table */ |
/* */ |
/* Hardware Errors */ |
/* Note pipe stalls are communication */ |
/* errors. The affected pipe can not */ |
/* be used until USBClearPipeStallByReference */ |
/* is used */ |
/* kUSBEndpointStallErr is returned in */ |
/* response to a stall handshake */ |
/* from a device. The device has to be */ |
/* cleared before a USBClearPipeStallByReference */ |
/* can be used */ |
kUSBLinkErr = -6916, |
kUSBCRCErr = -6915, /* Pipe stall, bad CRC */ |
kUSBBitstufErr = -6914, /* Pipe stall, bitstuffing */ |
kUSBDataToggleErr = -6913, /* Pipe stall, Bad data toggle */ |
kUSBEndpointStallErr = -6912, /* Device didn't understand */ |
kUSBNotRespondingErr = -6911, /* Pipe stall, No device, device hung */ |
kUSBPIDCheckErr = -6910, /* Pipe stall, PID CRC error */ |
kUSBWrongPIDErr = -6909, /* Pipe stall, Bad or wrong PID */ |
kUSBOverRunErr = -6908, /* Packet too large or more data than buffer */ |
kUSBUnderRunErr = -6907, /* Less data than buffer */ |
kUSBRes1Err = -6906, |
kUSBRes2Err = -6905, |
kUSBBufOvrRunErr = -6904, /* Host hardware failure on data in, PCI busy? */ |
kUSBBufUnderRunErr = -6903, /* Host hardware failure on data out, PCI busy? */ |
kUSBNotSent1Err = -6902, /* Transaction not sent */ |
kUSBNotSent2Err = -6901 /* Transaction not sent */ |
}; |
#define SECONDS( n ) (n*60) |
#define PROGRAM "DropPrint¥USB" |
#define kStrPrinterClass PROGRAM ": " |
enum { |
kStatusDialog = 513 |
}; |
enum { |
kStatusBarItem = 1 |
}; |
char *outbuffer = NULL; |
IOParam fsendblk; |
unsigned long fUSBReference; |
char *filename; |
DialogPtr gStatusDlg; |
void dump( char *p, long count ); |
OSErr sendfile( char *sourcefile, long buffersize ); |
OSStatus OpenClassDriver( char *which_printer ); |
void showstatus( long current, long endfile ); |
void |
dump( char *p, long count ) |
{ |
char *q, *e, *f, |
*d, line[64+32+1+1]; //2bytes per hex, 1 byte per char, 1 tab, 1 nul |
short nibble; |
while ( count > 0 ) |
{ |
q = p; // start of line |
e = p + 32; // proposed end of line |
f = p + (count > 32? 32: count); // actual end of line |
d = line; |
// |
// standard hex dump |
// |
for ( ; count > 0 && p < e; ++p, --count ) |
{ |
nibble = (*p >> 4) & 0x0F; |
*d++ = nibble + (nibble > 9? 'A' - 10:'0'); |
nibble = *p & 0x0F; |
*d++ = nibble + (nibble > 9? 'A' - 10:'0'); |
} |
for ( ; p < e; ++p ) |
{ |
*d++ = ' '; |
*d++ = ' '; |
} |
*d++ = '\t'; |
// |
// ascii sidebar |
// |
for ( p = q; p < f; ++p ) |
*d++ = *p < ' ' || *p >= 0x7F? '.': *p; |
*d = '\0'; |
fprintf( stderr, "%s\n", line ); |
} |
} |
OSStatus |
OpenClassDriver( char *which_printer ) |
{ |
Str255 driverName; // unit table driver name |
OSStatus err = -192; // resNotFound |
RegEntryID self; |
unsigned long length; |
fsendblk.ioRefNum = -1; // preload our IOParms in engvars |
fsendblk.ioResult = 0; |
fsendblk.ioCompletion = 0L; |
err = SafeRegistryEntryIDInit( &self ); |
if ( err == noErr ) |
{ |
err = SafeRegistryCStrEntryLookup( nil, which_printer, &self ); |
length = sizeof(driverName); |
if ( err == noErr ) |
err = SafeRegistryPropertyGet( &self, "drvrOut", &driverName, &length ); |
if ( err == noErr ) |
err = OpenDriver( driverName, &fsendblk.ioRefNum ); |
length = sizeof(fUSBReference); |
if ( err == noErr ) |
err = SafeRegistryPropertyGet( &self, "privateData", &fUSBReference, &length ); |
SafeRegistryEntryIDDispose(&self); |
} |
return err; |
} |
void |
showstatus( long current, long endfile ) |
{ |
GrafPtr oldport; |
Rect r; |
Handle h; |
short type; |
long width; |
char info[526]; |
GetPort( &oldport ); |
SetPort( gStatusDlg ); |
GetDialogItem( gStatusDlg, kStatusBarItem, &type, &h, &r ); |
// we have, width/ (r.right - r.left) == current/endfile |
width = current *(r.right - r.left); |
width /= endfile; |
FrameRect( &r ); |
InsetRect( &r, 1, 1 ); |
sprintf( info, "%ld of %ld", current, endfile ); |
TETextBox( info, strlen(info), &r, teJustCenter ); |
r.right = width + r.left; |
InvertRect( &r ); |
SetPort( oldport ); |
} |
OSErr |
sendfile( char *sourcefile, long buffersize ) |
{ |
FILE *fin = fopen( sourcefile, "rb" ); |
long count; |
EventRecord e; |
OSStatus err; |
long eoffin; // length of input file |
gStatusDlg = GetNewDialog( kStatusDialog, nil, (WindowPtr)-1); |
if ( !fin ) |
err = fnfErr; // cant open file |
else |
{ |
fseek( fin, 0, 2 /*fsFromEnd*/ ); |
eoffin = ftell( fin ); |
fseek( fin, 0, 0 /*fsFromStart*/ ); |
do { |
count = fread( outbuffer, sizeof(char), buffersize, fin ); |
if ( count <= 0 ) |
break; |
// dump( outbuffer, count ); |
fsendblk.ioBuffer = outbuffer; |
fsendblk.ioReqCount = count; |
err = PBWriteAsync( (ParamBlockRec*) &fsendblk ); |
if ( err != noErr ) |
break; |
showstatus( ftell( fin ), eoffin ); |
// wait for i/o to complete |
while ( fsendblk.ioResult == 1 ) |
{ |
WaitNextEvent( keyDownMask, &e, 0, NULL ); |
if (e.what == keyDown && e.modifiers & cmdKey) { |
if ( (e.message & charCodeMask) == '.' ) |
break; |
} |
} |
if ( fsendblk.ioResult != noErr ) |
break; |
// if user canceled, exit the download |
WaitNextEvent( keyDownMask, &e, 0, NULL ); |
if (e.what == keyDown && e.modifiers & cmdKey) { |
if ( (e.message & charCodeMask) == '.' ) |
break; |
} |
} while ( count > 0 ); |
DisposeDialog(gStatusDlg); |
if ( err == noErr && fsendblk.ioResult != noErr ) |
err = fsendblk.ioResult; |
fclose( fin ); |
} |
return err; |
} |
OSErr |
sendusb( char *printer_name, char *sourcefile, long blocksize, int repeat_count ) |
{ |
OSStatus err = noErr; |
outbuffer = (char *) malloc( blocksize ); |
memset( &fsendblk, 0, sizeof(fsendblk) ); |
if ( !outbuffer ) |
err = iMemFullErr; // memfull error |
if ( err == noErr ) |
err = OpenClassDriver( printer_name ); |
if ( err == noErr ) |
{ |
for ( ; err == noErr && repeat_count > 0; --repeat_count ) |
err = sendfile( sourcefile, blocksize ); |
if ( err != noErr ) |
KillIO( fsendblk.ioRefNum ); |
if ( fsendblk.ioRefNum != -1 ) |
CloseDriver(fsendblk.ioRefNum); |
} |
if ( outbuffer ) |
free( outbuffer ); |
if ( err != noErr ) |
{ |
unsigned char *p; |
int slen; |
switch ( err ) |
{ |
case iMemFullErr: p = "\p" PROGRAM "Not enough memory. (Increase App heap, or use smaller block)"; break; |
case kUSBInternalErr: p = "\p" kStrPrinterClass "Internal error"; break; |
case kUSBUnknownDeviceErr: p = "\p" kStrPrinterClass "Unknown device"; break; |
case kUSBUnknownPipeErr: p = "\p" kStrPrinterClass "Unknown pipe"; break; |
case kUSBTooManyPipesErr: p = "\p" kStrPrinterClass "Too many pipes"; break; |
case kUSBIncorrectTypeErr: p = "\p" kStrPrinterClass "Incorrect type"; break; |
case kUSBRqErr: p = "\p" kStrPrinterClass "Request error"; break; |
case kUSBUnknownRequestErr: p = "\p" kStrPrinterClass "Unknown request"; break; |
case kUSBTooManyTransactionsErr: p = "\p" kStrPrinterClass "Too many transactions"; break; |
case kUSBAlreadyOpenErr: p = "\p" kStrPrinterClass "Already open"; break; |
case kUSBNoDeviceErr: p = "\p" kStrPrinterClass "No device"; break; |
case kUSBDeviceErr: p = "\p" kStrPrinterClass "Device error"; break; |
case kUSBOutOfMemoryErr: p = "\p" kStrPrinterClass "Out of memory"; break; |
case kUSBNotFound: p = "\p" kStrPrinterClass "Not found"; break; |
case kUSBLinkErr: p = "\p" kStrPrinterClass "Link Err"; break; |
case kUSBCRCErr: p = "\p" kStrPrinterClass "Comms/Device err, bad CRC"; break; |
case kUSBBitstufErr: p = "\p" kStrPrinterClass "Comms/Device err, bitstuffing"; break; |
case kUSBDataToggleErr: p = "\p" kStrPrinterClass "Comms/Device err, Bad data toggle"; break; |
case kUSBEndpointStallErr: p = "\p" kStrPrinterClass "Device didn't understand"; break; |
case kUSBNotRespondingErr: p = "\p" kStrPrinterClass "No device, device hung"; break; |
case kUSBPIDCheckErr: p = "\p" kStrPrinterClass "Comms/Device err, PID CRC error"; break; |
case kUSBWrongPIDErr: p = "\p" kStrPrinterClass "Comms/Device err, Bad or wrong PID"; break; |
case kUSBOverRunErr: p = "\p" kStrPrinterClass "Packet too large or more data than buffer"; break; |
case kUSBUnderRunErr: p = "\p" kStrPrinterClass "Less data than buffer"; break; |
case kUSBRes1Err: p = "\p" kStrPrinterClass "kUSBRes1Err"; break; |
case kUSBRes2Err: p = "\p" kStrPrinterClass "kUSBRes1Err"; break; |
case kUSBBufOvrRunErr: p = "\p" kStrPrinterClass "Buffer over run error"; break; |
case kUSBBufUnderRunErr: p = "\p" kStrPrinterClass "Buffer under run error"; break; |
case kUSBNotSent1Err: p = "\p" kStrPrinterClass "Transaction not sent1"; break; |
case kUSBNotSent2Err: p = "\p" kStrPrinterClass "Transaction not sent2"; break; |
default: |
p = "\p" kStrPrinterClass "Unknown error nnnnnnnn"; |
NumToString( err, p + *p - 8 ); |
slen = *(p + *p - 8); |
*(p + *p - 8) = ' '; |
*p += slen - 8; |
break; |
} |
ParamText( p, nil, nil, nil ); |
StopAlert( 768, nil ); |
err = noErr; |
} |
return err; |
} |
/* eof */ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-26