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.
\r
/* Get the printer interface from the configuration descriptor */\r
if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,\r
- NextBidirectionalPrinterInterface)))\r
+ DComp_NextBidirectionalPrinterInterface)))\r
{\r
/* Descriptor not found, error out */\r
return NoInterfaceFound;\r
PrinterInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;\r
PrinterAltSetting = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).AlternateSetting;\r
\r
- /* Get the IN and OUT data endpoints for the mass storage interface */\r
+ /* Get the IN and OUT data endpoints for the printer interface */\r
while (FoundEndpoints != ((1 << PRINTER_DATA_OUT_PIPE) | (1 << PRINTER_DATA_IN_PIPE)))\r
{\r
/* Fetch the next bulk endpoint from the current printer interface */\r
if ((ErrorCode = USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,\r
- NextInterfaceBulkDataEndpoint)))\r
+ DComp_NextInterfaceBulkDataEndpoint)))\r
{\r
/* Descriptor not found, error out */\r
return NoEndpointFound;\r
return SuccessfulConfigRead;\r
}\r
\r
-uint8_t NextBidirectionalPrinterInterface(void* CurrentDescriptor)\r
+uint8_t DComp_NextBidirectionalPrinterInterface(void* CurrentDescriptor)\r
{\r
- /* PURPOSE: Find next Bidirectional protocol printer class interface descriptor */\r
+ /* PURPOSE: Find next bidirectional protocol printer class interface descriptor */\r
\r
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)\r
{\r
/* Check the descriptor class and protocol, break out if correct class/protocol interface found */\r
if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) &&\r
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) &&\r
- (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PROTOCOL_BIDIRECTIONAL))\r
+ (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL))\r
{\r
return DESCRIPTOR_SEARCH_Found;\r
}\r
return DESCRIPTOR_SEARCH_NotFound;\r
}\r
\r
-uint8_t NextInterfaceBulkDataEndpoint(void* CurrentDescriptor)\r
+uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor)\r
{\r
/* PURPOSE: Find next interface bulk endpoint descriptor before next interface descriptor */\r
\r
#include <LUFA/Drivers/USB/USB.h>\r
\r
#include "PrinterHost.h"\r
+ #include "Lib/PrinterCommands.h"\r
\r
/* Macros: */\r
+ /** Interface Class value for the Printer Device class */\r
#define PRINTER_CLASS 0x07\r
+\r
+ /** Interface Subclass value for the Printer Device class */\r
#define PRINTER_SUBCLASS 0x01\r
+\r
+ /** Interface Protocol value for a Bidirectional communication encapsulation */\r
+ #define PRINTER_PROTOCOL 0x02\r
\r
- #define PRINTER_DATA_OUT_PIPE 1\r
- #define PRINTER_DATA_IN_PIPE 2\r
- \r
+ /** Maximum size of a device configuration descriptor which can be processed by the host, in bytes */\r
#define MAX_CONFIG_DESCRIPTOR_SIZE 512\r
\r
/* Enums: */\r
+ /** Enum for the possible return codes of the ProcessConfigurationDescriptor() function. */\r
enum PrinterHost_GetConfigDescriptorDataCodes_t\r
{\r
- SuccessfulConfigRead = 0,\r
- ControlError = 1,\r
- DescriptorTooLarge = 2,\r
- InvalidConfigDataReturned = 3,\r
- NoInterfaceFound = 4,\r
- NoEndpointFound = 5,\r
+ SuccessfulConfigRead = 0, /**< Configuration Descriptor was processed successfully */\r
+ ControlError = 1, /**< A control request to the device failed to complete successfully */\r
+ DescriptorTooLarge = 2, /**< The device's Configuration Descriptor is too large to process */\r
+ InvalidConfigDataReturned = 3, /**< The device returned an invalid Configuration Descriptor */\r
+ NoInterfaceFound = 4, /**< A compatible printer interface was not found in the device's Configuration Descriptor */\r
+ NoEndpointFound = 5, /**< The printer data endpoints were not found in the device's Configuration Descriptor */\r
};\r
\r
/* External Variables: */\r
+ /** Interface index of the Bidirectional Printer interface within the device, once the Configuration\r
+ * Descriptor has been processed.\r
+ */\r
uint8_t PrinterInterfaceNumber;\r
+ \r
+ /** Interface Alternate Setting index of the Bidirectional Printer interface within the device, once\r
+ * the Configuration Descriptor has been processed.\r
+ */\r
uint8_t PrinterAltSetting;\r
\r
/* Function Prototypes: */\r
uint8_t ProcessConfigurationDescriptor(void); \r
\r
- uint8_t NextBidirectionalPrinterInterface(void* CurrentDescriptor);\r
- uint8_t NextInterfaceBulkDataEndpoint(void* CurrentDescriptor);\r
+ uint8_t DComp_NextBidirectionalPrinterInterface(void* CurrentDescriptor);\r
+ uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor);\r
\r
#endif\r
\r
#include "PrinterCommands.h"\r
\r
-uint8_t Printer_GetDeviceID(Device_ID_String_t* DeviceIDString)\r
+uint8_t Printer_SendData(char* PrinterCommands)\r
+{\r
+ uint8_t ErrorCode;\r
+\r
+ Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, strlen(PrinterCommands))) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+\r
+ Pipe_ClearOUT();\r
+ while (!(Pipe_IsOUTReady()));\r
+ \r
+ Pipe_Freeze();\r
+\r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a Printer class Get Device ID command to the attached device, to retrieve the device ID string (which indicates\r
+ * the accepted printer languages, the printer's model and other pertinent information).\r
+ *\r
+ * \param[out] DeviceIDString Pointer to the destination where the returned string should be stored\r
+ * \param[in] BufferSize Size in bytes of the allocated buffer for the returned Device ID string\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
+uint8_t Printer_GetDeviceID(char* DeviceIDString, uint8_t BufferSize)\r
{\r
uint8_t ErrorCode = HOST_SENDCONTROL_Successful;\r
uint16_t DeviceIDStringLength;\r
bRequest: GET_DEVICE_ID,\r
wValue: 0,\r
wIndex: 0,\r
- wLength: sizeof(DeviceIDString->Length),\r
+ wLength: sizeof(DeviceIDStringLength),\r
};\r
\r
- if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)\r
+ if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)\r
return ErrorCode;\r
\r
- DeviceIDStringLength = SwapEndian_16(DeviceIDString->Length);\r
+ DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);\r
\r
- /* Protect against overflow for the null terminator if the string length is equal to or larger than the buffer */\r
- if (DeviceIDStringLength >= sizeof(DeviceIDString->String))\r
- DeviceIDStringLength = sizeof(DeviceIDString->String) - 1;\r
+ if (DeviceIDStringLength > BufferSize)\r
+ DeviceIDStringLength = BufferSize;\r
\r
- USB_ControlRequest.wLength = DeviceIDStringLength;\r
+ USB_ControlRequest.wLength = (DeviceIDStringLength - 1);\r
\r
if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)\r
return ErrorCode;\r
\r
- DeviceIDString->String[DeviceIDStringLength] = 0x00;\r
+ DeviceIDString[DeviceIDStringLength] = 0x00;\r
\r
return HOST_SENDCONTROL_Successful;\r
}\r
\r
+/** Issues a Printer class Get Port Status command to the attached device, to retrieve the current status flags of the\r
+ * printer.\r
+ *\r
+ * \param[out] PortStatus Pointer to the destination where the printer's status flag values should be stored\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
uint8_t Printer_GetPortStatus(uint8_t* PortStatus)\r
{\r
USB_ControlRequest = (USB_Request_Header_t)\r
return USB_Host_SendControlRequest(PortStatus);\r
}\r
\r
+/** Issues a Printer class Soft Reset command to the attached device, to reset the printer ready for new input without\r
+ * physically cycling the printer's power.\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
uint8_t Printer_SoftReset(void)\r
{\r
USB_ControlRequest = (USB_Request_Header_t)\r
\r
/* Includes: */\r
#include <avr/io.h>\r
+ #include <string.h>\r
\r
#include <LUFA/Drivers/USB/USB.h>\r
\r
/* Macros: */\r
- #define PROTOCOL_UNIDIRECTIONAL 0x01\r
- #define PROTOCOL_BIDIRECTIONAL 0x02\r
- #define PROTOCOL_IEEE1284 0x03\r
- \r
+ /** Printer class-specific request to retrieve the printer's ID string */\r
#define GET_DEVICE_ID 0\r
+\r
+ /** Printer class-specific request to retrieve the printer's virtual port status flags */\r
#define GET_PORT_STATUS 1\r
+\r
+ /** Printer class-specific request to soft-reset the device */\r
#define SOFT_RESET 2\r
\r
- /* Type Defines: */\r
- typedef struct\r
- {\r
- uint16_t Length;\r
- uint8_t String[128];\r
- } Device_ID_String_t;\r
+ /** Pipe number of the Printer data IN pipe */\r
+ #define PRINTER_DATA_IN_PIPE 1\r
+\r
+ /** Pipe number of the Printer data OUT pipe */\r
+ #define PRINTER_DATA_OUT_PIPE 2\r
\r
/* Function Prototypes: */\r
- uint8_t Printer_GetDeviceID(Device_ID_String_t* DeviceIDString);\r
+ uint8_t Printer_SendData(char* PrinterCommands);\r
+ uint8_t Printer_GetDeviceID(char* DeviceIDString, uint8_t BufferSize);\r
uint8_t Printer_GetPortStatus(uint8_t* PortStatus);\r
uint8_t Printer_SoftReset(void);\r
\r
}\r
\r
/* Some printers use alternate settings to determine the communication protocol used - if so, send a SetInterface\r
- * request to switch to the interface alternate setting with the Bidirection protocol */\r
+ * request to switch to the interface alternate setting with the Bidirectional protocol */\r
if (PrinterAltSetting)\r
{\r
USB_ControlRequest = (USB_Request_Header_t)\r
case HOST_STATE_Configured:\r
puts_P(PSTR("Retrieving Device ID...\r\n"));\r
\r
- Device_ID_String_t DeviceIDString;\r
- if ((ErrorCode = Printer_GetDeviceID(&DeviceIDString)) != HOST_SENDCONTROL_Successful)\r
+ char DeviceIDString[128];\r
+ if ((ErrorCode = Printer_GetDeviceID(DeviceIDString, sizeof(DeviceIDString))) != HOST_SENDCONTROL_Successful)\r
{\r
puts_P(PSTR("Control Error (Get DeviceID).\r\n"));\r
printf_P(PSTR(" -- Error Code: %d\r\n"), ErrorCode);\r
break;\r
}\r
\r
- printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString.String);\r
+ printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString);\r
\r
puts_P(PSTR("Printer Enumerated.\r\n"));\r
\r
/* Indicate device busy via the status LEDs */\r
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
- //--------------------------------------------------------------\r
- #define TEST_TEXT_PAGE "\033%-12345X\033E LUFA PCL Test Page \033E\033%-12345X"\r
-// #define TEST_TEXT_PAGE "\033@\033i\001\033X\001\060\000\r\nLUFA ESCP/2 Test Page\r\n"\r
- #define PAGE_SIZE (sizeof(TEST_TEXT_PAGE) - 1)\r
+ char PCL_Test_Page[] = "\033%-12345X\033E LUFA PCL Test Page \033E\033%-12345X";\r
+// char ESCP2_Test_Page[] = "\033@\033i\001\033X\001\060\000\r\nLUFA ESCP/2 Test Page\r\n";\r
\r
- Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- puts_P(PSTR("Waiting for Printer to Become Ready...\r\n"));\r
- \r
- while (!(Pipe_IsReadWriteAllowed()));\r
+ printf_P(PSTR("Sending Test Page (%d bytes)...\r\n"), strlen(PCL_Test_Page));\r
\r
- printf_P(PSTR("Printer Write Allowed, Sending Page (%d bytes)...\r\n"), PAGE_SIZE);\r
- \r
- Pipe_Write_Stream_LE(TEST_TEXT_PAGE, PAGE_SIZE);\r
- Pipe_ClearOUT();\r
+ if ((ErrorCode = Printer_SendData(PCL_Test_Page)) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ puts_P(PSTR("Error Sending Test Page.\r\n"));\r
+ printf_P(PSTR(" -- Error Code: %d\r\n"), ErrorCode);\r
\r
- puts_P(PSTR("Page Sent, Waiting for Pipe...\r\n"));\r
+ /* Indicate error via status LEDs */\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
\r
- while (!(Pipe_IsReadWriteAllowed()));\r
- Pipe_Freeze(); \r
+ /* Wait until USB device disconnected */\r
+ USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
+ break;\r
+ }\r
\r
- puts_P(PSTR("Pipe Frozen.\r\n"));\r
- //--------------------------------------------------------------\r
+ puts_P(PSTR("Test Page Sent, Waiting for Pipe...\r\n"));\r
\r
/* Indicate device no longer busy */\r
LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
#include <avr/pgmspace.h>\r
#include <avr/power.h>\r
#include <stdio.h>\r
+ #include <string.h>\r
\r
#include "ConfigDescriptor.h"\r
#include "Lib/PrinterCommands.h"\r
* - Changed bootloaders to use FLASHEND rather than the existence of RAMPZ to determine if far FLASH pointers are needed to fix\r
* bootloaders on some of the USB AVR devices where avr-libc erronously defines RAMPZ\r
* - Fixes to MassStorageHost for better device compatibility (increase command timeout, change MassStore_WaitForDataReceived()\r
- * to only unfreeze and check one data pipe at a time) to prevent incorrect enumerations and freezes\r
+ * to only unfreeze and check one data pipe at a time) to prevent incorrect device enumerations and freezes while trasferring data\r
* - Make Pipe_ConfigurePipe() mask the given endpoint number against PIPE_EPNUM_MASK to ensure the endpoint IN direction bit is\r
* cleared to prevent endpoint type corruption\r
* - Fix documentation mentioning Pipe_GetCurrentToken() function when real name is Pipe_GetPipeToken()\r