Merge commit '60b30c0363' as 'lib/lufa'
				
					
				
			This commit is contained in:
		
						commit
						8655d4f494
					
				
					 1455 changed files with 394541 additions and 0 deletions
				
			
		
							
								
								
									
										197
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,197 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_AUDIO_DRIVER | ||||
| #define  __INCLUDE_FROM_AUDIO_DEVICE_C | ||||
| #include "AudioClassDevice.h" | ||||
| 
 | ||||
| void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||||
| 	{ | ||||
| 		uint8_t InterfaceIndex = (USB_ControlRequest.wIndex & 0xFF); | ||||
| 
 | ||||
| 		if ((InterfaceIndex != AudioInterfaceInfo->Config.ControlInterfaceNumber) && | ||||
| 		    (InterfaceIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||||
| 	{ | ||||
| 		uint8_t EndpointAddress = (USB_ControlRequest.wIndex & 0xFF); | ||||
| 
 | ||||
| 		if ((EndpointAddress != AudioInterfaceInfo->Config.DataINEndpoint.Address) && | ||||
| 		    (EndpointAddress != AudioInterfaceInfo->Config.DataOUTEndpoint.Address)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case REQ_SetInterface: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0); | ||||
| 				EVENT_Audio_Device_StreamStartStop(AudioInterfaceInfo); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case AUDIO_REQ_GetStatus: | ||||
| 			if ((USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) || | ||||
| 			    (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT))) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case AUDIO_REQ_SetCurrent: | ||||
| 		case AUDIO_REQ_SetMinimum: | ||||
| 		case AUDIO_REQ_SetMaximum: | ||||
| 		case AUDIO_REQ_SetResolution: | ||||
| 			if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||||
| 			{ | ||||
| 				uint8_t EndpointProperty = USB_ControlRequest.bRequest; | ||||
| 				uint8_t EndpointAddress  = (uint8_t)USB_ControlRequest.wIndex; | ||||
| 				uint8_t EndpointControl  = (USB_ControlRequest.wValue >> 8); | ||||
| 
 | ||||
| 				if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||||
| 				                                                 EndpointControl, NULL, NULL)) | ||||
| 				{ | ||||
| 					uint16_t ValueLength = USB_ControlRequest.wLength; | ||||
| 					uint8_t  Value[ValueLength]; | ||||
| 
 | ||||
| 					Endpoint_ClearSETUP(); | ||||
| 					Endpoint_Read_Control_Stream_LE(Value, ValueLength); | ||||
| 					Endpoint_ClearIN(); | ||||
| 
 | ||||
| 					CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||||
| 					                                             EndpointControl, &ValueLength, Value); | ||||
| 				} | ||||
| 			} | ||||
| 			else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||||
| 			{ | ||||
| 				uint8_t  Property  = USB_ControlRequest.bRequest; | ||||
| 				uint8_t  Entity    = (USB_ControlRequest.wIndex >> 8); | ||||
| 				uint16_t Parameter = USB_ControlRequest.wValue; | ||||
| 
 | ||||
| 				if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||||
| 				                                                  Parameter, NULL, NULL)) | ||||
| 				{ | ||||
| 					uint16_t ValueLength = USB_ControlRequest.wLength; | ||||
| 					uint8_t  Value[ValueLength]; | ||||
| 
 | ||||
| 					Endpoint_ClearSETUP(); | ||||
| 					Endpoint_Read_Control_Stream_LE(Value, ValueLength); | ||||
| 					Endpoint_ClearIN(); | ||||
| 
 | ||||
| 					CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||||
| 				                                                  Parameter, &ValueLength, Value); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case AUDIO_REQ_GetCurrent: | ||||
| 		case AUDIO_REQ_GetMinimum: | ||||
| 		case AUDIO_REQ_GetMaximum: | ||||
| 		case AUDIO_REQ_GetResolution: | ||||
| 			if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||||
| 			{ | ||||
| 				uint8_t  EndpointProperty = USB_ControlRequest.bRequest; | ||||
| 				uint8_t  EndpointAddress  = (uint8_t)USB_ControlRequest.wIndex; | ||||
| 				uint8_t  EndpointControl  = (USB_ControlRequest.wValue >> 8); | ||||
| 				uint16_t ValueLength      = USB_ControlRequest.wLength; | ||||
| 				uint8_t  Value[ValueLength]; | ||||
| 
 | ||||
| 				if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||||
| 				                                                 EndpointControl, &ValueLength, Value)) | ||||
| 				{ | ||||
| 					Endpoint_ClearSETUP(); | ||||
| 					Endpoint_Write_Control_Stream_LE(Value, ValueLength); | ||||
| 					Endpoint_ClearOUT(); | ||||
| 				} | ||||
| 			} | ||||
| 			else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||||
| 			{ | ||||
| 				uint8_t  Property    = USB_ControlRequest.bRequest; | ||||
| 				uint8_t  Entity      = (USB_ControlRequest.wIndex >> 8); | ||||
| 				uint16_t Parameter   = USB_ControlRequest.wValue; | ||||
| 				uint16_t ValueLength = USB_ControlRequest.wLength; | ||||
| 				uint8_t  Value[ValueLength]; | ||||
| 
 | ||||
| 				if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||||
| 				                                                  Parameter, &ValueLength, Value)) | ||||
| 				{ | ||||
| 					Endpoint_ClearSETUP(); | ||||
| 					Endpoint_Write_Control_Stream_LE(Value, ValueLength); | ||||
| 					Endpoint_ClearOUT(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| { | ||||
| 	memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); | ||||
| 
 | ||||
| 	AudioInterfaceInfo->Config.DataINEndpoint.Type  = EP_TYPE_ISOCHRONOUS; | ||||
| 	AudioInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_ISOCHRONOUS; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void Audio_Device_Event_Stub(void) | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										396
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										396
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,396 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB Audio 1.0 Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB Audio 1.0 Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassAudio
 | ||||
|  *  \defgroup Group_USBClassAudioDevice Audio 1.0 Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassAudioDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassAudioDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _AUDIO_CLASS_DEVICE_H_ | ||||
| #define _AUDIO_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/AudioClassCommon.h" | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_AUDIO_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief Audio Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each Audio interface | ||||
| 			 *  within the user application, and passed to each of the Audio class driver functions as the | ||||
| 			 *  \c AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t  ControlInterfaceNumber; /**< Index of the Audio Control interface within the device this
 | ||||
| 					                                  *   structure controls. | ||||
| 					                                  */ | ||||
| 					uint8_t  StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this
 | ||||
| 														*   structure controls. | ||||
| 														*/ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					bool InterfaceEnabled; /**< Set and cleared by the class driver to indicate if the host has enabled the streaming endpoints
 | ||||
| 					                        *   of the Audio Streaming interface. | ||||
| 					                        */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_Audio_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given Audio interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the | ||||
| 			 *  given Audio interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 */ | ||||
| 			void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Audio class driver callback for the setting and retrieval of streaming endpoint properties. This callback must be implemented
 | ||||
| 			 *  in the user application to handle property manipulations on streaming audio endpoints. | ||||
| 			 * | ||||
| 			 *  When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for | ||||
| 			 *  the given endpoint index, and should return as fast as possible. When non-NULL, this value may be altered for GET operations | ||||
| 			 *  to indicate the size of the retrieved data. | ||||
| 			 * | ||||
| 			 *  \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value | ||||
| 			 *        of the \c DataLength parameter. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 *  \param[in]     EndpointProperty    Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t. | ||||
| 			 *  \param[in]     EndpointAddress     Address of the streaming endpoint whose property is being referenced. | ||||
| 			 *  \param[in]     EndpointControl     Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t. | ||||
| 			 *  \param[in,out] DataLength          For SET operations, the length of the parameter data to set. For GET operations, the maximum | ||||
| 			 *                                     length of the retrieved data. When NULL, the function should return whether the given property | ||||
| 			 *                                     and parameter is valid for the requested endpoint without reading or modifying the Data buffer. | ||||
| 			 *  \param[in,out] Data                Pointer to a location where the parameter data is stored for SET operations, or where | ||||
| 			 *                                     the retrieved data is to be stored for GET operations. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the property GET/SET was successful, \c false otherwise | ||||
| 			 */ | ||||
| 			bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                                  const uint8_t EndpointProperty, | ||||
| 			                                                  const uint8_t EndpointAddress, | ||||
| 			                                                  const uint8_t EndpointControl, | ||||
| 			                                                  uint16_t* const DataLength, | ||||
| 			                                                  uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Audio class driver callback for the setting and retrieval of streaming interface properties. This callback must be implemented
 | ||||
| 			 *  in the user application to handle property manipulations on streaming audio interfaces. | ||||
| 			 * | ||||
| 			 *  When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for | ||||
| 			 *  the given entity and should return as fast as possible. When non-NULL, this value may be altered for GET operations | ||||
| 			 *  to indicate the size of the retrieved data. | ||||
| 			 * | ||||
| 			 *  \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value | ||||
| 			 *        of the \c DataLength parameter. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 *  \param[in]     Property            Property of the interface to get or set, a value from \ref Audio_ClassRequests_t. | ||||
| 			 *  \param[in]     EntityAddress       Address of the audio entity whose property is being referenced. | ||||
| 			 *  \param[in]     Parameter           Parameter of the entity to get or set, specific to each type of entity (see USB Audio specification). | ||||
| 			 *  \param[in,out] DataLength          For SET operations, the length of the parameter data to set. For GET operations, the maximum | ||||
| 			 *                                     length of the retrieved data. When NULL, the function should return whether the given property | ||||
| 			 *                                     and parameter is valid for the requested endpoint without reading or modifying the Data buffer. | ||||
| 			 *  \param[in,out] Data                Pointer to a location where the parameter data is stored for SET operations, or where | ||||
| 			 *                                     the retrieved data is to be stored for GET operations. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the property GET/SET was successful, \c false otherwise | ||||
| 			 */ | ||||
| 			bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                                   const uint8_t Property, | ||||
| 			                                                   const uint8_t EntityAddress, | ||||
| 			                                                   const uint16_t Parameter, | ||||
| 			                                                   uint16_t* const DataLength, | ||||
| 			                                                   uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Audio class driver event for an Audio Stream start/stop change. This event fires each time the device receives a stream enable or
 | ||||
| 			 *  disable control request from the host, to start and stop the audio stream. The current state of the stream can be determined by the | ||||
| 			 *  State.InterfaceEnabled value inside the Audio interface structure passed as a parameter. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 */ | ||||
| 			void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo); | ||||
| 
 | ||||
| 		/* Inline Functions: */ | ||||
| 			/** General management task for a given Audio class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 */ | ||||
| 			static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                        ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				(void)AudioInterfaceInfo; | ||||
| 			} | ||||
| 
 | ||||
| 			/** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming
 | ||||
| 			 *  OUT endpoint ready for reading. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the given Audio interface has a sample to be read, \c false otherwise. | ||||
| 			 */ | ||||
| 			static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                                 ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled)) | ||||
| 				  return false; | ||||
| 
 | ||||
| 				Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 				return Endpoint_IsOUTReceived(); | ||||
| 			} | ||||
| 
 | ||||
| 			/** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
 | ||||
| 			 *  the streaming IN endpoint ready for writing. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the given Audio interface is ready to accept the next sample, \c false otherwise. | ||||
| 			 */ | ||||
| 			static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                                     ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled)) | ||||
| 				  return false; | ||||
| 
 | ||||
| 				Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 				return Endpoint_IsINReady(); | ||||
| 			} | ||||
| 
 | ||||
| 			/** Reads the next 8-bit audio sample from the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||||
| 			 *       that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return  Signed 8-bit audio sample from the audio interface. | ||||
| 			 */ | ||||
| 			static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                              ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				int8_t Sample; | ||||
| 
 | ||||
| 				(void)AudioInterfaceInfo; | ||||
| 
 | ||||
| 				Sample = Endpoint_Read_8(); | ||||
| 
 | ||||
| 				if (!(Endpoint_BytesInEndpoint())) | ||||
| 				  Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 				return Sample; | ||||
| 			} | ||||
| 
 | ||||
| 			/** Reads the next 16-bit audio sample from the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||||
| 			 *       that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return  Signed 16-bit audio sample from the audio interface. | ||||
| 			 */ | ||||
| 			static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                                ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				int16_t Sample; | ||||
| 
 | ||||
| 				(void)AudioInterfaceInfo; | ||||
| 
 | ||||
| 				Sample = (int16_t)Endpoint_Read_16_LE(); | ||||
| 
 | ||||
| 				if (!(Endpoint_BytesInEndpoint())) | ||||
| 				  Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 				return Sample; | ||||
| 			} | ||||
| 
 | ||||
| 			/** Reads the next 24-bit audio sample from the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||||
| 			 *       that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Signed 24-bit audio sample from the audio interface. | ||||
| 			 */ | ||||
| 			static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			                                                ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 			{ | ||||
| 				int32_t Sample; | ||||
| 
 | ||||
| 				(void)AudioInterfaceInfo; | ||||
| 
 | ||||
| 				Sample = (((uint32_t)Endpoint_Read_8() << 16) | Endpoint_Read_16_LE()); | ||||
| 
 | ||||
| 				if (!(Endpoint_BytesInEndpoint())) | ||||
| 				  Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 				return Sample; | ||||
| 			} | ||||
| 
 | ||||
| 			/** Writes the next 8-bit audio sample to the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||||
| 			 *       ensure that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 *  \param[in]     Sample              Signed 8-bit audio sample. | ||||
| 			 */ | ||||
| 			static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                             const int8_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                             const int8_t Sample) | ||||
| 			{ | ||||
| 				Endpoint_Write_8(Sample); | ||||
| 
 | ||||
| 				if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||||
| 				  Endpoint_ClearIN(); | ||||
| 			} | ||||
| 
 | ||||
| 			/** Writes the next 16-bit audio sample to the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||||
| 			 *       ensure that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 *  \param[in]     Sample              Signed 16-bit audio sample. | ||||
| 			 */ | ||||
| 			static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                              const int16_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                              const int16_t Sample) | ||||
| 			{ | ||||
| 				Endpoint_Write_16_LE(Sample); | ||||
| 
 | ||||
| 				if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||||
| 				  Endpoint_ClearIN(); | ||||
| 			} | ||||
| 
 | ||||
| 			/** Writes the next 24-bit audio sample to the current audio interface.
 | ||||
| 			 * | ||||
| 			 *  \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||||
| 			 *       ensure that the correct endpoint is selected and ready for data. | ||||
| 			 * | ||||
| 			 *  \param[in,out] AudioInterfaceInfo  Pointer to a structure containing an Audio Class configuration and state. | ||||
| 			 *  \param[in]     Sample              Signed 24-bit audio sample. | ||||
| 			 */ | ||||
| 			static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                              const int32_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||||
| 			static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||||
| 			                                              const int32_t Sample) | ||||
| 			{ | ||||
| 				Endpoint_Write_16_LE(Sample); | ||||
| 				Endpoint_Write_8(Sample >> 16); | ||||
| 
 | ||||
| 				if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||||
| 				  Endpoint_ClearIN(); | ||||
| 			} | ||||
| 
 | ||||
| 	/* Private Interface - For use in library only: */ | ||||
| 	#if !defined(__DOXYGEN__) | ||||
| 		/* Function Prototypes: */ | ||||
| 			#if defined(__INCLUDE_FROM_AUDIO_DEVICE_C) | ||||
| 				void Audio_Device_Event_Stub(void) ATTR_CONST; | ||||
| 
 | ||||
| 				void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||||
| 				                                        ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(Audio_Device_Event_Stub); | ||||
| 			#endif | ||||
| 
 | ||||
| 	#endif | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										362
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,362 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_CDC_DRIVER | ||||
| #define  __INCLUDE_FROM_CDC_DEVICE_C | ||||
| #include "CDCClassDevice.h" | ||||
| 
 | ||||
| void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber) | ||||
| 	  return; | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case CDC_REQ_GetLineEncoding: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 
 | ||||
| 				while (!(Endpoint_IsINReady())); | ||||
| 
 | ||||
| 				Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS); | ||||
| 				Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat); | ||||
| 				Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType); | ||||
| 				Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits); | ||||
| 
 | ||||
| 				Endpoint_ClearIN(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case CDC_REQ_SetLineEncoding: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 
 | ||||
| 				while (!(Endpoint_IsOUTReceived())) | ||||
| 				{ | ||||
| 					if (USB_DeviceState == DEVICE_STATE_Unattached) | ||||
| 					  return; | ||||
| 				} | ||||
| 
 | ||||
| 				CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE(); | ||||
| 				CDCInterfaceInfo->State.LineEncoding.CharFormat  = Endpoint_Read_8(); | ||||
| 				CDCInterfaceInfo->State.LineEncoding.ParityType  = Endpoint_Read_8(); | ||||
| 				CDCInterfaceInfo->State.LineEncoding.DataBits    = Endpoint_Read_8(); | ||||
| 
 | ||||
| 				Endpoint_ClearOUT(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case CDC_REQ_SetControlLineState: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue; | ||||
| 
 | ||||
| 				EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case CDC_REQ_SendBreak: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); | ||||
| 
 | ||||
| 	CDCInterfaceInfo->Config.DataINEndpoint.Type       = EP_TYPE_BULK; | ||||
| 	CDCInterfaceInfo->Config.DataOUTEndpoint.Type      = EP_TYPE_BULK; | ||||
| 	CDCInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return; | ||||
| 
 | ||||
| 	#if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsINReady()) | ||||
| 	  CDC_Device_Flush(CDCInterfaceInfo); | ||||
| 	#endif | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                               const char* const String) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_Stream_LE(String, strlen(String), NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_SendString_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                               const char* const String) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_PStream_LE(String, strlen_P(String), NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                             const void* const Buffer, | ||||
|                             const uint16_t Length) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_Stream_LE(Buffer, Length, NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_SendData_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                             const void* const Buffer, | ||||
|                             const uint16_t Length) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_PStream_LE(Buffer, Length, NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                             const uint8_t Data) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 	{ | ||||
| 		Endpoint_ClearIN(); | ||||
| 
 | ||||
| 		uint8_t ErrorCode; | ||||
| 
 | ||||
| 		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 		  return ErrorCode; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_Write_8(Data); | ||||
| 	return ENDPOINT_READYWAIT_NoError; | ||||
| } | ||||
| 
 | ||||
| uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	uint8_t ErrorCode; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (!(Endpoint_BytesInEndpoint())) | ||||
| 	  return ENDPOINT_READYWAIT_NoError; | ||||
| 
 | ||||
| 	bool BankFull = !(Endpoint_IsReadWriteAllowed()); | ||||
| 
 | ||||
| 	Endpoint_ClearIN(); | ||||
| 
 | ||||
| 	if (BankFull) | ||||
| 	{ | ||||
| 		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 		  return ErrorCode; | ||||
| 
 | ||||
| 		Endpoint_ClearIN(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ENDPOINT_READYWAIT_NoError; | ||||
| } | ||||
| 
 | ||||
| uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return 0; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsOUTReceived()) | ||||
| 	{ | ||||
| 		if (!(Endpoint_BytesInEndpoint())) | ||||
| 		{ | ||||
| 			Endpoint_ClearOUT(); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return Endpoint_BytesInEndpoint(); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return -1; | ||||
| 
 | ||||
| 	int16_t ReceivedByte = -1; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsOUTReceived()) | ||||
| 	{ | ||||
| 		if (Endpoint_BytesInEndpoint()) | ||||
| 		  ReceivedByte = Endpoint_Read_8(); | ||||
| 
 | ||||
| 		if (!(Endpoint_BytesInEndpoint())) | ||||
| 		  Endpoint_ClearOUT(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| 
 | ||||
| void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||||
| 	  return; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpoint.Address); | ||||
| 
 | ||||
| 	USB_Request_Header_t Notification = (USB_Request_Header_t) | ||||
| 		{ | ||||
| 			.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), | ||||
| 			.bRequest      = CDC_NOTIF_SerialState, | ||||
| 			.wValue        = CPU_TO_LE16(0), | ||||
| 			.wIndex        = CPU_TO_LE16(0), | ||||
| 			.wLength       = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)), | ||||
| 		}; | ||||
| 
 | ||||
| 	Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL); | ||||
| 	Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost, | ||||
| 	                         sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), | ||||
| 	                         NULL); | ||||
| 	Endpoint_ClearIN(); | ||||
| } | ||||
| 
 | ||||
| #if defined(FDEV_SETUP_STREAM) | ||||
| void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                              FILE* const Stream) | ||||
| { | ||||
| 	*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW); | ||||
| 	fdev_set_udata(Stream, CDCInterfaceInfo); | ||||
| } | ||||
| 
 | ||||
| void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
|                                      FILE* const Stream) | ||||
| { | ||||
| 	*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW); | ||||
| 	fdev_set_udata(Stream, CDCInterfaceInfo); | ||||
| } | ||||
| 
 | ||||
| static int CDC_Device_putchar(char c, | ||||
|                               FILE* Stream) | ||||
| { | ||||
| 	return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0; | ||||
| } | ||||
| 
 | ||||
| static int CDC_Device_getchar(FILE* Stream) | ||||
| { | ||||
| 	int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream)); | ||||
| 
 | ||||
| 	if (ReceivedByte < 0) | ||||
| 	  return _FDEV_EOF; | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| 
 | ||||
| static int CDC_Device_getchar_Blocking(FILE* Stream) | ||||
| { | ||||
| 	int16_t ReceivedByte; | ||||
| 
 | ||||
| 	while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0) | ||||
| 	{ | ||||
| 		if (USB_DeviceState == DEVICE_STATE_Unattached) | ||||
| 		  return _FDEV_EOF; | ||||
| 
 | ||||
| 		CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream)); | ||||
| 		USB_USBTask(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void CDC_Device_Event_Stub(void) | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										386
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,386 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB CDC Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB CDC Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassCDC
 | ||||
|  *  \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassCDCDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassCDCDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the CDC USB Class driver. | ||||
|  * | ||||
|  *  \note There are several major drawbacks to the CDC-ACM standard USB class, however | ||||
|  *        it is very standardized and thus usually available as a built-in driver on | ||||
|  *        most platforms, and so is a better choice than a proprietary serial class. | ||||
|  * | ||||
|  *        One major issue with CDC-ACM is that it requires two Interface descriptors, | ||||
|  *        which will upset most hosts when part of a multi-function "Composite" USB | ||||
|  *        device. This is because each interface will be loaded into a separate driver | ||||
|  *        instance, causing the two interfaces be become unlinked. To prevent this, you | ||||
|  *        should use the "Interface Association Descriptor" addendum to the USB 2.0 standard | ||||
|  *        which is available on most OSes when creating Composite devices. | ||||
|  * | ||||
|  *        Another major oversight is that there is no mechanism for the host to notify the | ||||
|  *        device that there is a data sink on the host side ready to accept data. This | ||||
|  *        means that the device may try to send data while the host isn't listening, causing | ||||
|  *        lengthy blocking timeouts in the transmission routines. It is thus highly recommended | ||||
|  *        that the virtual serial line DTR (Data Terminal Ready) signal be used where possible | ||||
|  *        to determine if a host application is ready for data. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _CDC_CLASS_DEVICE_H_ | ||||
| #define _CDC_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/CDCClassCommon.h" | ||||
| 
 | ||||
| 		#include <stdio.h> | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_CDC_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief CDC Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each CDC interface | ||||
| 			 *  within the user application, and passed to each of the CDC class driver functions as the | ||||
| 			 *  CDCInterfaceInfo parameter. This stores each CDC interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					struct | ||||
| 					{ | ||||
| 						uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
 | ||||
| 											    *   masks. This value is updated each time \ref CDC_Device_USBTask() is called. | ||||
| 											    */ | ||||
| 						uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_*
 | ||||
| 											    *   masks - to notify the host of changes to these values, call the | ||||
| 											    *   \ref CDC_Device_SendControlLineStateChange() function. | ||||
| 											    */ | ||||
| 					} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */ | ||||
| 
 | ||||
| 					CDC_LineEncoding_t LineEncoding; /**< Line encoding used in the virtual serial port, for the device's information.
 | ||||
| 					                                  *   This is generally only used if the virtual serial port data is to be | ||||
| 					                                  *   reconstructed on a physical UART. | ||||
| 					                                  */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_CDC_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given CDC interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing | ||||
| 			 *  the given CDC interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 */ | ||||
| 			void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given CDC class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 */ | ||||
| 			void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a
 | ||||
| 			 *  line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the | ||||
| 			 *  user program by declaring a handler function with the same name and parameters listed here. The new line encoding | ||||
| 			 *  settings are available in the \c LineEncoding structure inside the CDC interface structure passed as a parameter. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 */ | ||||
| 			void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a
 | ||||
| 			 *  control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the | ||||
| 			 *  user program by declaring a handler function with the same name and parameters listed here. The new control line states | ||||
| 			 *  are available in the \c ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as | ||||
| 			 *  a mask of \c CDC_CONTROL_LINE_OUT_* masks. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 */ | ||||
| 			void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** CDC class driver event for a send break request sent to the device from the host. This is generally used to separate
 | ||||
| 			 *  data or to indicate a special condition to the receiving device. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     Duration          Duration of the break that has been sent by the host, in milliseconds. | ||||
| 			 */ | ||||
| 			void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                                const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is
 | ||||
| 			 *  called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank | ||||
| 			 *  becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows | ||||
| 			 *  for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     Buffer            Pointer to a buffer containing the data to send to the device. | ||||
| 			 *  \param[in]     Length            Length of the data to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                            const void* const Buffer, | ||||
| 			                            const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given data buffer from PROGMEM space to the attached USB host, if connected. If a host is not connected when the
 | ||||
| 			 *  function is called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint | ||||
| 			 *  bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows | ||||
| 			 *  for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     Buffer            Pointer to a buffer containing the data to send to the device. | ||||
| 			 *  \param[in]     Length            Length of the data to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_SendData_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                            const void* const Buffer, | ||||
| 			                            const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when
 | ||||
| 			 *  the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||||
| 			 *  the endpoint bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to | ||||
| 			 *  the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     String            Pointer to the null terminated string to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                              const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given null terminated string from PROGMEM space to the attached USB host, if connected. If a host is not connected
 | ||||
| 			 *  when the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||||
| 			 *  the endpoint bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to | ||||
| 			 *  the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     String            Pointer to the null terminated string to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_SendString_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                              const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
 | ||||
| 			 *  byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the | ||||
| 			 *  \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be | ||||
| 			 *  packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in]     Data              Byte of data to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                            const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Determines the number of bytes received by the CDC interface from the host, waiting to be read. This indicates the number
 | ||||
| 			 *  of bytes in the OUT endpoint bank only, and thus the number of calls to \ref CDC_Device_ReceiveByte() which are guaranteed to | ||||
| 			 *  succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint | ||||
| 			 *  bank will not be released back to the USB controller until all bytes are read. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Total number of buffered bytes received from the host. | ||||
| 			 */ | ||||
| 			uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
 | ||||
| 			 *  returns a negative value. The \ref CDC_Device_BytesReceived() function may be queried in advance to determine how many | ||||
| 			 *  bytes are currently buffered in the CDC interface's data receive endpoint bank, and thus how many repeated calls to this | ||||
| 			 *  function which are guaranteed to succeed. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Next received byte from the host, or a negative value if no data received. | ||||
| 			 */ | ||||
| 			int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
 | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial
 | ||||
| 			 *  control lines (DCD, DSR, etc.) have changed states, or to give BREAK notifications to the host. Line states persist | ||||
| 			 *  until they are cleared via a second notification. This should be called each time the CDC class driver's | ||||
| 			 *  \c ControlLineStates.DeviceToHost value is updated to push the new states to the USB host. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 */ | ||||
| 			void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			#if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__) | ||||
| 			/** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular
 | ||||
| 			 *  functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created | ||||
| 			 *  stream is bidirectional and can be used for both input and output functions. | ||||
| 			 * | ||||
| 			 *  Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single | ||||
| 			 *  fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may | ||||
| 			 *  be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own | ||||
| 			 *  line buffering. | ||||
| 			 * | ||||
| 			 *  \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions | ||||
| 			 *        to the given CDC interface. | ||||
| 			 *        \n\n | ||||
| 			 * | ||||
| 			 *  \note This function is not available on all microcontroller architectures. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in,out] Stream            Pointer to a FILE structure where the created stream should be placed. | ||||
| 			 */ | ||||
| 			void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                             FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Identical to \ref CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
 | ||||
| 			 *  the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications. | ||||
| 			 * | ||||
| 			 *  \note This function is not available on all microcontroller architectures. | ||||
| 			 * | ||||
| 			 *  \param[in,out] CDCInterfaceInfo  Pointer to a structure containing a CDC Class configuration and state. | ||||
| 			 *  \param[in,out] Stream            Pointer to a FILE structure where the created stream should be placed. | ||||
| 			 */ | ||||
| 			void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 			                                     FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 			#endif | ||||
| 
 | ||||
| 	/* Private Interface - For use in library only: */ | ||||
| 	#if !defined(__DOXYGEN__) | ||||
| 		/* Function Prototypes: */ | ||||
| 			#if defined(__INCLUDE_FROM_CDC_DEVICE_C) | ||||
| 				#if defined(FDEV_SETUP_STREAM) | ||||
| 				static int CDC_Device_putchar(char c, | ||||
| 				                              FILE* Stream) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 				static int CDC_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 				static int CDC_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 				#endif | ||||
| 
 | ||||
| 				void CDC_Device_Event_Stub(void) ATTR_CONST; | ||||
| 
 | ||||
| 				void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| 				                                          ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); | ||||
| 				void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||||
| 				                                             ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); | ||||
| 				void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||||
| 				                                const uint8_t Duration) ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) | ||||
| 				                                ATTR_ALIAS(CDC_Device_Event_Stub); | ||||
| 			#endif | ||||
| 
 | ||||
| 	#endif | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										211
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,211 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_HID_DRIVER | ||||
| #define  __INCLUDE_FROM_HID_DEVICE_C | ||||
| #include "HIDClassDevice.h" | ||||
| 
 | ||||
| void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber) | ||||
| 	  return; | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case HID_REQ_GetReport: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				uint16_t ReportSize = 0; | ||||
| 				uint8_t  ReportID   = (USB_ControlRequest.wValue & 0xFF); | ||||
| 				uint8_t  ReportType = (USB_ControlRequest.wValue >> 8) - 1; | ||||
| 				uint8_t  ReportData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; | ||||
| 
 | ||||
| 				memset(ReportData, 0, sizeof(ReportData)); | ||||
| 
 | ||||
| 				CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType, ReportData, &ReportSize); | ||||
| 
 | ||||
| 				if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL) | ||||
| 				{ | ||||
| 					memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportData, | ||||
| 					       HIDInterfaceInfo->Config.PrevReportINBufferSize); | ||||
| 				} | ||||
| 
 | ||||
| 				Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); | ||||
| 
 | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 
 | ||||
| 				if (ReportID) | ||||
| 				  Endpoint_Write_8(ReportID); | ||||
| 
 | ||||
| 				Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); | ||||
| 				Endpoint_ClearOUT(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case HID_REQ_SetReport: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				uint16_t ReportSize = USB_ControlRequest.wLength; | ||||
| 				uint8_t  ReportID   = (USB_ControlRequest.wValue & 0xFF); | ||||
| 				uint8_t  ReportType = (USB_ControlRequest.wValue >> 8) - 1; | ||||
| 				uint8_t  ReportData[ReportSize]; | ||||
| 
 | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_Read_Control_Stream_LE(ReportData, ReportSize); | ||||
| 				Endpoint_ClearIN(); | ||||
| 
 | ||||
| 				CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportType, | ||||
| 				                                     &ReportData[ReportID ? 1 : 0], ReportSize - (ReportID ? 1 : 0)); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case HID_REQ_GetProtocol: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				while (!(Endpoint_IsINReady())); | ||||
| 				Endpoint_Write_8(HIDInterfaceInfo->State.UsingReportProtocol); | ||||
| 				Endpoint_ClearIN(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case HID_REQ_SetProtocol: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case HID_REQ_SetIdle: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case HID_REQ_GetIdle: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				while (!(Endpoint_IsINReady())); | ||||
| 				Endpoint_Write_8(HIDInterfaceInfo->State.IdleCount >> 2); | ||||
| 				Endpoint_ClearIN(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||||
| { | ||||
| 	memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); | ||||
| 	HIDInterfaceInfo->State.UsingReportProtocol = true; | ||||
| 	HIDInterfaceInfo->State.IdleCount           = 500; | ||||
| 
 | ||||
| 	HIDInterfaceInfo->Config.ReportINEndpoint.Type = EP_TYPE_INTERRUPT; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&HIDInterfaceInfo->Config.ReportINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (HIDInterfaceInfo->State.PrevFrameNum == USB_Device_GetFrameNumber()) | ||||
| 	{ | ||||
| 		#if defined(USB_DEVICE_OPT_LOWSPEED) | ||||
| 		if (!(USB_Options & USB_DEVICE_OPT_LOWSPEED)) | ||||
| 		  return; | ||||
| 		#else | ||||
| 		return; | ||||
| 		#endif | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsReadWriteAllowed()) | ||||
| 	{ | ||||
| 		uint8_t  ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; | ||||
| 		uint8_t  ReportID     = 0; | ||||
| 		uint16_t ReportINSize = 0; | ||||
| 
 | ||||
| 		memset(ReportINData, 0, sizeof(ReportINData)); | ||||
| 
 | ||||
| 		bool ForceSend         = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, HID_REPORT_ITEM_In, | ||||
| 		                                                             ReportINData, &ReportINSize); | ||||
| 		bool StatesChanged     = false; | ||||
| 		bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining)); | ||||
| 
 | ||||
| 		if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL) | ||||
| 		{ | ||||
| 			StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0); | ||||
| 			memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize); | ||||
| 		} | ||||
| 
 | ||||
| 		if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed)) | ||||
| 		{ | ||||
| 			HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount; | ||||
| 
 | ||||
| 			Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address); | ||||
| 
 | ||||
| 			if (ReportID) | ||||
| 			  Endpoint_Write_8(ReportID); | ||||
| 
 | ||||
| 			Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL); | ||||
| 
 | ||||
| 			Endpoint_ClearIN(); | ||||
| 		} | ||||
| 
 | ||||
| 		HIDInterfaceInfo->State.PrevFrameNum = USB_Device_GetFrameNumber(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										210
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,210 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB HID Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB HID Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassHID
 | ||||
|  *  \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassHIDDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassHIDDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the HID USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _HID_CLASS_DEVICE_H_ | ||||
| #define _HID_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/HIDClassCommon.h" | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_HID_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief HID Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each HID interface | ||||
| 			 *  within the user application, and passed to each of the HID class driver functions as the | ||||
| 			 *  \c HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information. | ||||
| 			 * | ||||
| 			 *  \note Due to technical limitations, the HID device class driver does not utilize a separate OUT | ||||
| 			 *        endpoint for host->device communications. Instead, the host->device data (if any) is sent to | ||||
| 			 *        the device via the control endpoint. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t  InterfaceNumber; /**< Interface number of the HID interface within the device. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t ReportINEndpoint; /**< Data IN HID report endpoint configuration table. */ | ||||
| 
 | ||||
| 					void*    PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be
 | ||||
| 					                              *  stored by the driver, for comparison purposes to detect report changes that | ||||
| 					                              *  must be sent immediately to the host. This should point to a buffer big enough | ||||
| 					                              *  to hold the largest HID input report sent from the HID interface. If this is set | ||||
| 					                              *  to \c NULL, it is up to the user to force transfers when needed in the | ||||
| 					                              *  \ref CALLBACK_HID_Device_CreateHIDReport() callback function. | ||||
| 					                              * | ||||
| 					                              *  \note Due to the single buffer, the internal driver can only correctly compare | ||||
| 					                              *        subsequent reports with identical report IDs. In multiple report devices, | ||||
| 					                              *        this buffer should be set to \c NULL and the decision to send reports made | ||||
| 					                              *        by the user application instead. | ||||
| 					                              */ | ||||
| 					uint8_t  PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a
 | ||||
| 					                                  *  second buffer of the same size within the driver so that subsequent reports | ||||
| 					                                  *  can be compared. If the user app is to determine when reports are to be sent | ||||
| 					                                  *  exclusively (i.e. \c PrevReportINBuffer is \c NULL) this value must still be | ||||
| 					                                  *  set to the size of the largest report the device can issue to the host. | ||||
| 					                                  */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					bool     UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode. */ | ||||
| 					uint16_t PrevFrameNum; /**< Frame number of the previous HID report packet opportunity. */ | ||||
| 					uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host. */ | ||||
| 					uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this
 | ||||
| 				                               *   should be decremented by the user application if non-zero each millisecond. */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_HID_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||||
| 			 *  containing the given HID interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given HID class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 */ | ||||
| 			void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given HID class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 */ | ||||
| 			void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** HID class driver callback for the user creation of a HID IN report. This callback may fire in response to either
 | ||||
| 			 *  HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the | ||||
| 			 *  user is responsible for the creation of the next HID input report to be sent to the host. | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 *  \param[in,out] ReportID          If preset to a non-zero value, this is the report ID being requested by the host. If zero, | ||||
| 			 *                                   this should be set to the report ID of the generated HID input report (if any). If multiple | ||||
| 			 *                                   reports are not sent via the given HID interface, this parameter should be ignored. | ||||
| 			 *  \param[in]     ReportType        Type of HID report to generate, either \ref HID_REPORT_ITEM_In or \ref HID_REPORT_ITEM_Feature. | ||||
| 			 *  \param[out]    ReportData        Pointer to a buffer where the generated HID report should be stored. | ||||
| 			 *  \param[out]    ReportSize        Number of bytes in the generated input report, or zero if no report is to be sent. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true to force the sending of the report even if it is identical to the previous report and still within | ||||
| 			 *          the idle period (useful for devices which report relative movement), \c false otherwise. | ||||
| 			 */ | ||||
| 			bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, | ||||
| 			                                         uint8_t* const ReportID, | ||||
| 			                                         const uint8_t ReportType, | ||||
| 			                                         void* ReportData, | ||||
| 			                                         uint16_t* const ReportSize) ATTR_NON_NULL_PTR_ARG(1) | ||||
| 			                                         ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(4) ATTR_NON_NULL_PTR_ARG(5); | ||||
| 
 | ||||
| 			/** HID class driver callback for the user processing of a received HID OUT report. This callback may fire in response to
 | ||||
| 			 *  either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback | ||||
| 			 *  the user is responsible for the processing of the received HID output report from the host. | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 *  \param[in]     ReportID          Report ID of the received output report. If multiple reports are not received via the given HID | ||||
| 			 *                                   interface, this parameter should be ignored. | ||||
| 			 *  \param[in]     ReportType        Type of received HID report, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature. | ||||
| 			 *  \param[in]     ReportData        Pointer to a buffer where the received HID report is stored. | ||||
| 			 *  \param[in]     ReportSize        Size in bytes of the received report from the host. | ||||
| 			 */ | ||||
| 			void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, | ||||
| 			                                          const uint8_t ReportID, | ||||
| 			                                          const uint8_t ReportType, | ||||
| 			                                          const void* ReportData, | ||||
| 			                                          const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4); | ||||
| 
 | ||||
| 		/* Inline Functions: */ | ||||
| 			/** Indicates that a millisecond of idle time has elapsed on the given HID interface, and the interface's idle count should be
 | ||||
| 			 *  decremented. This should be called once per millisecond so that hardware key-repeats function correctly. It is recommended | ||||
| 			 *  that this be called by the \ref EVENT_USB_Device_StartOfFrame() event, once SOF events have been enabled via | ||||
| 			 *  \ref USB_Device_EnableSOFEvents(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] HIDInterfaceInfo  Pointer to a structure containing a HID Class configuration and state. | ||||
| 			 */ | ||||
| 			static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1); | ||||
| 			static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||||
| 			{ | ||||
| 				if (HIDInterfaceInfo->State.IdleMSRemaining) | ||||
| 				  HIDInterfaceInfo->State.IdleMSRemaining--; | ||||
| 			} | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										131
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,131 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_MIDI_DRIVER | ||||
| #define  __INCLUDE_FROM_MIDI_DEVICE_C | ||||
| #include "MIDIClassDevice.h" | ||||
| 
 | ||||
| bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||||
| { | ||||
| 	memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); | ||||
| 
 | ||||
| 	MIDIInterfaceInfo->Config.DataINEndpoint.Type  = EP_TYPE_BULK; | ||||
| 	MIDIInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return; | ||||
| 
 | ||||
| 	#if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||||
| 	Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsINReady()) | ||||
| 	  MIDI_Device_Flush(MIDIInterfaceInfo); | ||||
| 	#endif | ||||
| } | ||||
| 
 | ||||
| uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||||
|                                     const MIDI_EventPacket_t* const Event) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	uint8_t ErrorCode; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != ENDPOINT_RWSTREAM_NoError) | ||||
| 	  return ErrorCode; | ||||
| 
 | ||||
| 	if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 	  Endpoint_ClearIN(); | ||||
| 
 | ||||
| 	return ENDPOINT_RWSTREAM_NoError; | ||||
| } | ||||
| 
 | ||||
| uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	uint8_t ErrorCode; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_BytesInEndpoint()) | ||||
| 	{ | ||||
| 		Endpoint_ClearIN(); | ||||
| 
 | ||||
| 		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 		  return ErrorCode; | ||||
| 	} | ||||
| 
 | ||||
| 	return ENDPOINT_READYWAIT_NoError; | ||||
| } | ||||
| 
 | ||||
| bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||||
|                                     MIDI_EventPacket_t* const Event) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (!(Endpoint_IsOUTReceived())) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); | ||||
| 
 | ||||
| 	if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 	  Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										175
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,175 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB MIDI Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB MIDI Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassMIDI
 | ||||
|  *  \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassMIDIDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassMIDIDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the MIDI USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _MIDI_CLASS_DEVICE_H_ | ||||
| #define _MIDI_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/MIDIClassCommon.h" | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_MIDI_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Define: */ | ||||
| 			/** \brief MIDI Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each MIDI interface | ||||
| 			 *  within the user application, and passed to each of the MIDI class driver functions as the | ||||
| 			 *  \c MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t  StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 
 | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t RESERVED; // No state information for this class
 | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_MIDI_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given MIDI interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||||
| 			 *  containing the given MIDI interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given MIDI class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 */ | ||||
| 			void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Sends a MIDI event packet to the host. If no host is connected, the event packet is discarded. Events are queued into the
 | ||||
| 			 *  endpoint bank until either the endpoint bank is full, or \ref MIDI_Device_Flush() is called. This allows for multiple | ||||
| 			 *  MIDI events to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the | ||||
| 			 *       call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 *  \param[in]     Event              Pointer to a populated \ref MIDI_EventPacket_t structure containing the MIDI event to send. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||||
| 			                                    const MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 
 | ||||
| 			/** Flushes the MIDI send buffer, sending any queued MIDI events to the host. This should be called to override the
 | ||||
| 			 *  \ref MIDI_Device_SendEventPacket() function's packing behavior, to flush queued events. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Receives a MIDI event packet from the host. Events are unpacked from the endpoint, thus if the endpoint bank contains
 | ||||
| 			 *  multiple MIDI events from the host in the one packet, multiple calls to this function will return each individual event. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the | ||||
| 			 *       call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 *  \param[out]    Event              Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if a MIDI event packet was received, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||||
| 			                                    MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 		/* Inline Functions: */ | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given MIDI class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MIDIInterfaceInfo  Pointer to a structure containing a MIDI Class configuration and state. | ||||
| 			 */ | ||||
| 			static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 			static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||||
| 			{ | ||||
| 				(void)MIDIInterfaceInfo; | ||||
| 			} | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										215
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,215 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_MS_DRIVER | ||||
| #define  __INCLUDE_FROM_MASSSTORAGE_DEVICE_C | ||||
| #include "MassStorageClassDevice.h" | ||||
| 
 | ||||
| void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber) | ||||
| 	  return; | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case MS_REQ_MassStorageReset: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				MSInterfaceInfo->State.IsMassStoreReset = true; | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case MS_REQ_GetMaxLUN: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				while (!(Endpoint_IsINReady())); | ||||
| 				Endpoint_Write_8(MSInterfaceInfo->Config.TotalLUNs - 1); | ||||
| 				Endpoint_ClearIN(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||||
| { | ||||
| 	memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State)); | ||||
| 
 | ||||
| 	MSInterfaceInfo->Config.DataINEndpoint.Type  = EP_TYPE_BULK; | ||||
| 	MSInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsOUTReceived()) | ||||
| 	{ | ||||
| 		if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) | ||||
| 		{ | ||||
| 			if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) | ||||
| 			  Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 			bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo); | ||||
| 
 | ||||
| 			MSInterfaceInfo->State.CommandStatus.Status              = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail; | ||||
| 			MSInterfaceInfo->State.CommandStatus.Signature           = CPU_TO_LE32(MS_CSW_SIGNATURE); | ||||
| 			MSInterfaceInfo->State.CommandStatus.Tag                 = MSInterfaceInfo->State.CommandBlock.Tag; | ||||
| 			MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength; | ||||
| 
 | ||||
| 			if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue))) | ||||
| 			  Endpoint_StallTransaction(); | ||||
| 
 | ||||
| 			MS_Device_ReturnCommandStatus(MSInterfaceInfo); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 	{ | ||||
| 		Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 		Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 		Endpoint_ClearStall(); | ||||
| 		Endpoint_ResetDataToggle(); | ||||
| 		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 		Endpoint_ClearStall(); | ||||
| 		Endpoint_ResetDataToggle(); | ||||
| 
 | ||||
| 		MSInterfaceInfo->State.IsMassStoreReset = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||||
| { | ||||
| 	uint16_t BytesProcessed; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	BytesProcessed = 0; | ||||
| 	while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock, | ||||
| 	                               (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) == | ||||
| 	                               ENDPOINT_RWSTREAM_IncompleteTransfer) | ||||
| 	{ | ||||
| 		if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 		  return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((MSInterfaceInfo->State.CommandBlock.Signature         != CPU_TO_LE32(MS_CBW_SIGNATURE))     || | ||||
| 	    (MSInterfaceInfo->State.CommandBlock.LUN               >= MSInterfaceInfo->Config.TotalLUNs) || | ||||
| 		(MSInterfaceInfo->State.CommandBlock.Flags              & 0x1F)                              || | ||||
| 		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0)                                 || | ||||
| 		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength >  16)) | ||||
| 	{ | ||||
| 		Endpoint_StallTransaction(); | ||||
| 		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 		Endpoint_StallTransaction(); | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	BytesProcessed = 0; | ||||
| 	while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData, | ||||
| 	                                MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) == | ||||
| 	                                ENDPOINT_RWSTREAM_IncompleteTransfer) | ||||
| 	{ | ||||
| 		if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 		  return false; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||||
| { | ||||
| 	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	while (Endpoint_IsStalled()) | ||||
| 	{ | ||||
| 		#if !defined(INTERRUPT_CONTROL_ENDPOINT) | ||||
| 		USB_USBTask(); | ||||
| 		#endif | ||||
| 
 | ||||
| 		if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 		  return; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	while (Endpoint_IsStalled()) | ||||
| 	{ | ||||
| 		#if !defined(INTERRUPT_CONTROL_ENDPOINT) | ||||
| 		USB_USBTask(); | ||||
| 		#endif | ||||
| 
 | ||||
| 		if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 		  return; | ||||
| 	} | ||||
| 
 | ||||
| 	uint16_t BytesProcessed = 0; | ||||
| 	while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, | ||||
| 	                                sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) == | ||||
| 	                                ENDPOINT_RWSTREAM_IncompleteTransfer) | ||||
| 	{ | ||||
| 		if (MSInterfaceInfo->State.IsMassStoreReset) | ||||
| 		  return; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_ClearIN(); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										161
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,161 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB Mass Storage Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB Mass Storage Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassMS
 | ||||
|  *  \defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassMSDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassMSDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _MS_CLASS_DEVICE_H_ | ||||
| #define _MS_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/MassStorageClassCommon.h" | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_MS_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief Mass Storage Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each Mass Storage interface | ||||
| 			 *  within the user application, and passed to each of the Mass Storage class driver functions as the | ||||
| 			 *  \c MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t  InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 
 | ||||
| 					uint8_t  TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					MS_CommandBlockWrapper_t  CommandBlock; /**< Mass Storage class command block structure, stores the received SCSI
 | ||||
| 															 *   command from the host which is to be processed. | ||||
| 															 */ | ||||
| 					MS_CommandStatusWrapper_t CommandStatus; /**< Mass Storage class command status structure, set elements to indicate
 | ||||
| 															  *   the issued command's success or failure to the host. | ||||
| 															  */ | ||||
| 					volatile bool IsMassStoreReset; /**< Flag indicating that the host has requested that the Mass Storage interface be reset
 | ||||
| 											         *   and that all current Mass Storage operations should immediately abort. | ||||
| 											         */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_MS_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given Mass Storage interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||||
| 			 *  containing the given Mass Storage interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a Mass Storage Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a Mass Storage Class configuration and state. | ||||
| 			 */ | ||||
| 			void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given Mass Storage class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a Mass Storage configuration and state. | ||||
| 			 */ | ||||
| 			void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Mass Storage class driver callback for the user processing of a received SCSI command. This callback will fire each time the
 | ||||
| 			 *  host sends a SCSI command which requires processing by the user application. Inside this callback the user is responsible | ||||
| 			 *  for the processing of the received SCSI command from the host. The SCSI command is available in the CommandBlock structure | ||||
| 			 *  inside the Mass Storage class state structure passed as a parameter to the callback function. | ||||
| 			 * | ||||
| 			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a Mass Storage Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the SCSI command was successfully processed, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 	/* Private Interface - For use in library only: */ | ||||
| 	#if !defined(__DOXYGEN__) | ||||
| 		/* Function Prototypes: */ | ||||
| 			#if defined(__INCLUDE_FROM_MASSSTORAGE_DEVICE_C) | ||||
| 				static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 				static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 			#endif | ||||
| 
 | ||||
| 	#endif | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										314
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,314 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_PRINTER_DRIVER | ||||
| #define  __INCLUDE_FROM_PRINTER_DEVICE_C | ||||
| #include "PrinterClassDevice.h" | ||||
| 
 | ||||
| void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (USB_ControlRequest.wIndex != PRNTInterfaceInfo->Config.InterfaceNumber) | ||||
| 	  return; | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case PRNT_REQ_GetDeviceID: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 
 | ||||
| 				while (!(Endpoint_IsINReady())) | ||||
| 				{ | ||||
| 					if (USB_DeviceState == DEVICE_STATE_Unattached) | ||||
| 					  return; | ||||
| 				} | ||||
| 
 | ||||
| 				uint16_t IEEEStringLen = strlen(PRNTInterfaceInfo->Config.IEEE1284String); | ||||
| 				Endpoint_Write_16_BE(IEEEStringLen); | ||||
| 				Endpoint_Write_Control_Stream_LE(PRNTInterfaceInfo->Config.IEEE1284String, IEEEStringLen); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case PRNT_REQ_GetPortStatus: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 
 | ||||
| 				while (!(Endpoint_IsINReady())) | ||||
| 				{ | ||||
| 					if (USB_DeviceState == DEVICE_STATE_Unattached) | ||||
| 					  return; | ||||
| 				} | ||||
| 
 | ||||
| 				Endpoint_Write_8(PRNTInterfaceInfo->State.PortStatus); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case PRNT_REQ_SoftReset: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_ClearStatusStage(); | ||||
| 
 | ||||
| 				PRNTInterfaceInfo->State.IsPrinterReset = true; | ||||
| 
 | ||||
| 				EVENT_PRNT_Device_SoftReset(PRNTInterfaceInfo); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State)); | ||||
| 	PRNTInterfaceInfo->State.PortStatus = PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT; | ||||
| 
 | ||||
| 	PRNTInterfaceInfo->Config.DataINEndpoint.Type  = EP_TYPE_BULK; | ||||
| 	PRNTInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return; | ||||
| 
 | ||||
| 	#if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsINReady()) | ||||
| 	  PRNT_Device_Flush(PRNTInterfaceInfo); | ||||
| 	#endif | ||||
| 
 | ||||
| 	if (PRNTInterfaceInfo->State.IsPrinterReset) | ||||
| 	{ | ||||
| 		Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 		Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 		Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 		Endpoint_ClearStall(); | ||||
| 		Endpoint_ResetDataToggle(); | ||||
| 		Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 		Endpoint_ClearStall(); | ||||
| 		Endpoint_ResetDataToggle(); | ||||
| 
 | ||||
| 		PRNTInterfaceInfo->State.IsPrinterReset = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
|                                const char* const String) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_Stream_LE(String, strlen(String), NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
|                              const void* const Buffer, | ||||
|                              const uint16_t Length) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 	return Endpoint_Write_Stream_LE(Buffer, Length, NULL); | ||||
| } | ||||
| 
 | ||||
| uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
|                              const uint8_t Data) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 	{ | ||||
| 		Endpoint_ClearIN(); | ||||
| 
 | ||||
| 		uint8_t ErrorCode; | ||||
| 
 | ||||
| 		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 		  return ErrorCode; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_Write_8(Data); | ||||
| 	return ENDPOINT_READYWAIT_NoError; | ||||
| } | ||||
| 
 | ||||
| uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 
 | ||||
| 	uint8_t ErrorCode; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if (!(Endpoint_BytesInEndpoint())) | ||||
| 	  return ENDPOINT_READYWAIT_NoError; | ||||
| 
 | ||||
| 	bool BankFull = !(Endpoint_IsReadWriteAllowed()); | ||||
| 
 | ||||
| 	Endpoint_ClearIN(); | ||||
| 
 | ||||
| 	if (BankFull) | ||||
| 	{ | ||||
| 		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 		  return ErrorCode; | ||||
| 
 | ||||
| 		Endpoint_ClearIN(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ENDPOINT_READYWAIT_NoError; | ||||
| } | ||||
| 
 | ||||
| uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return 0; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsOUTReceived()) | ||||
| 	{ | ||||
| 		if (!(Endpoint_BytesInEndpoint())) | ||||
| 		{ | ||||
| 			Endpoint_ClearOUT(); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return Endpoint_BytesInEndpoint(); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return -1; | ||||
| 
 | ||||
| 	int16_t ReceivedByte = -1; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsOUTReceived()) | ||||
| 	{ | ||||
| 		if (Endpoint_BytesInEndpoint()) | ||||
| 		  ReceivedByte = Endpoint_Read_8(); | ||||
| 
 | ||||
| 		if (!(Endpoint_BytesInEndpoint())) | ||||
| 		  Endpoint_ClearOUT(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| 
 | ||||
| #if defined(FDEV_SETUP_STREAM) | ||||
| void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
|                               FILE* const Stream) | ||||
| { | ||||
| 	*Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar, _FDEV_SETUP_RW); | ||||
| 	fdev_set_udata(Stream, PRNTInterfaceInfo); | ||||
| } | ||||
| 
 | ||||
| void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
|                                       FILE* const Stream) | ||||
| { | ||||
| 	*Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar_Blocking, _FDEV_SETUP_RW); | ||||
| 	fdev_set_udata(Stream, PRNTInterfaceInfo); | ||||
| } | ||||
| 
 | ||||
| static int PRNT_Device_putchar(char c, | ||||
|                                FILE* Stream) | ||||
| { | ||||
| 	return PRNT_Device_SendByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0; | ||||
| } | ||||
| 
 | ||||
| static int PRNT_Device_getchar(FILE* Stream) | ||||
| { | ||||
| 	int16_t ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream)); | ||||
| 
 | ||||
| 	if (ReceivedByte < 0) | ||||
| 	  return _FDEV_EOF; | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| 
 | ||||
| static int PRNT_Device_getchar_Blocking(FILE* Stream) | ||||
| { | ||||
| 	int16_t ReceivedByte; | ||||
| 
 | ||||
| 	while ((ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream))) < 0) | ||||
| 	{ | ||||
| 		if (USB_DeviceState == DEVICE_STATE_Unattached) | ||||
| 		  return _FDEV_EOF; | ||||
| 
 | ||||
| 		PRNT_Device_USBTask((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream)); | ||||
| 		USB_USBTask(); | ||||
| 	} | ||||
| 
 | ||||
| 	return ReceivedByte; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void PRNT_Device_Event_Stub(void) | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										293
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,293 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB Printer Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB Printer Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassPrinter
 | ||||
|  *  \defgroup Group_USBClassPrinterDevice Printer Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassPrinterDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassPrinterDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the Printer USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _PRINTER_CLASS_DEVICE_H_ | ||||
| #define _PRINTER_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/PrinterClassCommon.h" | ||||
| 
 | ||||
| 		#include <stdio.h> | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_PRINTER_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief Printer Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each Printer interface | ||||
| 			 *  within the user application, and passed to each of the Printer class driver functions as the | ||||
| 			 *  PRNTInterfaceInfo parameter. This stores each Printer interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t InterfaceNumber; /**< Interface number of the Printer interface within the device. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 
 | ||||
| 					char* IEEE1284String; /**< IEEE 1284 identification string, sent to the host during enumeration
 | ||||
| 					                       *   to identify the printer model, manufacturer and other characteristics. | ||||
| 					                       */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t PortStatus; /**< Current status of the Printer virtual port, a collection of \c PRNT_PORTSTATUS_*
 | ||||
| 					                     *   bitmask values. | ||||
| 					                     */ | ||||
| 
 | ||||
| 					volatile bool IsPrinterReset; /**< Flag indicating that the host has requested that the Printer interface be reset
 | ||||
| 											       *   and that all current Mass Storage operations should immediately abort. | ||||
| 											       */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_PRNT_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given Printer interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing | ||||
| 			 *  the given Printer interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given Printer class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 */ | ||||
| 			void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given Printer class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 */ | ||||
| 			void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Printer class driver event for a soft reset request on a Printer interface. This event fires each time the host
 | ||||
| 			 *  requests a reset of the printer interface's internal state, and may be hooked in the user program by declaring a | ||||
| 			 *  handler function with the same name and parameters listed here. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 */ | ||||
| 			void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is
 | ||||
| 			 *  called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank | ||||
| 			 *  becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows | ||||
| 			 *  for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 *  \param[in]     Buffer            Pointer to a buffer containing the data to send to the device. | ||||
| 			 *  \param[in]     Length            Length of the data to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
| 			                             const void* const Buffer, | ||||
| 			                             const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when
 | ||||
| 			 *  the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||||
| 			 *  the endpoint bank becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to | ||||
| 			 *  the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 *  \param[in]     String            Pointer to the null terminated string to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
| 			                               const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
 | ||||
| 			 *  byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the | ||||
| 			 *  \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be | ||||
| 			 *  packed into a single endpoint packet, increasing data throughput. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 *  \param[in]     Data              Byte of data to send to the host. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
| 			                             const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Determines the number of bytes received by the Printer interface from the host, waiting to be read. This indicates the number
 | ||||
| 			 *  of bytes in the OUT endpoint bank only, and thus the number of calls to \ref PRNT_Device_ReceiveByte() which are guaranteed to | ||||
| 			 *  succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint | ||||
| 			 *  bank will not be released back to the USB controller until all bytes are read. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Total number of buffered bytes received from the host. | ||||
| 			 */ | ||||
| 			uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
 | ||||
| 			 *  returns a negative value. The \ref PRNT_Device_BytesReceived() function may be queried in advance to determine how many | ||||
| 			 *  bytes are currently buffered in the Printer interface's data receive endpoint bank, and thus how many repeated calls to this | ||||
| 			 *  function which are guaranteed to succeed. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Next received byte from the host, or a negative value if no data received. | ||||
| 			 */ | ||||
| 			int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
 | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||||
| 			 *       the call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			#if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__) | ||||
| 			/** Creates a standard character stream for the given Printer Device instance so that it can be used with all the regular
 | ||||
| 			 *  functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created | ||||
| 			 *  stream is bidirectional and can be used for both input and output functions. | ||||
| 			 * | ||||
| 			 *  Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single | ||||
| 			 *  fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may | ||||
| 			 *  be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own | ||||
| 			 *  line buffering. | ||||
| 			 * | ||||
| 			 *  \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions | ||||
| 			 *        to the given Printer interface. | ||||
| 			 *        \n\n | ||||
| 			 * | ||||
| 			 *  \note This function is not available on all microcontroller architectures. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 *  \param[in,out] Stream            Pointer to a FILE structure where the created stream should be placed. | ||||
| 			 */ | ||||
| 			void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
| 			                              FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 
 | ||||
| 			/** Identical to \ref PRNT_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
 | ||||
| 			 *  the transfer. While blocking, the USB and Printer service tasks are called repeatedly to maintain USB communications. | ||||
| 			 * | ||||
| 			 *  \note This function is not available on all microcontroller architectures. | ||||
| 			 * | ||||
| 			 *  \param[in,out] PRNTInterfaceInfo  Pointer to a structure containing a Printer Class configuration and state. | ||||
| 			 *  \param[in,out] Stream            Pointer to a FILE structure where the created stream should be placed. | ||||
| 			 */ | ||||
| 			void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||||
| 			                                      FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 			#endif | ||||
| 
 | ||||
| 	/* Private Interface - For use in library only: */ | ||||
| 	#if !defined(__DOXYGEN__) | ||||
| 		/* Function Prototypes: */ | ||||
| 			#if defined(__INCLUDE_FROM_PRINTER_DEVICE_C) | ||||
| 				#if defined(FDEV_SETUP_STREAM) | ||||
| 				static int PRNT_Device_putchar(char c, | ||||
| 				                               FILE* Stream) ATTR_NON_NULL_PTR_ARG(2); | ||||
| 				static int PRNT_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 				static int PRNT_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 				#endif | ||||
| 
 | ||||
| 				void PRNT_Device_Event_Stub(void) ATTR_CONST; | ||||
| 
 | ||||
| 				void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||||
| 				                                 ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(PRNT_Device_Event_Stub); | ||||
| 
 | ||||
| 			#endif | ||||
| 
 | ||||
| 	#endif | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
							
								
								
									
										508
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										508
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,508 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_USB_DRIVER | ||||
| #include "../../Core/USBMode.h" | ||||
| 
 | ||||
| #if defined(USB_CAN_BE_DEVICE) | ||||
| 
 | ||||
| #define  __INCLUDE_FROM_RNDIS_DRIVER | ||||
| #define  __INCLUDE_FROM_RNDIS_DEVICE_C | ||||
| #include "RNDISClassDevice.h" | ||||
| 
 | ||||
| static const uint32_t PROGMEM AdapterSupportedOIDList[]  = | ||||
| 	{ | ||||
| 		CPU_TO_LE32(OID_GEN_SUPPORTED_LIST), | ||||
| 		CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM), | ||||
| 		CPU_TO_LE32(OID_GEN_HARDWARE_STATUS), | ||||
| 		CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED), | ||||
| 		CPU_TO_LE32(OID_GEN_MEDIA_IN_USE), | ||||
| 		CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE), | ||||
| 		CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE), | ||||
| 		CPU_TO_LE32(OID_GEN_LINK_SPEED), | ||||
| 		CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE), | ||||
| 		CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE), | ||||
| 		CPU_TO_LE32(OID_GEN_VENDOR_ID), | ||||
| 		CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION), | ||||
| 		CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER), | ||||
| 		CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE), | ||||
| 		CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS), | ||||
| 		CPU_TO_LE32(OID_GEN_XMIT_OK), | ||||
| 		CPU_TO_LE32(OID_GEN_RCV_OK), | ||||
| 		CPU_TO_LE32(OID_GEN_XMIT_ERROR), | ||||
| 		CPU_TO_LE32(OID_GEN_RCV_ERROR), | ||||
| 		CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER), | ||||
| 		CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS), | ||||
| 		CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS), | ||||
| 		CPU_TO_LE32(OID_802_3_MULTICAST_LIST), | ||||
| 		CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE), | ||||
| 		CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT), | ||||
| 		CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION), | ||||
| 		CPU_TO_LE32(OID_802_3_XMIT_MORE_COLLISIONS), | ||||
| 	}; | ||||
| 
 | ||||
| void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| { | ||||
| 	if (!(Endpoint_IsSETUPReceived())) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber) | ||||
| 	  return; | ||||
| 
 | ||||
| 	switch (USB_ControlRequest.bRequest) | ||||
| 	{ | ||||
| 		case RNDIS_REQ_SendEncapsulatedCommand: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength); | ||||
| 				Endpoint_ClearIN(); | ||||
| 
 | ||||
| 				RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case RNDIS_REQ_GetEncapsulatedResponse: | ||||
| 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
| 			{ | ||||
| 				RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 
 | ||||
| 				if (!(MessageHeader->MessageLength)) | ||||
| 				{ | ||||
| 					RNDISInterfaceInfo->Config.MessageBuffer[0] = 0; | ||||
| 					MessageHeader->MessageLength                = CPU_TO_LE32(1); | ||||
| 				} | ||||
| 
 | ||||
| 				Endpoint_ClearSETUP(); | ||||
| 				Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength)); | ||||
| 				Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 				MessageHeader->MessageLength = CPU_TO_LE32(0); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| { | ||||
| 	memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); | ||||
| 
 | ||||
| 	RNDISInterfaceInfo->Config.DataINEndpoint.Type       = EP_TYPE_BULK; | ||||
| 	RNDISInterfaceInfo->Config.DataOUTEndpoint.Type      = EP_TYPE_BULK; | ||||
| 	RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT; | ||||
| 
 | ||||
| 	if (RNDISInterfaceInfo->Config.MessageBuffer == NULL) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1))) | ||||
| 	  return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| { | ||||
| 	if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
| 	  return; | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address); | ||||
| 
 | ||||
| 	if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) | ||||
| 	{ | ||||
| 		USB_Request_Header_t Notification = (USB_Request_Header_t) | ||||
| 			{ | ||||
| 				.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), | ||||
| 				.bRequest      = RNDIS_NOTIF_ResponseAvailable, | ||||
| 				.wValue        = CPU_TO_LE16(0), | ||||
| 				.wIndex        = CPU_TO_LE16(0), | ||||
| 				.wLength       = CPU_TO_LE16(0), | ||||
| 			}; | ||||
| 
 | ||||
| 		Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL); | ||||
| 
 | ||||
| 		Endpoint_ClearIN(); | ||||
| 
 | ||||
| 		RNDISInterfaceInfo->State.ResponseReady = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| { | ||||
| 	/* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
 | ||||
| 	         this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */ | ||||
| 
 | ||||
| 	RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 
 | ||||
| 	switch (le32_to_cpu(MessageHeader->MessageType)) | ||||
| 	{ | ||||
| 		case REMOTE_NDIS_INITIALIZE_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = true; | ||||
| 
 | ||||
| 			RNDIS_Initialize_Message_t*  INITIALIZE_Message  = | ||||
| 			               (RNDIS_Initialize_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			RNDIS_Initialize_Complete_t* INITIALIZE_Response = | ||||
| 			               (RNDIS_Initialize_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 
 | ||||
| 			INITIALIZE_Response->MessageType            = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT); | ||||
| 			INITIALIZE_Response->MessageLength          = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t)); | ||||
| 			INITIALIZE_Response->RequestId              = INITIALIZE_Message->RequestId; | ||||
| 			INITIALIZE_Response->Status                 = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||||
| 
 | ||||
| 			INITIALIZE_Response->MajorVersion           = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR); | ||||
| 			INITIALIZE_Response->MinorVersion           = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR); | ||||
| 			INITIALIZE_Response->DeviceFlags            = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS); | ||||
| 			INITIALIZE_Response->Medium                 = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3); | ||||
| 			INITIALIZE_Response->MaxPacketsPerTransfer  = CPU_TO_LE32(1); | ||||
| 			INITIALIZE_Response->MaxTransferSize        = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX); | ||||
| 			INITIALIZE_Response->PacketAlignmentFactor  = CPU_TO_LE32(0); | ||||
| 			INITIALIZE_Response->AFListOffset           = CPU_TO_LE32(0); | ||||
| 			INITIALIZE_Response->AFListSize             = CPU_TO_LE32(0); | ||||
| 
 | ||||
| 			RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Initialized; | ||||
| 			break; | ||||
| 		case REMOTE_NDIS_HALT_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = false; | ||||
| 
 | ||||
| 			MessageHeader->MessageLength                = CPU_TO_LE32(0); | ||||
| 
 | ||||
| 			RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Uninitialized; | ||||
| 			break; | ||||
| 		case REMOTE_NDIS_QUERY_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = true; | ||||
| 
 | ||||
| 			RNDIS_Query_Message_t*  QUERY_Message       = (RNDIS_Query_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			RNDIS_Query_Complete_t* QUERY_Response      = (RNDIS_Query_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			uint32_t                Query_Oid           = CPU_TO_LE32(QUERY_Message->Oid); | ||||
| 
 | ||||
| 			void*    QueryData    = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) + | ||||
| 			                                                                  le32_to_cpu(QUERY_Message->InformationBufferOffset)]; | ||||
| 			void*    ResponseData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Query_Complete_t)]; | ||||
| 			uint16_t ResponseSize; | ||||
| 
 | ||||
| 			QUERY_Response->MessageType                 = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT); | ||||
| 
 | ||||
| 			if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength), | ||||
| 			                                  ResponseData, &ResponseSize)) | ||||
| 			{ | ||||
| 				QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||||
| 				QUERY_Response->MessageLength           = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize); | ||||
| 
 | ||||
| 				QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize); | ||||
| 				QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED); | ||||
| 				QUERY_Response->MessageLength           = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t)); | ||||
| 
 | ||||
| 				QUERY_Response->InformationBufferLength = CPU_TO_LE32(0); | ||||
| 				QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0); | ||||
| 			} | ||||
| 
 | ||||
| 			break; | ||||
| 		case REMOTE_NDIS_SET_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = true; | ||||
| 
 | ||||
| 			RNDIS_Set_Message_t*  SET_Message           = (RNDIS_Set_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			RNDIS_Set_Complete_t* SET_Response          = (RNDIS_Set_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			uint32_t              SET_Oid               = le32_to_cpu(SET_Message->Oid); | ||||
| 
 | ||||
| 			SET_Response->MessageType                   = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT); | ||||
| 			SET_Response->MessageLength                 = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t)); | ||||
| 			SET_Response->RequestId                     = SET_Message->RequestId; | ||||
| 
 | ||||
| 			void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) + | ||||
| 			                                                              le32_to_cpu(SET_Message->InformationBufferOffset)]; | ||||
| 
 | ||||
| 			SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, | ||||
| 			                                                   le32_to_cpu(SET_Message->InformationBufferLength)) ? | ||||
| 			                                                   REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED; | ||||
| 			break; | ||||
| 		case REMOTE_NDIS_RESET_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = true; | ||||
| 
 | ||||
| 			RNDIS_Reset_Complete_t* RESET_Response      = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 
 | ||||
| 			RESET_Response->MessageType                 = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT); | ||||
| 			RESET_Response->MessageLength               = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t)); | ||||
| 			RESET_Response->Status                      = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||||
| 			RESET_Response->AddressingReset             = CPU_TO_LE32(0); | ||||
| 
 | ||||
| 			break; | ||||
| 		case REMOTE_NDIS_KEEPALIVE_MSG: | ||||
| 			RNDISInterfaceInfo->State.ResponseReady     = true; | ||||
| 
 | ||||
| 			RNDIS_KeepAlive_Message_t*  KEEPALIVE_Message  = | ||||
| 			                (RNDIS_KeepAlive_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 			RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = | ||||
| 			                (RNDIS_KeepAlive_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||||
| 
 | ||||
| 			KEEPALIVE_Response->MessageType             = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT); | ||||
| 			KEEPALIVE_Response->MessageLength           = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t)); | ||||
| 			KEEPALIVE_Response->RequestId               = KEEPALIVE_Message->RequestId; | ||||
| 			KEEPALIVE_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||||
| 
 | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
|                                           const uint32_t OId, | ||||
|                                           void* const QueryData, | ||||
|                                           const uint16_t QuerySize, | ||||
|                                           void* ResponseData, | ||||
|                                           uint16_t* const ResponseSize) | ||||
| { | ||||
| 	(void)QueryData; | ||||
| 	(void)QuerySize; | ||||
| 
 | ||||
| 	switch (OId) | ||||
| 	{ | ||||
| 		case OID_GEN_SUPPORTED_LIST: | ||||
| 			*ResponseSize = sizeof(AdapterSupportedOIDList); | ||||
| 
 | ||||
| 			memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList)); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_PHYSICAL_MEDIUM: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Indicate that the device is a true ethernet link */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(0); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_HARDWARE_STATUS: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_MEDIA_SUPPORTED: | ||||
| 		case OID_GEN_MEDIA_IN_USE: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_VENDOR_ID: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_MAXIMUM_FRAME_SIZE: | ||||
| 		case OID_GEN_TRANSMIT_BLOCK_SIZE: | ||||
| 		case OID_GEN_RECEIVE_BLOCK_SIZE: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_VENDOR_DESCRIPTION: | ||||
| 			*ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1); | ||||
| 
 | ||||
| 			memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_MEDIA_CONNECT_STATUS: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_LINK_SPEED: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Indicate 10Mb/s link speed */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(100000); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_802_3_PERMANENT_ADDRESS: | ||||
| 		case OID_802_3_CURRENT_ADDRESS: | ||||
| 			*ResponseSize = sizeof(MAC_Address_t); | ||||
| 
 | ||||
| 			memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t)); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_802_3_MAXIMUM_LIST_SIZE: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Indicate only one multicast address supported */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(1); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_CURRENT_PACKET_FILTER: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			*((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_XMIT_OK: | ||||
| 		case OID_GEN_RCV_OK: | ||||
| 		case OID_GEN_XMIT_ERROR: | ||||
| 		case OID_GEN_RCV_ERROR: | ||||
| 		case OID_GEN_RCV_NO_BUFFER: | ||||
| 		case OID_802_3_RCV_ERROR_ALIGNMENT: | ||||
| 		case OID_802_3_XMIT_ONE_COLLISION: | ||||
| 		case OID_802_3_XMIT_MORE_COLLISIONS: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Unused statistic OIDs - always return 0 for each */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(0); | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_GEN_MAXIMUM_TOTAL_SIZE: | ||||
| 			*ResponseSize = sizeof(uint32_t); | ||||
| 
 | ||||
| 			/* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */ | ||||
| 			*((uint32_t*)ResponseData) = CPU_TO_LE32(RNDISInterfaceInfo->Config.MessageBufferLength + ETHERNET_FRAME_SIZE_MAX); | ||||
| 
 | ||||
| 			return true; | ||||
| 		default: | ||||
| 			return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
|                                         const uint32_t OId, | ||||
|                                         const void* SetData, | ||||
|                                         const uint16_t SetSize) | ||||
| { | ||||
| 	(void)SetSize; | ||||
| 
 | ||||
| 	switch (OId) | ||||
| 	{ | ||||
| 		case OID_GEN_CURRENT_PACKET_FILTER: | ||||
| 			RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData)); | ||||
| 			RNDISInterfaceInfo->State.CurrRNDISState   = (RNDISInterfaceInfo->State.CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Initialized; | ||||
| 
 | ||||
| 			return true; | ||||
| 		case OID_802_3_MULTICAST_LIST: | ||||
| 			/* Do nothing - throw away the value from the host as it is unused */ | ||||
| 
 | ||||
| 			return true; | ||||
| 		default: | ||||
| 			return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||||
| 	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 	return Endpoint_IsOUTReceived(); | ||||
| } | ||||
| 
 | ||||
| uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
|                                 void* Buffer, | ||||
|                                 uint16_t* const PacketLength) | ||||
| { | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||||
| 	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||||
| 	{ | ||||
| 		return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address); | ||||
| 
 | ||||
| 	*PacketLength = 0; | ||||
| 
 | ||||
| 	if (!(Endpoint_IsOUTReceived())) | ||||
| 		return ENDPOINT_RWSTREAM_NoError; | ||||
| 
 | ||||
| 	RNDIS_Packet_Message_t RNDISPacketHeader; | ||||
| 	Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); | ||||
| 
 | ||||
| 	if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX) | ||||
| 	{ | ||||
| 		Endpoint_StallTransaction(); | ||||
| 
 | ||||
| 		return RNDIS_ERROR_LOGICAL_CMD_FAILED; | ||||
| 	} | ||||
| 
 | ||||
| 	*PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength); | ||||
| 
 | ||||
| 	Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL); | ||||
| 	Endpoint_ClearOUT(); | ||||
| 
 | ||||
| 	return ENDPOINT_RWSTREAM_NoError; | ||||
| } | ||||
| 
 | ||||
| uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
|                                 void* Buffer, | ||||
|                                 const uint16_t PacketLength) | ||||
| { | ||||
| 	uint8_t ErrorCode; | ||||
| 
 | ||||
| 	if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||||
| 	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||||
| 	{ | ||||
| 		return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||||
| 	} | ||||
| 
 | ||||
| 	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address); | ||||
| 
 | ||||
| 	if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||||
| 	  return ErrorCode; | ||||
| 
 | ||||
| 	RNDIS_Packet_Message_t RNDISPacketHeader; | ||||
| 
 | ||||
| 	memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t)); | ||||
| 
 | ||||
| 	RNDISPacketHeader.MessageType   = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG); | ||||
| 	RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength); | ||||
| 	RNDISPacketHeader.DataOffset    = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); | ||||
| 	RNDISPacketHeader.DataLength    = cpu_to_le32(PacketLength); | ||||
| 
 | ||||
| 	Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); | ||||
| 	Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL); | ||||
| 	Endpoint_ClearIN(); | ||||
| 
 | ||||
| 	return ENDPOINT_RWSTREAM_NoError; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										207
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,207 @@ | |||
| /*
 | ||||
|              LUFA Library | ||||
|      Copyright (C) Dean Camera, 2017. | ||||
| 
 | ||||
|   dean [at] fourwalledcubicle [dot] com | ||||
|            www.lufa-lib.org | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
|   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||||
| 
 | ||||
|   Permission to use, copy, modify, distribute, and sell this | ||||
|   software and its documentation for any purpose is hereby granted | ||||
|   without fee, provided that the above copyright notice appear in | ||||
|   all copies and that both that the copyright notice and this | ||||
|   permission notice and warranty disclaimer appear in supporting | ||||
|   documentation, and that the name of the author not be used in | ||||
|   advertising or publicity pertaining to distribution of the | ||||
|   software without specific, written prior permission. | ||||
| 
 | ||||
|   The author disclaims all warranties with regard to this | ||||
|   software, including all implied warranties of merchantability | ||||
|   and fitness.  In no event shall the author be liable for any | ||||
|   special, indirect or consequential damages or any damages | ||||
|   whatsoever resulting from loss of use, data or profits, whether | ||||
|   in an action of contract, negligence or other tortious action, | ||||
|   arising out of or in connection with the use or performance of | ||||
|   this software. | ||||
| */ | ||||
| 
 | ||||
| /** \file
 | ||||
|  *  \brief Device mode driver for the library USB RNDIS Class driver. | ||||
|  * | ||||
|  *  Device mode driver for the library USB RNDIS Class driver. | ||||
|  * | ||||
|  *  \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||||
|  *        dispatch header located in LUFA/Drivers/USB.h. | ||||
|  */ | ||||
| 
 | ||||
| /** \ingroup Group_USBClassRNDIS
 | ||||
|  *  \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver | ||||
|  * | ||||
|  *  \section Sec_USBClassRNDISDevice_Dependencies Module Source Dependencies | ||||
|  *  The following files must be built with any user project that uses this module: | ||||
|  *    - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||||
|  * | ||||
|  *  \section Sec_USBClassRNDISDevice_ModDescription Module Description | ||||
|  *  Device Mode USB Class driver framework interface, for the RNDIS USB Class driver. | ||||
|  * | ||||
|  *  @{ | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _RNDIS_CLASS_DEVICE_H_ | ||||
| #define _RNDIS_CLASS_DEVICE_H_ | ||||
| 
 | ||||
| 	/* Includes: */ | ||||
| 		#include "../../USB.h" | ||||
| 		#include "../Common/RNDISClassCommon.h" | ||||
| 
 | ||||
| 	/* Enable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			extern "C" { | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Preprocessor Checks: */ | ||||
| 		#if !defined(__INCLUDE_FROM_RNDIS_DRIVER) | ||||
| 			#error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||||
| 		#endif | ||||
| 
 | ||||
| 	/* Public Interface - May be used in end-application: */ | ||||
| 		/* Type Defines: */ | ||||
| 			/** \brief RNDIS Class Device Mode Configuration and State Structure.
 | ||||
| 			 * | ||||
| 			 *  Class state structure. An instance of this structure should be made for each RNDIS interface | ||||
| 			 *  within the user application, and passed to each of the RNDIS class driver functions as the | ||||
| 			 *  \c RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information. | ||||
| 			 */ | ||||
| 			typedef struct | ||||
| 			{ | ||||
| 				struct | ||||
| 				{ | ||||
| 					uint8_t  ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */ | ||||
| 
 | ||||
| 					USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||||
| 					USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */ | ||||
| 
 | ||||
| 					char*         AdapterVendorDescription; /**< String description of the adapter vendor. */ | ||||
| 					MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */ | ||||
| 
 | ||||
| 					uint8_t*      MessageBuffer; /**< Buffer where RNDIS messages can be stored by the internal driver. This
 | ||||
| 					                              *   should be at least 132 bytes in length for minimal functionality. */ | ||||
| 					uint16_t      MessageBufferLength; /**< Length in bytes of the \ref MessageBuffer RNDIS buffer. */ | ||||
| 				} Config; /**< Config data for the USB class interface within the device. All elements in this section
 | ||||
| 				           *   <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||||
| 				           */ | ||||
| 				struct | ||||
| 				{ | ||||
| 					bool     ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */ | ||||
| 					uint8_t  CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \ref RNDIS_States_t enum. */ | ||||
| 					uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver. */ | ||||
| 				} State; /**< State data for the USB class interface within the device. All elements in this section
 | ||||
| 				          *   are reset to their defaults when the interface is enumerated. | ||||
| 				          */ | ||||
| 			} USB_ClassInfo_RNDIS_Device_t; | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 			/** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library
 | ||||
| 			 *  \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||||
| 			 *  containing the given RNDIS interface is selected. | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing a RNDIS Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be
 | ||||
| 			 *  linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing a RNDIS Class configuration and state. | ||||
| 			 */ | ||||
| 			void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** General management task for a given RNDIS class interface, required for the correct operation of the interface. This should
 | ||||
| 			 *  be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing a RNDIS Class configuration and state. | ||||
| 			 */ | ||||
| 			void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Determines if a packet is currently waiting for the device to read in and process.
 | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||||
| 			 *       call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state. | ||||
| 			 * | ||||
| 			 *  \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise. | ||||
| 			 */ | ||||
| 			bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
 | ||||
| 			 *  only the packet contents for processing by the device in the nominated buffer. | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||||
| 			 *       call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state. | ||||
| 			 *  \param[out]    Buffer              Pointer to a buffer where the packer data is to be written to. | ||||
| 			 *  \param[out]    PacketLength        Pointer to where the length in bytes of the read packet is to be stored. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
| 											void* Buffer, | ||||
| 											uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 			/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
 | ||||
| 			 * | ||||
| 			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||||
| 			 *       call will fail. | ||||
| 			 * | ||||
| 			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state. | ||||
| 			 *  \param[in]     Buffer              Pointer to a buffer where the packer data is to be read from. | ||||
| 			 *  \param[in]     PacketLength        Length in bytes of the packet to send. | ||||
| 			 * | ||||
| 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||||
| 			 */ | ||||
| 			uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
| 											void* Buffer, | ||||
| 											const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1); | ||||
| 
 | ||||
| 	/* Private Interface - For use in library only: */ | ||||
| 	#if !defined(__DOXYGEN__) | ||||
| 		/* Macros: */ | ||||
| 			#define RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH  sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_Query_Complete_t) | ||||
| 
 | ||||
| 		/* Function Prototypes: */ | ||||
| 		#if defined(__INCLUDE_FROM_RNDIS_DEVICE_C) | ||||
| 			static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||||
| 			                                                    ATTR_NON_NULL_PTR_ARG(1); | ||||
| 			static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
| 			                                          const uint32_t OId, | ||||
|                                                       void* const QueryData, | ||||
|                                                       const uint16_t QuerySize, | ||||
| 										              void* ResponseData, | ||||
|                                                       uint16_t* const ResponseSize) ATTR_NON_NULL_PTR_ARG(1) | ||||
| 			                                          ATTR_NON_NULL_PTR_ARG(5) ATTR_NON_NULL_PTR_ARG(6); | ||||
| 			static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||||
|                                                     const uint32_t OId, | ||||
| 			                                        const void* SetData, | ||||
|                                                     const uint16_t SetSize) ATTR_NON_NULL_PTR_ARG(1) | ||||
| 			                                        ATTR_NON_NULL_PTR_ARG(3); | ||||
| 		#endif | ||||
| 
 | ||||
| 	#endif | ||||
| 
 | ||||
| 	/* Disable C linkage for C++ Compilers: */ | ||||
| 		#if defined(__cplusplus) | ||||
| 			} | ||||
| 		#endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /** @} */ | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jack Humbert
						Jack Humbert