?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /******************************************************************************
2  
3 USB Host Printer Client Driver
4  
5 Summary:
6 This is the Printer client driver file for a USB Embedded Host device.
7  
8 Description:
9 This is the Printer client driver file for a USB Embedded Host device.
10 It allows an embedded application to utilize a USB printer to provide
11 printed output.
12  
13 USB printers utilize the USB Printer Class to communicate with a USB
14 Host. This class defines the USB transfer type, the endpoint structure,
15 a device requests that can be performed. The actual commands sent to
16 the printer, however, are dictated by the printer language used by the
17 particular printer.
18  
19 Many different printer languages are utilized by the wide variety of
20 printers on the market. Typically, low end printers receive printer-specific
21 binary data, utilizing the processing power of the USB Host to perform
22 all of the complex calculations required to translate text and graphics to
23 a simple binary representation. This works well when a PC is the USB Host,
24 but it is not conducive to an embedded application with limited resources.
25  
26 Many printers on the market use a command based printer language, relying
27 on the printer itself to interpret commands to produce the desired output.
28 Some languages are standardized across printers from a particular
29 manufacturer, and some are used across multiple manufacturer. This method
30 lends itself better to embedded applications by allowing the printer to
31 take on some of the computational overhead. Microchip provides support for
32 some printer languages, including PostScript and PCL 5. Additional printer
33 language can be implemented. Refer to the USB Embedded Host Printer Class
34 application notes for more details on implementing printer language support.
35  
36  
37 Remarks:
38 This driver should be used in a project with usb_host.c to provided the USB
39 Embedded Host and hardware interfaces, plus one or more language support
40 files.
41  
42 To interface with USB Embedded Host layer, the routine USBHostPrinterInitialize()
43 should be specified as the Initialize() function, and
44 USBHostPrinterEventHandler() should be specified as the EventHandler()
45 function in the usbClientDrvTable[] array declared in usb_config.c.
46  
47 This driver requires transfer events from usb_host.c, so
48 USB_ENABLE_TRANSFER_EVENT must be defined.
49  
50 Since the printer class is performed with bulk transfers,
51 USB_SUPPORT_BULK_TRANSFERS must be defined.
52  
53 *******************************************************************************/
54 //DOM-IGNORE-BEGIN
55 /******************************************************************************
56  
57 FileName: usb_host_printer.c
58 Dependencies: None
59 Processor: PIC24F/PIC32MX
60 Compiler: C30/C32
61 Company: Microchip Technology, Inc.
62  
63 Software License Agreement
64  
65 The software supplied herewith by Microchip Technology Incorporated
66 (the “Company”) for its PICmicro® Microcontroller is intended and
67 supplied to you, the Company’s customer, for use solely and
68 exclusively on Microchip PICmicro Microcontroller products. The
69 software is owned by the Company and/or its supplier, and is
70 protected under applicable copyright laws. All rights are reserved.
71 Any use in violation of the foregoing restrictions may subject the
72 user to criminal sanctions under applicable laws, as well as to
73 civil liability for the breach of the terms and conditions of this
74 license.
75  
76 THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
77 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
78 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
79 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
80 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
81 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
82  
83 Change History:
84 Rev Description
85 ---------- -----------
86 2.6 - 2.6a No chance except stack revision number
87  
88 2.7 Minor updates to USBHostPrinterGetStatus() header
89 to better describe the function requirements and
90 operation.
91  
92 Changed how transfer queues are handled to do a peek
93 now before removing the item from the queue.
94  
95 2.7a Provided macro wrapped versions of malloc() and free()
96 so that a user can override these functions easily.
97 ********************************************************************/
98  
99 //DOM-IGNORE-END
100  
101 #include <stdlib.h>
102 #include <string.h>
103 #include <ctype.h>
104 #include "GenericTypeDefs.h"
105 #include "usb_config.h"
106 #include "struct_queue.h"
107 #include "USB\usb.h"
108 #include "USB\usb_host_printer.h"
109  
110 #ifdef USB_PRINTER_LANGUAGE_PCL_5
111 #include "USB\usb_host_printer_pcl_5.h"
112 #endif
113  
114 #ifdef USB_PRINTER_LANGUAGE_POSTSCRIPT
115 #include "USB\usb_host_printer_postscript.h"
116 #endif
117  
118 #ifndef USB_MALLOC
119 #define USB_MALLOC(size) malloc(size)
120 #endif
121  
122 #ifndef USB_FREE
123 #define USB_FREE(ptr) free(ptr)
124 #endif
125  
126 #define USB_FREE_AND_CLEAR(ptr) {USB_FREE(ptr); ptr = NULL;}
127  
128 //#define DEBUG_MODE
129 //#define DEBUG_PRINT_COMMANDS
130 #if defined( DEBUG_MODE ) || defined( DEBUG_PRINT_COMMANDS )
131 #include "uart2.h"
132 #endif
133  
134  
135 // *****************************************************************************
136 // *****************************************************************************
137 // Section: Configuration
138 // *****************************************************************************
139 // *****************************************************************************
140  
141 #if !defined(USB_ENABLE_TRANSFER_EVENT)
142 #error The USB Host Printer Client Driver requires transfer events.
143 #endif
144  
145  
146 // *****************************************************************************
147 // *****************************************************************************
148 // Section: Constants
149 // *****************************************************************************
150 // *****************************************************************************
151  
152 // *****************************************************************************
153 // Section: Interface and Protocol Constants
154 // *****************************************************************************
155  
156 #define DEVICE_CLASS_PRINTER 0x07 // Class code for Printers
157  
158 #define DEVICE_SUBCLASS_PRINTERS 0x01 // SubClass code for Printers
159  
160 #define DEVICE_INTERFACE_UNIDIRECTIONAL 0x01 // Protocol code for unidirectional interface
161 #define DEVICE_INTERFACE_BIDIRECTIONAL 0x02 // Protocol code for bidirectional interface
162 #define DEVICE_INTERFACE_IEEE1284_4 0x03 // Protocol code for IEEE 1284.4 interface
163  
164  
165 // *****************************************************************************
166 // *****************************************************************************
167 // Section: Data Structures
168 // *****************************************************************************
169 // *****************************************************************************
170  
171 // *****************************************************************************
172 /* Printer Transfer Queue Information
173  
174 This structure contains the information needed for one entry in the transfer
175 queue.
176 */
177 typedef struct _USB_PRINTER_QUEUE_ITEM
178 {
179 DWORD size;
180 BYTE *data;
181 BYTE flags;
182 } USB_PRINTER_QUEUE_ITEM;
183  
184  
185 // *****************************************************************************
186 /* Printer Transfer Queue
187  
188 This is the structure for the printer transfer queue.
189 */
190 typedef struct _USB_PRINTER_QUEUE
191 {
192 int head;
193 int tail;
194 int count;
195 USB_PRINTER_QUEUE_ITEM buffer[USB_PRINTER_TRANSFER_QUEUE_SIZE];
196 } USB_PRINTER_QUEUE;
197  
198  
199 // *****************************************************************************
200 /* Printer Device Information
201  
202 This structure contains information about an attached device, including
203 status flags and device identification.
204 */
205 typedef struct _USB_PRINTER_DEVICE
206 {
207 USB_PRINTER_DEVICE_ID ID; // Identification information about the device
208 BYTE clientDriverID;
209 DWORD rxLength; // Number of bytes received in the last IN transfer
210 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
211 char* deviceIDString;
212 WORD deviceIDStringLength;
213 WORD deviceIDStringIndex;
214 #endif
215 USB_PRINTER_LANGUAGE_HANDLER languageHandler;
216 BYTE endpointIN; // Bulk IN endpoint
217 BYTE endpointOUT; // Bulk OUT endpoint
218  
219 USB_PRINTER_QUEUE transferQueueIN;
220 USB_PRINTER_QUEUE transferQueueOUT;
221  
222 union
223 {
224 BYTE value; // BYTE representation of device status flags
225 struct
226 {
227 BYTE inUse : 1; // This array member is in use
228 BYTE initialized : 1; // Driver has been initialized
229 BYTE txBusy : 1; // Driver busy transmitting data
230 BYTE rxBusy : 1; // Driver busy receiving data
231 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
232 BYTE deviceIDStringLengthValid : 1; // Device ID string length is valid
233 #endif
234 };
235 } flags; // Printer client driver status flags
236  
237 } USB_PRINTER_DEVICE;
238  
239  
240 // *****************************************************************************
241 // *****************************************************************************
242 // Section: Global Variables
243 // *****************************************************************************
244 // *****************************************************************************
245  
246 BYTE currentPrinterRecord;
247 extern USB_PRINTER_INTERFACE usbPrinterClientLanguages[];
248 USB_PRINTER_DEVICE usbPrinters[USB_MAX_PRINTER_DEVICES];
249 extern USB_PRINTER_SPECIFIC_INTERFACE usbPrinterSpecificLanguage[];
250  
251  
252 // *****************************************************************************
253 // *****************************************************************************
254 // Section: Local Prototypes
255 // *****************************************************************************
256 // *****************************************************************************
257  
258 BOOL _USBHostPrinter_FindDevice( BYTE address );
259 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
260 BOOL _USBHostPrinter_GetDeviceIDString( void );
261 #endif
262 BYTE _USBHostPrinter_ReadFromQueue( BYTE deviceAddress );
263 BYTE _USBHostPrinter_WriteFromQueue( BYTE deviceAddress );
264  
265 // *****************************************************************************
266 // *****************************************************************************
267 // Section: Host Stack Interface Functions
268 // *****************************************************************************
269 // *****************************************************************************
270  
271 /****************************************************************************
272 Function:
273 BOOL USBHostPrinterInitialize ( BYTE address, DWORD flags, BYTE clientDriverID )
274  
275 Summary:
276 This function is called by the USB Embedded Host layer when a printer
277 attaches.
278  
279 Description:
280 This routine is a call out from the USB Embedded Host layer to the USB
281 printer client driver. It is called when a "printer" device has been
282 connected to the host. Its purpose is to initialize and activate the USB
283 Printer client driver.
284  
285 Preconditions:
286 The device has been configured.
287  
288 Parameters:
289 BYTE address - Device's address on the bus
290 DWORD flags - Initialization flags
291 BYTE clientDriverID - Client driver identification for device requests
292  
293 Return Values:
294 TRUE - Initialization was successful
295 FALSE - Initialization failed
296  
297 Remarks:
298 Multiple client drivers may be used in a single application. The USB
299 Embedded Host layer will call the initialize routine required for the
300 attached device.
301 ***************************************************************************/
302  
303 BOOL USBHostPrinterInitialize ( BYTE address, DWORD flags, BYTE clientDriverID )
304 {
305 BYTE endpointIN;
306 BYTE endpointOUT;
307 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
308 BYTE errorCode;
309 #endif
310 WORD i;
311 WORD j;
312 BYTE *pDesc;
313 BYTE *pDescriptor;
314  
315 #ifdef DEBUG_MODE
316 UART2PrintString( "PRN: Printer Client Init called\r\n" );
317 #endif
318  
319 for (currentPrinterRecord=0; currentPrinterRecord<USB_MAX_PRINTER_DEVICES; currentPrinterRecord++)
320 {
321 if (!usbPrinters[currentPrinterRecord].flags.inUse) break;
322 }
323 if (currentPrinterRecord == USB_MAX_PRINTER_DEVICES)
324 {
325 #ifdef DEBUG_MODE
326 UART2PrintString( "PRN: No more space\r\n" );
327 #endif
328 return FALSE; // We have no more room for a new device.
329 }
330  
331 pDesc = USBHostGetDeviceDescriptor(address);
332  
333 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
334 usbPrinters[currentPrinterRecord].deviceIDString = (char *)USB_MALLOC( ((USB_DEVICE_DESCRIPTOR*)pDesc)->bMaxPacketSize0 );
335 if (usbPrinters[currentPrinterRecord].deviceIDString == NULL)
336 {
337 #ifdef DEBUG_MODE
338 UART2PrintString( "PRN: Out of memory for device ID string length\r\n" );
339 #endif
340 return FALSE; // Out of memory
341 }
342 #endif
343  
344 // Initialize state
345 usbPrinters[currentPrinterRecord].rxLength = 0;
346 usbPrinters[currentPrinterRecord].flags.value = 0x01; // Set the inUse flag.
347 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
348 usbPrinters[currentPrinterRecord].deviceIDStringIndex = 0;
349 #endif
350  
351 // Save device the address, VID, & PID, and client driver ID.
352 usbPrinters[currentPrinterRecord].ID.deviceAddress = address;
353 pDesc += 8;
354 usbPrinters[currentPrinterRecord].ID.vid = (WORD)*pDesc; pDesc++;
355 usbPrinters[currentPrinterRecord].ID.vid |= ((WORD)*pDesc) << 8; pDesc++;
356 usbPrinters[currentPrinterRecord].ID.pid = (WORD)*pDesc; pDesc++;
357 usbPrinters[currentPrinterRecord].ID.pid |= ((WORD)*pDesc) << 8; pDesc++;
358 usbPrinters[currentPrinterRecord].clientDriverID = clientDriverID;
359  
360 #ifdef DEBUG_MODE
361 UART2PrintString( "PRN: USB Printer Client Initalized: flags=0x" );
362 UART2PutHex( flags );
363 UART2PrintString( " address=" );
364 UART2PutDec( address );
365 UART2PrintString( " VID=0x" );
366 UART2PutHex( usbPrinters[currentPrinterRecord].ID.vid >> 8 );
367 UART2PutHex( usbPrinters[currentPrinterRecord].ID.vid & 0xFF );
368 UART2PrintString( " PID=0x" );
369 UART2PutHex( usbPrinters[currentPrinterRecord].ID.pid >> 8 );
370 UART2PutHex( usbPrinters[currentPrinterRecord].ID.pid & 0xFF );
371 UART2PrintString( "\r\n" );
372 #endif
373  
374 // Extract the bulk IN and OUT endpoint that the printer uses.
375  
376 pDescriptor = (BYTE *)USBHostGetCurrentConfigurationDescriptor( address );
377  
378 i = 0;
379  
380 #ifdef DEBUG_MODE
381 UART2PrintString( "PRN: Checking descriptor " );
382 UART2PutDec( pDescriptor[i+5] );
383 UART2PrintString( " ...\r\n" );
384 #endif
385  
386 // Find the next interface descriptor.
387 while (i < ((USB_CONFIGURATION_DESCRIPTOR *)pDescriptor)->wTotalLength)
388 {
389 #ifdef DEBUG_MODE
390 UART2PrintString( "PRN: Checking interface...\r\n" );
391 #endif
392 // See if we are pointing to an interface descriptor.
393 if (pDescriptor[i+1] == USB_DESCRIPTOR_INTERFACE)
394 {
395 if (USBHostDeviceSpecificClientDriver( address ) ||
396 ((pDescriptor[i+5] == DEVICE_CLASS_PRINTER) &&
397 (pDescriptor[i+6] == DEVICE_SUBCLASS_PRINTERS) &&
398 ((pDescriptor[i+7] == DEVICE_INTERFACE_UNIDIRECTIONAL) ||
399 (pDescriptor[i+7] == DEVICE_INTERFACE_BIDIRECTIONAL))))
400 {
401 // Either this client driver was specified in the TPL for this
402 // exact device, or the interface has the correct class,
403 // subclass, and protocol values for the printer class.
404 #ifdef DEBUG_MODE
405 if (USBHostDeviceSpecificClientDriver( address ))
406 {
407 UART2PrintString( "PRN: Explicit client driver support in TPL.\r\n" );
408 }
409 #endif
410  
411 // Look for bulk IN and OUT endpoints.
412 endpointIN = 0;
413 endpointOUT = 0;
414  
415 // Scan for endpoint descriptors.
416 i += pDescriptor[i];
417 while (pDescriptor[i+1] == USB_DESCRIPTOR_ENDPOINT)
418 {
419 if (pDescriptor[i+3] == 0x02) // Bulk
420 {
421 if (((pDescriptor[i+2] & 0x80) == 0x80) && (endpointIN == 0))
422 {
423 endpointIN = pDescriptor[i+2];
424 }
425 if (((pDescriptor[i+2] & 0x80) == 0x00) && (endpointOUT == 0))
426 {
427 endpointOUT = pDescriptor[i+2];
428 }
429 }
430 i += pDescriptor[i];
431 }
432  
433 if ((endpointIN != 0) && (endpointOUT != 0))
434 {
435 // Initialize the device endpoint information.
436 usbPrinters[currentPrinterRecord].endpointIN = endpointIN;
437 usbPrinters[currentPrinterRecord].endpointOUT = endpointOUT;
438 #ifdef DEBUG_MODE
439 UART2PrintString( "PRN: Bulk endpoint IN: " );
440 UART2PutHex( endpointIN );
441 UART2PrintString( " Bulk endpoint OUT: " );
442 UART2PutHex( endpointOUT );
443 UART2PrintString( "\r\n" );
444 #endif
445 USBHostSetNAKTimeout( address, endpointIN, 1, USB_NUM_BULK_NAKS );
446 USBHostSetNAKTimeout( address, endpointOUT, 1, USB_NUM_BULK_NAKS );
447  
448 // See if the printer language has been specified explicitly.
449 j = 0;
450 usbPrinters[currentPrinterRecord].languageHandler = NULL;
451 while ((usbPrinterSpecificLanguage[j].vid != 0x0000) &&
452 (usbPrinters[currentPrinterRecord].languageHandler == NULL))
453 {
454 if ((usbPrinterSpecificLanguage[j].vid == usbPrinters[currentPrinterRecord].ID.vid) &&
455 (usbPrinterSpecificLanguage[j].pid == usbPrinters[currentPrinterRecord].ID.pid))
456 {
457 usbPrinters[currentPrinterRecord].languageHandler = usbPrinterClientLanguages[usbPrinterSpecificLanguage[j].languageIndex].languageCommandHandler;
458 usbPrinters[currentPrinterRecord].ID.support = usbPrinterSpecificLanguage[j].support;
459 #ifdef DEBUG_MODE
460 UART2PrintString( "PRN: Explicit language support. Flags: " );
461 UART2PutHex( (BYTE)usbPrinters[currentPrinterRecord].ID.support.val );
462 UART2PrintString( "\r\n" );
463 #endif
464 }
465 j ++;
466 }
467  
468 if (usbPrinters[currentPrinterRecord].languageHandler != NULL)
469 {
470 // We have a printer language that we can use with this printer.
471 // Complete the client driver attachment.
472 usbPrinters[currentPrinterRecord].flags.initialized = 1;
473 USBHostPrinterCommand( usbPrinters[currentPrinterRecord].ID.deviceAddress, USB_PRINTER_ATTACHED,
474 USB_DATA_POINTER_RAM(&(usbPrinters[currentPrinterRecord].ID.support)), sizeof(USB_PRINTER_FUNCTION_SUPPORT), 0 );
475  
476 // Tell the application layer that we have a device.
477 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_ATTACH, &(usbPrinters[currentPrinterRecord].ID), sizeof(USB_PRINTER_DEVICE_ID) );
478 }
479 else
480 {
481 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
482 // No printer language has been specified for this printer.
483 // Get the printer device ID string, so we can try to determine
484 // what printer languages it supports.
485 errorCode = USBHostIssueDeviceRequest( address, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE,
486 PRINTER_DEVICE_REQUEST_GET_DEVICE_ID, 0, 0, ((USB_DEVICE_DESCRIPTOR*)pDeviceDescriptor)->bMaxPacketSize0,
487 (BYTE *)usbPrinters[currentPrinterRecord].deviceIDString, USB_DEVICE_REQUEST_GET,
488 usbPrinters[currentPrinterRecord].clientDriverID );
489 if (errorCode)
490 {
491 #ifdef DEBUG_MODE
492 UART2PrintString( "PRN: Cannot get device ID string length - " );
493 UART2PutHex( errorCode );
494 UART2PrintString( "\r\n" );
495 #endif
496 // If we cannot read the ID string, then we cannot determine the required printer language.
497 usbPrinters[currentPrinterRecord].flags.value = 0;
498 return FALSE;
499 }
500 #ifdef DEBUG_MODE
501 UART2PrintString( "PRN: Getting device ID string length...\r\n" );
502 #endif
503 #else
504 // No printer language has been specified for this printer.
505 // We cannot enumerate it.
506 #ifdef DEBUG_MODE
507 UART2PrintString( "PRN: No printer language specified.\r\n" );
508 #endif
509 usbPrinters[currentPrinterRecord].flags.value = 0;
510 return FALSE;
511 #endif
512 }
513  
514 return TRUE;
515 }
516 }
517 }
518  
519 // Jump to the next descriptor in this configuration.
520 i += pDescriptor[i];
521 }
522  
523 // This client driver could not initialize the device
524 #ifdef DEBUG_MODE
525 UART2PrintString( "PRN: Device is not a printer.\r\n" );
526 #endif
527 usbPrinters[currentPrinterRecord].flags.value = 0;
528 return FALSE;
529  
530 } // USBHostPrinterInitialize
531  
532  
533 /****************************************************************************
534 Function:
535 BOOL USBHostPrinterEventHandler ( BYTE address, USB_EVENT event,
536 void *data, DWORD size )
537  
538 Summary:
539 This routine is called by the Host layer to notify the general client of
540 events that occur.
541  
542 Description:
543 This routine is called by the Host layer to notify the general client of
544 events that occur. If the event is recognized, it is handled and the
545 routine returns TRUE. Otherwise, it is ignored and the routine returns
546 FALSE.
547  
548 This routine can notify the application with the following events:
549 * EVENT_PRINTER_ATTACH
550 * EVENT_PRINTER_DETACH
551 * EVENT_PRINTER_TX_DONE
552 * EVENT_PRINTER_RX_DONE
553 * EVENT_PRINTER_REQUEST_DONE
554 * EVENT_PRINTER_UNSUPPORTED
555  
556 Preconditions:
557 None
558  
559 Parameters:
560 BYTE address - Address of device with the event
561 USB_EVENT event - The bus event that occured
562 void *data - Pointer to event-specific data
563 DWORD size - Size of the event-specific data
564  
565 Return Values:
566 TRUE - The event was handled
567 FALSE - The event was not handled
568  
569 Remarks:
570 None
571 ***************************************************************************/
572  
573 BOOL USBHostPrinterEventHandler ( BYTE address, USB_EVENT event, void *data, DWORD size )
574 {
575 USB_PRINTER_QUEUE_ITEM *transfer;
576  
577 #ifdef DEBUG_MODE
578 //UART2PrintString( "PRN: Receiving event\r\n" );
579 #endif
580  
581 // Make sure it was for our device
582 if (!_USBHostPrinter_FindDevice( address ))
583 {
584 return FALSE; // The device was not found.
585 }
586  
587 // Handle specific events.
588 switch (event)
589 {
590 case EVENT_DETACH:
591 // Purge the IN and OUT transfer queues.
592 while (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
593 {
594 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE );
595 }
596 while (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
597 {
598 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE );
599 if (transfer->flags & USB_PRINTER_TRANSFER_COPY_DATA)
600 {
601 USB_FREE( transfer->data );
602 }
603 }
604  
605 // Tell the printer language support that the device has been detached.
606 USBHostPrinterCommand( usbPrinters[currentPrinterRecord].ID.deviceAddress, USB_PRINTER_DETACHED, USB_NULL, 0, 0 );
607 // Notify that application that the device has been detached.
608 USB_HOST_APP_EVENT_HANDLER(usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_DETACH,
609 &usbPrinters[currentPrinterRecord].ID.deviceAddress, sizeof(BYTE) );
610 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
611 USB_FREE( usbPrinters[currentPrinterRecord].deviceIDString );
612 #endif
613 usbPrinters[currentPrinterRecord].flags.value = 0;
614 #ifdef DEBUG_MODE
615 UART2PrintString( "PRN: USB Printer Client Device Detached: address=" );
616 UART2PutDec( address );
617 UART2PrintString( "\r\n" );
618 #endif
619 return TRUE;
620  
621 case EVENT_TRANSFER:
622 #ifdef DEBUG_MODE
623 //UART2PrintString( "PRN: TRANSFER event occurred.\r\n" );
624 #endif
625  
626 if ( (data != NULL) && (size == sizeof(HOST_TRANSFER_DATA)) )
627 {
628 DWORD dataCount = ((HOST_TRANSFER_DATA *)data)->dataCount;
629  
630 if ( ((HOST_TRANSFER_DATA *)data)->bEndpointAddress == (USB_IN_EP | usbPrinters[currentPrinterRecord].endpointIN) )
631 {
632 usbPrinters[currentPrinterRecord].flags.rxBusy = 0;
633 usbPrinters[currentPrinterRecord].rxLength = dataCount;
634  
635 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE );
636 if (transfer->flags & USB_PRINTER_TRANSFER_COPY_DATA)
637 {
638 USB_FREE( transfer->data );
639 }
640  
641 if (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
642 {
643 _USBHostPrinter_ReadFromQueue( usbPrinters[currentPrinterRecord].ID.deviceAddress );
644 }
645  
646 if (transfer->flags & USB_PRINTER_TRANSFER_NOTIFY)
647 {
648 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_RX_DONE, &dataCount, sizeof(DWORD) );
649 }
650 }
651 else if ( ((HOST_TRANSFER_DATA *)data)->bEndpointAddress == (USB_OUT_EP | usbPrinters[currentPrinterRecord].endpointOUT) )
652 {
653 usbPrinters[currentPrinterRecord].flags.txBusy = 0;
654  
655 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE );
656 if (transfer->flags & USB_PRINTER_TRANSFER_COPY_DATA)
657 {
658 USB_FREE( transfer->data );
659 }
660  
661 if (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
662 {
663 _USBHostPrinter_WriteFromQueue( usbPrinters[currentPrinterRecord].ID.deviceAddress );
664 }
665  
666 if (transfer->flags & USB_PRINTER_TRANSFER_NOTIFY)
667 {
668 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_TX_DONE, &dataCount, sizeof(DWORD) );
669 }
670 }
671 else if ((((HOST_TRANSFER_DATA *)data)->bEndpointAddress & 0x7F) == 0)
672 {
673 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
674 if (!usbPrinters[currentPrinterRecord].flags.initialized)
675 {
676 #ifdef DEBUG_MODE
677 UART2PrintString( "PRN: Check Device ID string...\r\n" );
678 #endif
679 if (!_USBHostPrinter_GetDeviceIDString())
680 {
681 #ifdef DEBUG_MODE
682 UART2PrintString( "PRN: Sending Unsupported Printer event...\r\n" );
683 #endif
684 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_UNSUPPORTED, NULL, 0 );
685 }
686 }
687 else
688 #endif
689 {
690 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_REQUEST_DONE, &dataCount, sizeof(DWORD) );
691 }
692 }
693 else
694 {
695 // Event is on an unknown endpoint.
696 return FALSE;
697 }
698 return TRUE;
699 }
700 else
701 {
702 // The data does not match what was expected for this event.
703 return FALSE;
704 }
705 break;
706  
707 case EVENT_BUS_ERROR:
708 // A bus error occurred. Clean up the best we can.
709 #ifdef DEBUG_MODE
710 UART2PrintString( "PRN: BUS_ERROR event occurred.\r\n" );
711 #endif
712  
713 if ( (data != NULL) && (size == sizeof(HOST_TRANSFER_DATA)) )
714 {
715 if ( ((HOST_TRANSFER_DATA *)data)->bEndpointAddress == (USB_IN_EP | usbPrinters[currentPrinterRecord].endpointIN) )
716 {
717 usbPrinters[currentPrinterRecord].flags.rxBusy = 0;
718 usbPrinters[currentPrinterRecord].rxLength = 0;
719  
720 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE );
721 if (transfer->flags & USB_PRINTER_TRANSFER_COPY_DATA)
722 {
723 USB_FREE( transfer->data );
724 }
725  
726 if (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
727 {
728 _USBHostPrinter_ReadFromQueue( usbPrinters[currentPrinterRecord].ID.deviceAddress );
729 }
730  
731 // if (transfer->flags & USB_PRINTER_TRANSFER_NOTIFY)
732 {
733 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_RX_ERROR, NULL, ((HOST_TRANSFER_DATA *)data)->bErrorCode );
734 }
735 }
736 else if ( ((HOST_TRANSFER_DATA *)data)->bEndpointAddress == (USB_OUT_EP | usbPrinters[currentPrinterRecord].endpointOUT) )
737 {
738 usbPrinters[currentPrinterRecord].flags.txBusy = 0;
739  
740 transfer = StructQueueRemove( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE );
741 if (transfer->flags & USB_PRINTER_TRANSFER_COPY_DATA)
742 {
743 USB_FREE( transfer->data );
744 }
745  
746 if (StructQueueIsNotEmpty( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
747 {
748 _USBHostPrinter_WriteFromQueue( usbPrinters[currentPrinterRecord].ID.deviceAddress );
749 }
750  
751 // if (transfer->flags & USB_PRINTER_TRANSFER_NOTIFY)
752 {
753 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_TX_ERROR, NULL, ((HOST_TRANSFER_DATA *)data)->bErrorCode );
754 }
755 }
756 else if ((((HOST_TRANSFER_DATA *)data)->bEndpointAddress & 0x7F) == 0)
757 {
758 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
759 if (!usbPrinters[currentPrinterRecord].flags.initialized &&
760 !usbPrinters[currentPrinterRecord].flags.deviceIDStringLengthValid)
761 {
762 // The printer does not support the GET_DEVICE_ID printer class request.
763 // We cannot determine a printer language for this printer.
764 #ifdef DEBUG_MODE
765 UART2PrintString( "PRN: Required specific printer language not found\r\n" );
766 #endif
767 usbPrinters[currentPrinterRecord].flags.value = 0;
768 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_UNSUPPORTED, NULL, 0 );
769  
770 }
771 else
772 #endif
773 {
774 // The printer gave an error during an application control transfer.
775 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_REQUEST_ERROR, NULL, ((HOST_TRANSFER_DATA *)data)->bErrorCode );
776 }
777 }
778 else
779 {
780 // Event is on an unknown endpoint.
781 return FALSE;
782 }
783 return TRUE;
784 }
785 else
786 {
787 // The data does not match what was expected for this event.
788 return FALSE;
789 }
790 break;
791  
792 case EVENT_SUSPEND:
793 case EVENT_RESUME:
794 default:
795 break;
796 }
797  
798 return FALSE;
799 } // USBHostPrinterEventHandler
800  
801  
802 // *****************************************************************************
803 // *****************************************************************************
804 // Section: Application Callable Functions
805 // *****************************************************************************
806 // *****************************************************************************
807  
808 /****************************************************************************
809 Function:
810 BYTE USBHostPrinterCommand( BYTE deviceAddress, USB_PRINTER_COMMAND command,
811 USB_DATA_POINTER data, DWORD size, BYTE flags )
812  
813 Summary:
814 This is the primary user interface function for the printer client
815 driver. It is used to issue all printer commands.
816  
817 Description:
818 This is the primary user interface function for the printer client
819 driver. It is used to issue all printer commands. Each generic printer
820 command is translated to the appropriate command for the supported
821 language and is enqueued for transfer to the printer. Before calling
822 this routine, it is recommended to call the function
823 USBHostPrinterCommandReady() to determine if there is space available
824 in the printer's output queue.
825  
826 Preconditions:
827 None
828  
829 Parameters:
830 BYTE address - Device's address on the bus
831 USB_PRINTER_COMMAND command - Command to execute. See the enumeration
832 USB_PRINTER_COMMAND for the list of
833 valid commands and their requirements.
834 USB_DATA_POINTER data - Pointer to the required data. Note that
835 the caller must set transferFlags
836 appropriately to indicate if the pointer is
837 a RAM pointer or a ROM pointer.
838 DWORD size - Size of the data. For some commands, this
839 parameter is used to hold the data itself.
840 BYTE transferFlags - Flags that indicate details about the
841 transfer operation. Refer to these flags
842 * USB_PRINTER_TRANSFER_COPY_DATA
843 * USB_PRINTER_TRANSFER_STATIC_DATA
844 * USB_PRINTER_TRANSFER_NOTIFY
845 * USB_PRINTER_TRANSFER_FROM_ROM
846 * USB_PRINTER_TRANSFER_FROM_RAM
847  
848 Returns:
849 See the USB_PRINTER_ERRORS enumeration. Also, refer to the printer
850 language command handler function, such as
851 USBHostPrinterLanguagePostScript().
852  
853 Example:
854 <code>
855 if (USBHostPrinterCommandReady( address ))
856 {
857 USBHostPrinterCommand( address, USB_PRINTER_JOB_START, NULL, 0, 0 );
858 }
859 </code>
860  
861 Remarks:
862 Use the definitions USB_DATA_POINTER_RAM() and USB_DATA_POINTER_ROM()
863 to cast data pointers. For example:
864 <code>
865 USBHostPrinterCommand( address, USB_PRINTER_TEXT, USB_DATA_POINTER_RAM(buffer), strlen(buffer), 0 );
866 </code>
867  
868 When developing new commands, keep in mind that the function
869 USBHostPrinterCommandReady() will often be used before calling this
870 function to see if there is space available in the output transfer queue.
871 USBHostPrinterCommandReady() will routine TRUE if a single space is
872 available in the output queue. Therefore, each command can generate only
873 one output transfer.
874 ***************************************************************************/
875  
876 BYTE USBHostPrinterCommand( BYTE deviceAddress, USB_PRINTER_COMMAND command,
877 USB_DATA_POINTER data, DWORD size, BYTE flags )
878 {
879 if (!_USBHostPrinter_FindDevice( deviceAddress ))
880 {
881 // The device was not found.
882 return USB_PRINTER_UNKNOWN_DEVICE;
883 }
884  
885 return usbPrinters[currentPrinterRecord].languageHandler( deviceAddress, command, data, size, flags );
886 }
887  
888  
889 /****************************************************************************
890 Function:
891 BOOL USBHostPrinterCommandReady( BYTE deviceAddress )
892  
893 Description:
894 This interface is used to check if the client driver has space available
895 to enqueue another transfer.
896  
897 Preconditions:
898 None
899  
900 Parameters:
901 deviceAddress - USB Address of the device
902  
903 Return Values:
904 TRUE - The printer client driver has room for at least one more
905 transfer request, or the device is not attached. The latter
906 allows this routine to be called without generating an
907 infinite loop if the device detaches.
908 FALSE - The transfer queue is full.
909  
910 Example:
911 <code>
912 if (USBHostPrinterCommandReady( address ))
913 {
914 USBHostPrinterCommand( address, USB_PRINTER_JOB_START, NULL, 0, 0 );
915 }
916 </code>
917  
918 Remarks:
919 This routine will return TRUE if a single transfer can be enqueued. Since
920 this routine is the check to see if USBHostPrinterCommand() can be called,
921 every command can generate at most one transfer.
922 ***************************************************************************/
923  
924 BOOL USBHostPrinterCommandReady( BYTE deviceAddress )
925 {
926 if (!_USBHostPrinter_FindDevice( deviceAddress ))
927 {
928 // The device was not found.
929 return TRUE;
930 }
931  
932 if (StructQueueSpaceAvailable( 1, &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
933 {
934 return TRUE;
935 }
936 return FALSE;
937 }
938  
939  
940 /****************************************************************************
941 Function:
942 BOOL USBHostPrinterDeviceDetached( BYTE deviceAddress )
943  
944 Description:
945 This interface is used to check if the device has been detached from the
946 bus.
947  
948 Preconditions:
949 None
950  
951 Parameters:
952 BYTE deviceAddress - USB Address of the device.
953  
954 Return Values:
955 TRUE - The device has been detached, or an invalid deviceAddress is given.
956 FALSE - The device is attached
957  
958 Example:
959 <code>
960 if (USBHostPrinterDeviceDetached( deviceAddress ))
961 {
962 // Handle detach
963 }
964 </code>
965  
966 Remarks:
967 The event EVENT_PRINTER_DETACH can also be used to detect a detach.
968 ***************************************************************************/
969  
970 BOOL USBHostPrinterDeviceDetached( BYTE deviceAddress )
971 {
972 if (_USBHostPrinter_FindDevice( deviceAddress ))
973 {
974 return FALSE;
975 }
976 return TRUE;
977 }
978  
979  
980 /****************************************************************************
981 Function:
982 DWORD USBHostPrinterGetRxLength( BYTE deviceAddress )
983  
984 Description:
985 This function retrieves the number of bytes copied to user's buffer by
986 the most recent call to the USBHostPrinterRead() function.
987  
988 Preconditions:
989 The device must be connected and enumerated.
990  
991 Parameters:
992 BYTE deviceAddress - USB Address of the device
993  
994 Returns:
995 Returns the number of bytes most recently received from the Generic
996 device with address deviceAddress.
997  
998 Remarks:
999 None
1000 ***************************************************************************/
1001  
1002 DWORD USBHostPrinterGetRxLength( BYTE deviceAddress )
1003 {
1004 if (!_USBHostPrinter_FindDevice( deviceAddress ))
1005 {
1006 return 0;
1007 }
1008 return usbPrinters[currentPrinterRecord].rxLength;
1009 }
1010  
1011  
1012 /****************************************************************************
1013 Function:
1014 BYTE USBHostPrinterGetStatus( BYTE deviceAddress, BYTE *status )
1015  
1016 Summary:
1017 This function issues the Printer class-specific Device Request to
1018 obtain the printer status.
1019  
1020 Description:
1021 This function issues the Printer class-specific Device Request to
1022 obtain the printer status. The returned status should have the following
1023 format, per the USB specification. Any deviation will be due to the
1024 specific printer implementation.
1025 * Bit 5 - Paper Empty; 1 = paper empty, 0 = paper not empty
1026 * Bit 4 - Select; 1 = selected, 0 = not selected
1027 * Bit 3 - Not Error; 1 = no error, 0 = error
1028 * All other bits are reserved.
1029  
1030 The *status parameter is not updated until the EVENT_PRINTER_REQUEST_DONE
1031 event is thrown. Until that point the value of *status is unknown.
1032  
1033 The *status parameter will only be updated if this function returns
1034 USB_SUCCESS. If this function returns with any other error code then the
1035 EVENT_PRINTER_REQUEST_DONE event will not be thrown and the status field
1036 will not be updated.
1037  
1038 Preconditions:
1039 The device must be connected and enumerated.
1040  
1041 Parameters:
1042 deviceAddress - USB Address of the device
1043 *status - pointer to the returned status byte
1044  
1045 Returns:
1046 See the return values for the USBHostIssueDeviceRequest() function.
1047  
1048 Remarks:
1049 None
1050 ***************************************************************************/
1051  
1052 BYTE USBHostPrinterGetStatus( BYTE deviceAddress, BYTE *status )
1053 {
1054 if (!_USBHostPrinter_FindDevice( deviceAddress ))
1055 {
1056 return USB_UNKNOWN_DEVICE;
1057 }
1058  
1059 return USBHostIssueDeviceRequest( deviceAddress,
1060 USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE,
1061 PRINTER_DEVICE_REQUEST_GET_PORT_STATUS,
1062 0, 0x0000, 1,
1063 status, USB_DEVICE_REQUEST_GET, usbPrinters[currentPrinterRecord].clientDriverID );
1064 }
1065  
1066  
1067 /****************************************************************************
1068 Function:
1069 void USBHostPrinterRead( BYTE deviceAddress, BYTE *buffer, DWORD length,
1070 BYTE transferFlags )
1071  
1072 Description:
1073 Use this routine to receive from the device and store it into memory.
1074  
1075 Preconditions:
1076 The device must be connected and enumerated.
1077  
1078 Parameters:
1079 deviceAddress - USB Address of the device.
1080 buffer - Pointer to the data buffer
1081 length - Number of bytes to be transferred
1082 transferFlags - Flags for how to perform the operation
1083  
1084 Return Values:
1085 USB_SUCCESS - The Read was started successfully
1086 (USB error code) - The Read was not started. See USBHostRead() for
1087 a list of errors.
1088  
1089 Example:
1090 <code>
1091 if (!USBHostPrinterRxIsBusy( deviceAddress ))
1092 {
1093 USBHostPrinterRead( deviceAddress, &buffer, sizeof(buffer), 0 );
1094 }
1095 </code>
1096  
1097 Remarks:
1098 None
1099 ***************************************************************************/
1100  
1101 BYTE USBHostPrinterRead( BYTE deviceAddress, void *buffer, DWORD length,
1102 BYTE transferFlags )
1103 {
1104 USB_PRINTER_QUEUE_ITEM *transfer;
1105  
1106 // Validate the call
1107 if (!_USBHostPrinter_FindDevice( deviceAddress ) ||
1108 !usbPrinters[currentPrinterRecord].flags.initialized)
1109 {
1110 return USB_INVALID_STATE;
1111 }
1112  
1113 // Check transfer path
1114 if (StructQueueIsFull( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
1115 {
1116 return USB_PRINTER_BUSY;
1117 }
1118  
1119 // Add the newest transfer to the queue
1120  
1121 transfer = StructQueueAdd( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE);
1122 transfer->data = buffer;
1123 transfer->size = length;
1124 transfer->flags = transferFlags;
1125  
1126 if (usbPrinters[currentPrinterRecord].flags.rxBusy)
1127 {
1128 // The request has been queued. We'll execute it when the current transfer is complete.
1129 return USB_SUCCESS;
1130 }
1131 else
1132 {
1133 return _USBHostPrinter_ReadFromQueue( deviceAddress );
1134 }
1135 } // USBHostPrinterRead
1136  
1137  
1138 /****************************************************************************
1139 Function:
1140 BYTE USBHostPrinterReset( BYTE deviceAddress )
1141  
1142 Description:
1143 This function issues the Printer class-specific Device Request to
1144 perform a soft reset.
1145  
1146 Preconditions:
1147 The device must be connected and enumerated.
1148  
1149 Parameters:
1150 BYTE deviceAddress - USB Address of the device
1151  
1152 Returns:
1153 See the return values for the USBHostIssueDeviceRequest() function.
1154  
1155 Remarks:
1156 Not all printers support this command.
1157 ***************************************************************************/
1158  
1159 BYTE USBHostPrinterReset( BYTE deviceAddress )
1160 {
1161 if (!_USBHostPrinter_FindDevice( deviceAddress ))
1162 {
1163 return USB_UNKNOWN_DEVICE;
1164 }
1165  
1166 return USBHostIssueDeviceRequest( deviceAddress,
1167 USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE,
1168 PRINTER_DEVICE_REQUEST_SOFT_RESET,
1169 0, 0x0000, 0,
1170 NULL, USB_DEVICE_REQUEST_SET, usbPrinters[currentPrinterRecord].clientDriverID );
1171 }
1172  
1173  
1174 /****************************************************************************
1175 Function:
1176 BOOL USBHostPrinterRxIsBusy( BYTE deviceAddress )
1177  
1178 Summary:
1179 This interface is used to check if the client driver is currently busy
1180 receiving data from the device.
1181  
1182 Description:
1183 This interface is used to check if the client driver is currently busy
1184 receiving data from the device. This function is intended for use with
1185 transfer events. With polling, the function USBHostPrinterRxIsComplete()
1186 should be used.
1187  
1188 Preconditions:
1189 None
1190  
1191 Parameters:
1192 deviceAddress - USB Address of the device
1193  
1194 Return Values:
1195 TRUE - The device is receiving data or an invalid deviceAddress is
1196 given.
1197 FALSE - The device is not receiving data
1198  
1199 Example:
1200 <code>
1201 if (!USBHostPrinterRxIsBusy( deviceAddress ))
1202 {
1203 USBHostPrinterRead( deviceAddress, &Buffer, sizeof( Buffer ) );
1204 }
1205 </code>
1206  
1207 Remarks:
1208 None
1209 ***************************************************************************/
1210  
1211 BOOL USBHostPrinterRxIsBusy( BYTE deviceAddress )
1212 {
1213 if (!_USBHostPrinter_FindDevice( deviceAddress ))
1214 {
1215 // The device was not found.
1216 return TRUE;
1217 }
1218  
1219 if (usbPrinters[currentPrinterRecord].flags.rxBusy)
1220 {
1221 return TRUE;
1222 }
1223 return FALSE;
1224 }
1225  
1226  
1227 /****************************************************************************
1228 Function:
1229 BYTE USBHostPrinterWrite( BYTE deviceAddress, void *buffer, DWORD length,
1230 BYTE transferFlags )
1231  
1232 Description:
1233 Use this routine to transmit data from memory to the device. This
1234 routine will not usually be called by the application directly. The
1235 application will use the USBHostPrinterCommand() function, which will
1236 call the appropriate printer language support function, which will
1237 utilize this routine.
1238  
1239 Preconditions:
1240 The device must be connected and enumerated.
1241  
1242 Parameters:
1243 BYTE deviceAddress - USB Address of the device.
1244 void *buffer - Pointer to the data buffer
1245 DWORD length - Number of bytes to be transferred
1246 BYTE transferFlags - Flags for how to perform the operation
1247  
1248 Return Values:
1249 USB_SUCCESS - The Write was started successfully.
1250 USB_PRINTER_UNKNOWN_DEVICE - Device not found or has not been initialized.
1251 USB_PRINTER_BUSY - The printer's output queue is full.
1252 (USB error code) - The Write was not started. See USBHostWrite() for
1253 a list of errors.
1254  
1255 Remarks:
1256 None
1257 ***************************************************************************/
1258  
1259  
1260 BYTE USBHostPrinterWrite( BYTE deviceAddress, void *buffer, DWORD length,
1261 BYTE transferFlags)
1262 {
1263 USB_PRINTER_QUEUE_ITEM *transfer;
1264  
1265 // Validate the call
1266 if (!_USBHostPrinter_FindDevice( deviceAddress ) ||
1267 !usbPrinters[currentPrinterRecord].flags.initialized)
1268 {
1269 return USB_PRINTER_UNKNOWN_DEVICE;
1270 }
1271  
1272 // Check transfer path
1273 if (StructQueueIsFull( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE ))
1274 {
1275 // The queue is full. If the caller was using heap space for the data,
1276 // deallocate the memory.
1277 if (transferFlags & USB_PRINTER_TRANSFER_COPY_DATA)
1278 {
1279 USB_FREE( buffer );
1280 }
1281 return USB_PRINTER_BUSY;
1282 }
1283  
1284 // Add the newest transfer to the queue
1285  
1286 transfer = StructQueueAdd( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE );
1287 transfer->data = buffer;
1288 transfer->size = length;
1289 transfer->flags = transferFlags;
1290  
1291 if (usbPrinters[currentPrinterRecord].flags.txBusy)
1292 {
1293 // The request has been queued. We'll execute it when the current transfer is complete.
1294 return USB_SUCCESS;
1295 }
1296 else
1297 {
1298 // We can send the request now. We still have to put it in the
1299 // queue, because that's where the event handler gets its information.
1300 return _USBHostPrinter_WriteFromQueue( deviceAddress );
1301 }
1302 }
1303  
1304  
1305 /****************************************************************************
1306 Function:
1307 BOOL USBHostPrinterWriteComplete( BYTE deviceAddress )
1308  
1309 Description:
1310 This interface is used to check if the client driver is currently
1311 transmitting data to the printer, or if it is between transfers but still
1312 has transfers queued.
1313  
1314 Preconditions:
1315 None
1316  
1317 Parameters:
1318 deviceAddress - USB Address of the device
1319  
1320 Return Values:
1321 TRUE - The device is done transmitting data or an invalid deviceAddress
1322 is given.
1323 FALSE - The device is transmitting data or has a transfer in the queue.
1324  
1325 Remarks:
1326 None
1327 ***************************************************************************/
1328  
1329 BOOL USBHostPrinterWriteComplete( BYTE deviceAddress )
1330 {
1331 if (!_USBHostPrinter_FindDevice( deviceAddress ))
1332 {
1333 // The device was not found.
1334 return TRUE;
1335 }
1336  
1337 if (usbPrinters[currentPrinterRecord].flags.txBusy ||
1338 !(StructQueueIsEmpty( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE )))
1339 {
1340 return FALSE;
1341 }
1342 return TRUE;
1343 }
1344  
1345  
1346 // *****************************************************************************
1347 // *****************************************************************************
1348 // Section: Internal Functions
1349 // *****************************************************************************
1350 // *****************************************************************************
1351  
1352 /****************************************************************************
1353 Function:
1354 BOOL _USBHostPrinter_FindDevice( BYTE address )
1355  
1356 Description:
1357 This function looks in the array of printers to see if there is currently
1358 a printer attached at the indicated device. If so, it returns TRUE, and
1359 the global variable currentPrinterRecord is changed to the index of the
1360 printer. If not, it returns FALSE. Note that the function implies
1361 nothing about the status of the printer; it may not be ready to use.
1362  
1363 Preconditions:
1364 None
1365  
1366 Parameters:
1367 deviceAddress - USB Address of the device.
1368  
1369 Return Values:
1370 TRUE - The indicated device is attached
1371 FALSE - The indicated device is not attached
1372  
1373 Remarks:
1374 None
1375 ***************************************************************************/
1376  
1377 BOOL _USBHostPrinter_FindDevice( BYTE address )
1378 {
1379 for (currentPrinterRecord=0; currentPrinterRecord<USB_MAX_PRINTER_DEVICES; currentPrinterRecord++)
1380 {
1381 if (usbPrinters[currentPrinterRecord].flags.inUse &&
1382 (usbPrinters[currentPrinterRecord].ID.deviceAddress == address))
1383 {
1384 return TRUE;
1385 }
1386 }
1387 return FALSE; // The device was not found.
1388 }
1389  
1390  
1391 /****************************************************************************
1392 Function:
1393 BOOL _USBHostPrinter_GetDeviceIDString( void )
1394  
1395 Description:
1396 This routine performs most of the process required to get the device ID
1397 string. The initial request to get the length is performed in the
1398 initialization handler. This routine handles the processing of the
1399 length, the request for the entire string, and processing of the string.
1400 The format of this string is specified by IEEE 1284.
1401  
1402 Preconditions:
1403 None
1404  
1405 Parameters:
1406 None - None
1407  
1408 Return Values:
1409 TRUE - Processing is proceeding normally
1410 FALSE - Cannot read the device ID string, or cannot find a printer
1411 language to use to communicate with the printer.
1412  
1413 Remarks:
1414 This function is available only if USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
1415 has been defined.
1416 ***************************************************************************/
1417  
1418 #ifdef USB_PRINTER_ALLOW_DYNAMIC_LANGUAGE_DETERMINATION
1419  
1420 BOOL _USBHostPrinter_GetDeviceIDString( void )
1421 {
1422 BYTE errorCode;
1423  
1424 if (!usbPrinters[currentPrinterRecord].flags.deviceIDStringLengthValid)
1425 {
1426 // This transfer was to get the length of the string.
1427 // The length is a 2-byte value, MSB first.
1428 usbPrinters[currentPrinterRecord].deviceIDStringLength = ( (BYTE)usbPrinters[currentPrinterRecord].deviceIDString[0] << 8) + (BYTE)usbPrinters[currentPrinterRecord].deviceIDString[1];
1429 usbPrinters[currentPrinterRecord].flags.deviceIDStringLengthValid = 1;
1430  
1431 #ifdef DEBUG_MODE
1432 UART2PrintString( "PRN: Got device ID string length: " );
1433 UART2PutHex( usbPrinters[currentPrinterRecord].deviceIDStringLength >> 8);
1434 UART2PutHex( usbPrinters[currentPrinterRecord].deviceIDStringLength );
1435 UART2PrintString( "\r\n" );
1436 #endif
1437  
1438 USB_FREE( usbPrinters[currentPrinterRecord].deviceIDString );
1439 usbPrinters[currentPrinterRecord].deviceIDString = (char *)USB_MALLOC( usbPrinters[currentPrinterRecord].deviceIDStringLength + 3 );
1440 if (usbPrinters[currentPrinterRecord].deviceIDString == NULL)
1441 {
1442 #ifdef DEBUG_MODE
1443 UART2PrintString( "PRN: Out of memory for the device ID string.\r\n" );
1444 #endif
1445 usbPrinters[currentPrinterRecord].flags.value = 0;
1446 return FALSE;
1447 }
1448 else
1449 {
1450 // Get the full string
1451 errorCode = USBHostIssueDeviceRequest( usbPrinters[currentPrinterRecord].ID.deviceAddress,
1452 USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE,
1453 PRINTER_DEVICE_REQUEST_GET_DEVICE_ID, 0, 0, usbPrinters[currentPrinterRecord].deviceIDStringLength,
1454 (BYTE *)usbPrinters[currentPrinterRecord].deviceIDString, USB_DEVICE_REQUEST_GET,
1455 usbPrinters[currentPrinterRecord].clientDriverID );
1456 if (errorCode)
1457 {
1458 #ifdef DEBUG_MODE
1459 UART2PrintString( "PRN: Cannot get device ID string - " );
1460 UART2PutHex( errorCode );
1461 UART2PrintString( "\r\n" );
1462 #endif
1463 // If we cannot read the ID string, then we cannot determine the required printer language.
1464 usbPrinters[currentPrinterRecord].flags.value = 0;
1465 return FALSE;
1466 }
1467 #ifdef DEBUG_MODE
1468 UART2PrintString( "PRN: Getting device ID string ...\r\n" );
1469 #endif
1470 }
1471 }
1472 else
1473 {
1474 char *commandSet;
1475 WORD i;
1476 WORD semicolonLocation;
1477  
1478 // Null terminate the device ID string so we can do string manipulation on it.
1479 usbPrinters[currentPrinterRecord].deviceIDString[usbPrinters[currentPrinterRecord].deviceIDStringLength + 2] = 0;
1480  
1481 #ifdef DEBUG_MODE
1482 UART2PrintString( "PRN: Got device ID string: (Length " );
1483 UART2PutHex( usbPrinters[currentPrinterRecord].deviceIDString[0] );
1484 UART2PutHex( usbPrinters[currentPrinterRecord].deviceIDString[1] );
1485 UART2PrintString( ")\r\n" );
1486 for (i=2; i<usbPrinters[currentPrinterRecord].deviceIDStringLength; i++)
1487 {
1488 UART2PutChar( usbPrinters[currentPrinterRecord].deviceIDString[i] );
1489 }
1490 UART2PrintString( "\r\n" );
1491 #endif
1492  
1493 // Determine if one of the languages we are currently using can support this
1494 // printer. Languages should be listed in ascending order of preference
1495 // in the usbPrinterClientLanguages array, so we can stop looking as soon
1496 // as we find a match.
1497 commandSet = strstr( &(usbPrinters[currentPrinterRecord].deviceIDString[2]), "COMMAND SET:" );
1498 if (!commandSet)
1499 {
1500 commandSet = strstr( &(usbPrinters[currentPrinterRecord].deviceIDString[2]), "CMD:" );
1501 }
1502 if (!commandSet)
1503 {
1504 // No printer language support is indicated.
1505 #ifdef DEBUG_MODE
1506 UART2PrintString( "PRN: Device ID string did not contain command set\r\n" );
1507 #endif
1508 usbPrinters[currentPrinterRecord].flags.value = 0;
1509 return FALSE;
1510 }
1511  
1512 // Replace the semicolon at the end of the COMMAND SET: specification with a
1513 // null, so we don't get a false positive based on some other portion of the
1514 // device ID string. If we don't find a semicolon, set the location to 0.
1515 for (semicolonLocation = 0;
1516 (commandSet[semicolonLocation] != 0) && (commandSet[semicolonLocation] != ';');
1517 semicolonLocation ++ ) {};
1518 if (commandSet[semicolonLocation] == 0)
1519 {
1520 semicolonLocation = 0;
1521 }
1522 else
1523 {
1524 commandSet[semicolonLocation] = 0;
1525 }
1526  
1527 // Convert the command set to all upper case.
1528 for (i=0; i<semicolonLocation; i++)
1529 {
1530 commandSet[i] = toupper( commandSet[i] );
1531 }
1532  
1533 // Look for a supported printer language in the array of available languages.
1534 i = 0;
1535 usbPrinters[currentPrinterRecord].languageHandler = NULL;
1536 while ((usbPrinterClientLanguages[i].isLanguageSupported != NULL) &&
1537 (usbPrinters[currentPrinterRecord].languageHandler == NULL))
1538 {
1539 if (usbPrinterClientLanguages[i].isLanguageSupported( commandSet, &(usbPrinters[currentPrinterRecord].ID.support) ))
1540 {
1541 usbPrinters[currentPrinterRecord].languageHandler = usbPrinterClientLanguages[i].languageCommandHandler;
1542 #ifdef DEBUG_MODE
1543 UART2PrintString( "PRN: Printer language support: " );
1544 UART2PutHex( usbPrinters[currentPrinterRecord].ID.support.val );
1545 UART2PrintString( "\r\n" );
1546 #endif
1547 }
1548 i ++;
1549 }
1550  
1551 // Restore the device ID string to its original state.
1552 if (semicolonLocation != 0)
1553 {
1554 commandSet[semicolonLocation] = ';';
1555 }
1556  
1557 // See if we were able to find a printer language.
1558 if (usbPrinters[currentPrinterRecord].languageHandler == NULL)
1559 {
1560 #ifdef DEBUG_MODE
1561 UART2PrintString( "PRN: Required printer language not found\r\n" );
1562 #endif
1563 usbPrinters[currentPrinterRecord].flags.value = 0;
1564 return FALSE;
1565 }
1566  
1567 // We have a printer language that we can use with this printer.
1568 #ifdef DEBUG_MODE
1569 UART2PrintString( "PRN: Required printer language found\r\n" );
1570 #endif
1571 usbPrinters[currentPrinterRecord].flags.initialized = 1;
1572 USBHostPrinterCommand( usbPrinters[currentPrinterRecord].ID.deviceAddress, USB_PRINTER_ATTACHED,
1573 USB_DATA_POINTER_RAM(&(usbPrinters[currentPrinterRecord].ID.support)), sizeof(USB_PRINTER_FUNCTION_SUPPORT), 0 );
1574  
1575 // Tell the application layer that we have a device.
1576 USB_HOST_APP_EVENT_HANDLER( usbPrinters[currentPrinterRecord].ID.deviceAddress, EVENT_PRINTER_ATTACH,
1577 &(usbPrinters[currentPrinterRecord].ID), sizeof(USB_PRINTER_DEVICE_ID) );
1578 }
1579  
1580 return TRUE;
1581 }
1582  
1583 #endif
1584  
1585  
1586 /****************************************************************************
1587 Function:
1588 void _USBHostPrinter_ReadFromQueue( BYTE deviceAddress )
1589  
1590 Description:
1591 This routine initiates the IN transfer described by the first entry
1592 in the queue.
1593  
1594 Preconditions:
1595 * The receive path must be clear before calling this routine.
1596 * The queue must contain at least one valid entry.
1597 * currentPrinterRecord must be valid.
1598  
1599 Parameters:
1600 deviceAddress - USB Address of the device.
1601  
1602 Return Values:
1603 USB_SUCCESS - The Read was started successfully
1604 (USB error code) - The Read was not started. See USBHostRead() for
1605 a list of errors.
1606  
1607 Remarks:
1608 None
1609 ***************************************************************************/
1610  
1611 BYTE _USBHostPrinter_ReadFromQueue( BYTE deviceAddress )
1612 {
1613 BYTE returnValue;
1614 USB_PRINTER_QUEUE_ITEM *transfer;
1615  
1616 transfer = StructQueuePeekTail( &(usbPrinters[currentPrinterRecord].transferQueueIN), USB_PRINTER_TRANSFER_QUEUE_SIZE );
1617  
1618 usbPrinters[currentPrinterRecord].flags.rxBusy = 1;
1619 usbPrinters[currentPrinterRecord].rxLength = 0;
1620 returnValue = USBHostRead( deviceAddress, USB_IN_EP|usbPrinters[currentPrinterRecord].endpointIN, (BYTE *)(transfer->data), transfer->size );
1621 if (returnValue != USB_SUCCESS)
1622 {
1623 usbPrinters[currentPrinterRecord].flags.rxBusy = 0; // Clear flag to allow re-try
1624 }
1625  
1626 return returnValue;
1627 }
1628  
1629  
1630 /****************************************************************************
1631 Function:
1632 void _USBHostPrinter_WriteFromQueue( BYTE deviceAddress )
1633  
1634 Description:
1635 This routine initiates the OUT transfer described by the first entry
1636 in the queue.
1637  
1638 Preconditions:
1639 * The transmit path must be clear before calling this routine.
1640 * The queue must contain at least one valid entry.
1641 * currentPrinterRecord must be valid.
1642  
1643 Parameters:
1644 deviceAddress - USB Address of the device.
1645  
1646 Return Values:
1647 USB_SUCCESS - The Read was started successfully
1648 (USB error code) - The Read was not started. See USBHostWrite() for
1649 a list of errors.
1650  
1651 Remarks:
1652 None
1653 ***************************************************************************/
1654  
1655 BYTE _USBHostPrinter_WriteFromQueue( BYTE deviceAddress )
1656 {
1657 BYTE returnValue;
1658 USB_PRINTER_QUEUE_ITEM *transfer;
1659 #if defined( DEBUG_MODE ) || defined( DEBUG_PRINT_COMMANDS )
1660 //BYTE i;
1661 #endif
1662  
1663 transfer = StructQueuePeekTail( &(usbPrinters[currentPrinterRecord].transferQueueOUT), USB_PRINTER_TRANSFER_QUEUE_SIZE );
1664  
1665 #if defined( DEBUG_MODE )
1666 //UART2PrintString( "PRN: OUT, " );
1667 #endif
1668 #if defined( DEBUG_MODE ) || defined( DEBUG_PRINT_COMMANDS )
1669 //for (i=0; i<transfer->size; i++) UART2PutChar(transfer->data[i]);
1670 //UART2PutHex( transfer->size >> 8 );
1671 //UART2PutHex( transfer->size );
1672 //UART2PrintString( "\r\n" );
1673 #endif
1674  
1675 usbPrinters[currentPrinterRecord].flags.txBusy = 1;
1676 returnValue = USBHostWrite( deviceAddress, USB_OUT_EP|usbPrinters[currentPrinterRecord].endpointOUT, (BYTE *)(transfer->data), transfer->size );
1677 if (returnValue != USB_SUCCESS)
1678 {
1679 usbPrinters[currentPrinterRecord].flags.txBusy = 0; // Clear flag to allow re-try
1680 }
1681  
1682 return returnValue;
1683 }
1684  
1685  
1686 /*************************************************************************
1687 * EOF usb_client_generic.c
1688 */
1689  
1690  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3