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.
This commit is contained in:
		
							parent
							
								
									d3fb6273aa
								
							
						
					
					
						commit
						786479faf0
					
				
					 7 changed files with 110 additions and 62 deletions
				
			
		| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,35 +35,48 @@
 | 
			
		|||
		#include <LUFA/Drivers/USB/USB.h>
 | 
			
		||||
		
 | 
			
		||||
		#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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,27 +33,29 @@
 | 
			
		|||
 | 
			
		||||
	/* Includes: */
 | 
			
		||||
		#include <avr/io.h>
 | 
			
		||||
		#include <string.h>
 | 
			
		||||
 | 
			
		||||
		#include <LUFA/Drivers/USB/USB.h>
 | 
			
		||||
 | 
			
		||||
	/* 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);
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@
 | 
			
		|||
		#include <avr/pgmspace.h>
 | 
			
		||||
		#include <avr/power.h>
 | 
			
		||||
		#include <stdio.h>
 | 
			
		||||
		#include <string.h>
 | 
			
		||||
 | 
			
		||||
		#include "ConfigDescriptor.h"
 | 
			
		||||
		#include "Lib/PrinterCommands.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue