From 786479faf0605d610c93041191ee5bd6d020ccf9 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Sun, 19 Jul 2009 12:36:19 +0000 Subject: [PATCH] Add partial project documentation to the incomplete PrinterHost demo. Change over Printer_GetDeviceID() to require a pointer to the destination buffer plus the buffer size, rather than using a pointer to a special structure. Make new Printer_SendData() function to hide the implementation of sending data to an attached printer, cleaning up the main demo source file body. --- .../Incomplete/PrinterHost/ConfigDescriptor.c | 14 ++--- .../Incomplete/PrinterHost/ConfigDescriptor.h | 35 ++++++++---- .../PrinterHost/Lib/PrinterCommands.c | 55 ++++++++++++++++--- .../PrinterHost/Lib/PrinterCommands.h | 24 ++++---- .../Host/Incomplete/PrinterHost/PrinterHost.c | 41 ++++++-------- .../Host/Incomplete/PrinterHost/PrinterHost.h | 1 + LUFA/ManPages/ChangeLog.txt | 2 +- 7 files changed, 110 insertions(+), 62 deletions(-) diff --git a/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.c b/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.c index 67a0fa76e5..d4eaff94a1 100644 --- a/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.c +++ b/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.c @@ -61,7 +61,7 @@ uint8_t ProcessConfigurationDescriptor(void) /* Get the printer interface from the configuration descriptor */ if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, - NextBidirectionalPrinterInterface))) + DComp_NextBidirectionalPrinterInterface))) { /* Descriptor not found, error out */ return NoInterfaceFound; @@ -70,12 +70,12 @@ uint8_t ProcessConfigurationDescriptor(void) PrinterInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; PrinterAltSetting = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).AlternateSetting; - /* Get the IN and OUT data endpoints for the mass storage interface */ + /* Get the IN and OUT data endpoints for the printer interface */ while (FoundEndpoints != ((1 << PRINTER_DATA_OUT_PIPE) | (1 << PRINTER_DATA_IN_PIPE))) { /* Fetch the next bulk endpoint from the current printer interface */ if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, - NextInterfaceBulkDataEndpoint))) + DComp_NextInterfaceBulkDataEndpoint))) { /* Descriptor not found, error out */ return NoEndpointFound; @@ -112,16 +112,16 @@ uint8_t ProcessConfigurationDescriptor(void) return SuccessfulConfigRead; } -uint8_t NextBidirectionalPrinterInterface(void* CurrentDescriptor) +uint8_t DComp_NextBidirectionalPrinterInterface(void* CurrentDescriptor) { - /* PURPOSE: Find next Bidirectional protocol printer class interface descriptor */ + /* PURPOSE: Find next bidirectional protocol printer class interface descriptor */ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { /* Check the descriptor class and protocol, break out if correct class/protocol interface found */ if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) && - (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PROTOCOL_BIDIRECTIONAL)) + (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } @@ -130,7 +130,7 @@ uint8_t NextBidirectionalPrinterInterface(void* CurrentDescriptor) return DESCRIPTOR_SEARCH_NotFound; } -uint8_t NextInterfaceBulkDataEndpoint(void* CurrentDescriptor) +uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor) { /* PURPOSE: Find next interface bulk endpoint descriptor before next interface descriptor */ diff --git a/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.h b/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.h index bbe23725ce..3e24adc11b 100644 --- a/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.h +++ b/Demos/Host/Incomplete/PrinterHost/ConfigDescriptor.h @@ -35,35 +35,48 @@ #include #include "PrinterHost.h" + #include "Lib/PrinterCommands.h" /* Macros: */ + /** Interface Class value for the Printer Device class */ #define PRINTER_CLASS 0x07 + + /** Interface Subclass value for the Printer Device class */ #define PRINTER_SUBCLASS 0x01 + + /** Interface Protocol value for a Bidirectional communication encapsulation */ + #define PRINTER_PROTOCOL 0x02 - #define PRINTER_DATA_OUT_PIPE 1 - #define PRINTER_DATA_IN_PIPE 2 - + /** Maximum size of a device configuration descriptor which can be processed by the host, in bytes */ #define MAX_CONFIG_DESCRIPTOR_SIZE 512 /* Enums: */ + /** Enum for the possible return codes of the ProcessConfigurationDescriptor() function. */ enum PrinterHost_GetConfigDescriptorDataCodes_t { - SuccessfulConfigRead = 0, - ControlError = 1, - DescriptorTooLarge = 2, - InvalidConfigDataReturned = 3, - NoInterfaceFound = 4, - NoEndpointFound = 5, + SuccessfulConfigRead = 0, /**< Configuration Descriptor was processed successfully */ + ControlError = 1, /**< A control request to the device failed to complete successfully */ + DescriptorTooLarge = 2, /**< The device's Configuration Descriptor is too large to process */ + InvalidConfigDataReturned = 3, /**< The device returned an invalid Configuration Descriptor */ + NoInterfaceFound = 4, /**< A compatible printer interface was not found in the device's Configuration Descriptor */ + NoEndpointFound = 5, /**< The printer data endpoints were not found in the device's Configuration Descriptor */ }; /* External Variables: */ + /** Interface index of the Bidirectional Printer interface within the device, once the Configuration + * Descriptor has been processed. + */ uint8_t PrinterInterfaceNumber; + + /** Interface Alternate Setting index of the Bidirectional Printer interface within the device, once + * the Configuration Descriptor has been processed. + */ uint8_t PrinterAltSetting; /* Function Prototypes: */ uint8_t ProcessConfigurationDescriptor(void); - uint8_t NextBidirectionalPrinterInterface(void* CurrentDescriptor); - uint8_t NextInterfaceBulkDataEndpoint(void* CurrentDescriptor); + uint8_t DComp_NextBidirectionalPrinterInterface(void* CurrentDescriptor); + uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor); #endif diff --git a/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.c b/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.c index 9324a141c0..075b2d6015 100644 --- a/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.c +++ b/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.c @@ -30,7 +30,33 @@ #include "PrinterCommands.h" -uint8_t Printer_GetDeviceID(Device_ID_String_t* DeviceIDString) +uint8_t Printer_SendData(char* PrinterCommands) +{ + uint8_t ErrorCode; + + Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, strlen(PrinterCommands))) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + Pipe_ClearOUT(); + while (!(Pipe_IsOUTReady())); + + Pipe_Freeze(); + + return PIPE_RWSTREAM_NoError; +} + +/** Issues a Printer class Get Device ID command to the attached device, to retrieve the device ID string (which indicates + * the accepted printer languages, the printer's model and other pertinent information). + * + * \param[out] DeviceIDString Pointer to the destination where the returned string should be stored + * \param[in] BufferSize Size in bytes of the allocated buffer for the returned Device ID string + * + * \return A value from the USB_Host_SendControlErrorCodes_t enum + */ +uint8_t Printer_GetDeviceID(char* DeviceIDString, uint8_t BufferSize) { uint8_t ErrorCode = HOST_SENDCONTROL_Successful; uint16_t DeviceIDStringLength; @@ -41,28 +67,34 @@ uint8_t Printer_GetDeviceID(Device_ID_String_t* DeviceIDString) bRequest: GET_DEVICE_ID, wValue: 0, wIndex: 0, - wLength: sizeof(DeviceIDString->Length), + wLength: sizeof(DeviceIDStringLength), }; - if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful) + if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful) return ErrorCode; - DeviceIDStringLength = SwapEndian_16(DeviceIDString->Length); + DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength); - /* Protect against overflow for the null terminator if the string length is equal to or larger than the buffer */ - if (DeviceIDStringLength >= sizeof(DeviceIDString->String)) - DeviceIDStringLength = sizeof(DeviceIDString->String) - 1; + if (DeviceIDStringLength > BufferSize) + DeviceIDStringLength = BufferSize; - USB_ControlRequest.wLength = DeviceIDStringLength; + USB_ControlRequest.wLength = (DeviceIDStringLength - 1); if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful) return ErrorCode; - DeviceIDString->String[DeviceIDStringLength] = 0x00; + DeviceIDString[DeviceIDStringLength] = 0x00; return HOST_SENDCONTROL_Successful; } +/** Issues a Printer class Get Port Status command to the attached device, to retrieve the current status flags of the + * printer. + * + * \param[out] PortStatus Pointer to the destination where the printer's status flag values should be stored + * + * \return A value from the USB_Host_SendControlErrorCodes_t enum + */ uint8_t Printer_GetPortStatus(uint8_t* PortStatus) { USB_ControlRequest = (USB_Request_Header_t) @@ -77,6 +109,11 @@ uint8_t Printer_GetPortStatus(uint8_t* PortStatus) return USB_Host_SendControlRequest(PortStatus); } +/** Issues a Printer class Soft Reset command to the attached device, to reset the printer ready for new input without + * physically cycling the printer's power. + * + * \return A value from the USB_Host_SendControlErrorCodes_t enum + */ uint8_t Printer_SoftReset(void) { USB_ControlRequest = (USB_Request_Header_t) diff --git a/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.h b/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.h index e9c1d9fb9c..01f1f14082 100644 --- a/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.h +++ b/Demos/Host/Incomplete/PrinterHost/Lib/PrinterCommands.h @@ -33,27 +33,29 @@ /* Includes: */ #include + #include #include /* Macros: */ - #define PROTOCOL_UNIDIRECTIONAL 0x01 - #define PROTOCOL_BIDIRECTIONAL 0x02 - #define PROTOCOL_IEEE1284 0x03 - + /** Printer class-specific request to retrieve the printer's ID string */ #define GET_DEVICE_ID 0 + + /** Printer class-specific request to retrieve the printer's virtual port status flags */ #define GET_PORT_STATUS 1 + + /** Printer class-specific request to soft-reset the device */ #define SOFT_RESET 2 - /* Type Defines: */ - typedef struct - { - uint16_t Length; - uint8_t String[128]; - } Device_ID_String_t; + /** Pipe number of the Printer data IN pipe */ + #define PRINTER_DATA_IN_PIPE 1 + + /** Pipe number of the Printer data OUT pipe */ + #define PRINTER_DATA_OUT_PIPE 2 /* Function Prototypes: */ - uint8_t Printer_GetDeviceID(Device_ID_String_t* DeviceIDString); + uint8_t Printer_SendData(char* PrinterCommands); + uint8_t Printer_GetDeviceID(char* DeviceIDString, uint8_t BufferSize); uint8_t Printer_GetPortStatus(uint8_t* PortStatus); uint8_t Printer_SoftReset(void); diff --git a/Demos/Host/Incomplete/PrinterHost/PrinterHost.c b/Demos/Host/Incomplete/PrinterHost/PrinterHost.c index 643f919c93..ea179b6878 100644 --- a/Demos/Host/Incomplete/PrinterHost/PrinterHost.c +++ b/Demos/Host/Incomplete/PrinterHost/PrinterHost.c @@ -150,7 +150,7 @@ void USB_Printer_Host(void) } /* Some printers use alternate settings to determine the communication protocol used - if so, send a SetInterface - * request to switch to the interface alternate setting with the Bidirection protocol */ + * request to switch to the interface alternate setting with the Bidirectional protocol */ if (PrinterAltSetting) { USB_ControlRequest = (USB_Request_Header_t) @@ -181,8 +181,8 @@ void USB_Printer_Host(void) case HOST_STATE_Configured: puts_P(PSTR("Retrieving Device ID...\r\n")); - Device_ID_String_t DeviceIDString; - if ((ErrorCode = Printer_GetDeviceID(&DeviceIDString)) != HOST_SENDCONTROL_Successful) + char DeviceIDString[128]; + if ((ErrorCode = Printer_GetDeviceID(DeviceIDString, sizeof(DeviceIDString))) != HOST_SENDCONTROL_Successful) { puts_P(PSTR("Control Error (Get DeviceID).\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n"), ErrorCode); @@ -195,7 +195,7 @@ void USB_Printer_Host(void) break; } - printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString.String); + printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString); puts_P(PSTR("Printer Enumerated.\r\n")); @@ -205,30 +205,25 @@ void USB_Printer_Host(void) /* Indicate device busy via the status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_BUSY); - //-------------------------------------------------------------- - #define TEST_TEXT_PAGE "\033%-12345X\033E LUFA PCL Test Page \033E\033%-12345X" -// #define TEST_TEXT_PAGE "\033@\033i\001\033X\001\060\000\r\nLUFA ESCP/2 Test Page\r\n" - #define PAGE_SIZE (sizeof(TEST_TEXT_PAGE) - 1) + char PCL_Test_Page[] = "\033%-12345X\033E LUFA PCL Test Page \033E\033%-12345X"; +// char ESCP2_Test_Page[] = "\033@\033i\001\033X\001\060\000\r\nLUFA ESCP/2 Test Page\r\n"; - Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE); - Pipe_Unfreeze(); - - puts_P(PSTR("Waiting for Printer to Become Ready...\r\n")); - - while (!(Pipe_IsReadWriteAllowed())); + printf_P(PSTR("Sending Test Page (%d bytes)...\r\n"), strlen(PCL_Test_Page)); - printf_P(PSTR("Printer Write Allowed, Sending Page (%d bytes)...\r\n"), PAGE_SIZE); - - Pipe_Write_Stream_LE(TEST_TEXT_PAGE, PAGE_SIZE); - Pipe_ClearOUT(); + if ((ErrorCode = Printer_SendData(PCL_Test_Page)) != PIPE_RWSTREAM_NoError) + { + puts_P(PSTR("Error Sending Test Page.\r\n")); + printf_P(PSTR(" -- Error Code: %d\r\n"), ErrorCode); - puts_P(PSTR("Page Sent, Waiting for Pipe...\r\n")); + /* Indicate error via status LEDs */ + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); - while (!(Pipe_IsReadWriteAllowed())); - Pipe_Freeze(); + /* Wait until USB device disconnected */ + USB_HostState = HOST_STATE_WaitForDeviceRemoval; + break; + } - puts_P(PSTR("Pipe Frozen.\r\n")); - //-------------------------------------------------------------- + puts_P(PSTR("Test Page Sent, Waiting for Pipe...\r\n")); /* Indicate device no longer busy */ LEDs_SetAllLEDs(LEDMASK_USB_READY); diff --git a/Demos/Host/Incomplete/PrinterHost/PrinterHost.h b/Demos/Host/Incomplete/PrinterHost/PrinterHost.h index c0bbebfe39..5851349e4d 100644 --- a/Demos/Host/Incomplete/PrinterHost/PrinterHost.h +++ b/Demos/Host/Incomplete/PrinterHost/PrinterHost.h @@ -37,6 +37,7 @@ #include #include #include + #include #include "ConfigDescriptor.h" #include "Lib/PrinterCommands.h" diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 62997d73dd..04d5d09a68 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -49,7 +49,7 @@ * - Changed bootloaders to use FLASHEND rather than the existence of RAMPZ to determine if far FLASH pointers are needed to fix * bootloaders on some of the USB AVR devices where avr-libc erronously defines RAMPZ * - Fixes to MassStorageHost for better device compatibility (increase command timeout, change MassStore_WaitForDataReceived() - * to only unfreeze and check one data pipe at a time) to prevent incorrect enumerations and freezes + * to only unfreeze and check one data pipe at a time) to prevent incorrect device enumerations and freezes while trasferring data * - Make Pipe_ConfigurePipe() mask the given endpoint number against PIPE_EPNUM_MASK to ensure the endpoint IN direction bit is * cleared to prevent endpoint type corruption * - Fix documentation mentioning Pipe_GetCurrentToken() function when real name is Pipe_GetPipeToken()