diff options
Diffstat (limited to 'lib/lufa/LUFA/Drivers/USB/Class/Device')
14 files changed, 3766 insertions, 0 deletions
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c new file mode 100644 index 000000000..08cbeb706 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_AUDIO_DRIVER | ||
| 37 | #define __INCLUDE_FROM_AUDIO_DEVICE_C | ||
| 38 | #include "AudioClassDevice.h" | ||
| 39 | |||
| 40 | void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 41 | { | ||
| 42 | if (!(Endpoint_IsSETUPReceived())) | ||
| 43 | return; | ||
| 44 | |||
| 45 | if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||
| 46 | { | ||
| 47 | uint8_t InterfaceIndex = (USB_ControlRequest.wIndex & 0xFF); | ||
| 48 | |||
| 49 | if ((InterfaceIndex != AudioInterfaceInfo->Config.ControlInterfaceNumber) && | ||
| 50 | (InterfaceIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber)) | ||
| 51 | { | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||
| 56 | { | ||
| 57 | uint8_t EndpointAddress = (USB_ControlRequest.wIndex & 0xFF); | ||
| 58 | |||
| 59 | if ((EndpointAddress != AudioInterfaceInfo->Config.DataINEndpoint.Address) && | ||
| 60 | (EndpointAddress != AudioInterfaceInfo->Config.DataOUTEndpoint.Address)) | ||
| 61 | { | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | switch (USB_ControlRequest.bRequest) | ||
| 67 | { | ||
| 68 | case REQ_SetInterface: | ||
| 69 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE)) | ||
| 70 | { | ||
| 71 | Endpoint_ClearSETUP(); | ||
| 72 | Endpoint_ClearStatusStage(); | ||
| 73 | |||
| 74 | AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0); | ||
| 75 | EVENT_Audio_Device_StreamStartStop(AudioInterfaceInfo); | ||
| 76 | } | ||
| 77 | |||
| 78 | break; | ||
| 79 | case AUDIO_REQ_GetStatus: | ||
| 80 | if ((USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) || | ||
| 81 | (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT))) | ||
| 82 | { | ||
| 83 | Endpoint_ClearSETUP(); | ||
| 84 | Endpoint_ClearStatusStage(); | ||
| 85 | } | ||
| 86 | |||
| 87 | break; | ||
| 88 | case AUDIO_REQ_SetCurrent: | ||
| 89 | case AUDIO_REQ_SetMinimum: | ||
| 90 | case AUDIO_REQ_SetMaximum: | ||
| 91 | case AUDIO_REQ_SetResolution: | ||
| 92 | if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||
| 93 | { | ||
| 94 | uint8_t EndpointProperty = USB_ControlRequest.bRequest; | ||
| 95 | uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex; | ||
| 96 | uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8); | ||
| 97 | |||
| 98 | if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||
| 99 | EndpointControl, NULL, NULL)) | ||
| 100 | { | ||
| 101 | uint16_t ValueLength = USB_ControlRequest.wLength; | ||
| 102 | uint8_t Value[ValueLength]; | ||
| 103 | |||
| 104 | Endpoint_ClearSETUP(); | ||
| 105 | Endpoint_Read_Control_Stream_LE(Value, ValueLength); | ||
| 106 | Endpoint_ClearIN(); | ||
| 107 | |||
| 108 | CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||
| 109 | EndpointControl, &ValueLength, Value); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||
| 113 | { | ||
| 114 | uint8_t Property = USB_ControlRequest.bRequest; | ||
| 115 | uint8_t Entity = (USB_ControlRequest.wIndex >> 8); | ||
| 116 | uint16_t Parameter = USB_ControlRequest.wValue; | ||
| 117 | |||
| 118 | if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||
| 119 | Parameter, NULL, NULL)) | ||
| 120 | { | ||
| 121 | uint16_t ValueLength = USB_ControlRequest.wLength; | ||
| 122 | uint8_t Value[ValueLength]; | ||
| 123 | |||
| 124 | Endpoint_ClearSETUP(); | ||
| 125 | Endpoint_Read_Control_Stream_LE(Value, ValueLength); | ||
| 126 | Endpoint_ClearIN(); | ||
| 127 | |||
| 128 | CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||
| 129 | Parameter, &ValueLength, Value); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | break; | ||
| 134 | case AUDIO_REQ_GetCurrent: | ||
| 135 | case AUDIO_REQ_GetMinimum: | ||
| 136 | case AUDIO_REQ_GetMaximum: | ||
| 137 | case AUDIO_REQ_GetResolution: | ||
| 138 | if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) | ||
| 139 | { | ||
| 140 | uint8_t EndpointProperty = USB_ControlRequest.bRequest; | ||
| 141 | uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex; | ||
| 142 | uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8); | ||
| 143 | uint16_t ValueLength = USB_ControlRequest.wLength; | ||
| 144 | uint8_t Value[ValueLength]; | ||
| 145 | |||
| 146 | if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress, | ||
| 147 | EndpointControl, &ValueLength, Value)) | ||
| 148 | { | ||
| 149 | Endpoint_ClearSETUP(); | ||
| 150 | Endpoint_Write_Control_Stream_LE(Value, ValueLength); | ||
| 151 | Endpoint_ClearOUT(); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE) | ||
| 155 | { | ||
| 156 | uint8_t Property = USB_ControlRequest.bRequest; | ||
| 157 | uint8_t Entity = (USB_ControlRequest.wIndex >> 8); | ||
| 158 | uint16_t Parameter = USB_ControlRequest.wValue; | ||
| 159 | uint16_t ValueLength = USB_ControlRequest.wLength; | ||
| 160 | uint8_t Value[ValueLength]; | ||
| 161 | |||
| 162 | if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity, | ||
| 163 | Parameter, &ValueLength, Value)) | ||
| 164 | { | ||
| 165 | Endpoint_ClearSETUP(); | ||
| 166 | Endpoint_Write_Control_Stream_LE(Value, ValueLength); | ||
| 167 | Endpoint_ClearOUT(); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | break; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 176 | { | ||
| 177 | memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); | ||
| 178 | |||
| 179 | AudioInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_ISOCHRONOUS; | ||
| 180 | AudioInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_ISOCHRONOUS; | ||
| 181 | |||
| 182 | if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 183 | return false; | ||
| 184 | |||
| 185 | if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 186 | return false; | ||
| 187 | |||
| 188 | return true; | ||
| 189 | } | ||
| 190 | |||
| 191 | void Audio_Device_Event_Stub(void) | ||
| 192 | { | ||
| 193 | |||
| 194 | } | ||
| 195 | |||
| 196 | #endif | ||
| 197 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h new file mode 100644 index 000000000..ca63511b2 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h | |||
| @@ -0,0 +1,396 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB Audio 1.0 Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB Audio 1.0 Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassAudio | ||
| 41 | * \defgroup Group_USBClassAudioDevice Audio 1.0 Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassAudioDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassAudioDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _AUDIO_CLASS_DEVICE_H_ | ||
| 54 | #define _AUDIO_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/AudioClassCommon.h" | ||
| 59 | |||
| 60 | /* Enable C linkage for C++ Compilers: */ | ||
| 61 | #if defined(__cplusplus) | ||
| 62 | extern "C" { | ||
| 63 | #endif | ||
| 64 | |||
| 65 | /* Preprocessor Checks: */ | ||
| 66 | #if !defined(__INCLUDE_FROM_AUDIO_DRIVER) | ||
| 67 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* Public Interface - May be used in end-application: */ | ||
| 71 | /* Type Defines: */ | ||
| 72 | /** \brief Audio Class Device Mode Configuration and State Structure. | ||
| 73 | * | ||
| 74 | * Class state structure. An instance of this structure should be made for each Audio interface | ||
| 75 | * within the user application, and passed to each of the Audio class driver functions as the | ||
| 76 | * \c AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information. | ||
| 77 | */ | ||
| 78 | typedef struct | ||
| 79 | { | ||
| 80 | struct | ||
| 81 | { | ||
| 82 | uint8_t ControlInterfaceNumber; /**< Index of the Audio Control interface within the device this | ||
| 83 | * structure controls. | ||
| 84 | */ | ||
| 85 | uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this | ||
| 86 | * structure controls. | ||
| 87 | */ | ||
| 88 | |||
| 89 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 90 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 91 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 92 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 93 | */ | ||
| 94 | struct | ||
| 95 | { | ||
| 96 | bool InterfaceEnabled; /**< Set and cleared by the class driver to indicate if the host has enabled the streaming endpoints | ||
| 97 | * of the Audio Streaming interface. | ||
| 98 | */ | ||
| 99 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 100 | * are reset to their defaults when the interface is enumerated. | ||
| 101 | */ | ||
| 102 | } USB_ClassInfo_Audio_Device_t; | ||
| 103 | |||
| 104 | /* Function Prototypes: */ | ||
| 105 | /** Configures the endpoints of a given Audio interface, ready for use. This should be linked to the library | ||
| 106 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the | ||
| 107 | * given Audio interface is selected. | ||
| 108 | * | ||
| 109 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 110 | * | ||
| 111 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 112 | */ | ||
| 113 | bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 114 | |||
| 115 | /** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be | ||
| 116 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 117 | * | ||
| 118 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 119 | */ | ||
| 120 | void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 121 | |||
| 122 | /** Audio class driver callback for the setting and retrieval of streaming endpoint properties. This callback must be implemented | ||
| 123 | * in the user application to handle property manipulations on streaming audio endpoints. | ||
| 124 | * | ||
| 125 | * When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for | ||
| 126 | * the given endpoint index, and should return as fast as possible. When non-NULL, this value may be altered for GET operations | ||
| 127 | * to indicate the size of the retrieved data. | ||
| 128 | * | ||
| 129 | * \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value | ||
| 130 | * of the \c DataLength parameter. | ||
| 131 | * | ||
| 132 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 133 | * \param[in] EndpointProperty Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t. | ||
| 134 | * \param[in] EndpointAddress Address of the streaming endpoint whose property is being referenced. | ||
| 135 | * \param[in] EndpointControl Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t. | ||
| 136 | * \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum | ||
| 137 | * length of the retrieved data. When NULL, the function should return whether the given property | ||
| 138 | * and parameter is valid for the requested endpoint without reading or modifying the Data buffer. | ||
| 139 | * \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where | ||
| 140 | * the retrieved data is to be stored for GET operations. | ||
| 141 | * | ||
| 142 | * \return Boolean \c true if the property GET/SET was successful, \c false otherwise | ||
| 143 | */ | ||
| 144 | bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 145 | const uint8_t EndpointProperty, | ||
| 146 | const uint8_t EndpointAddress, | ||
| 147 | const uint8_t EndpointControl, | ||
| 148 | uint16_t* const DataLength, | ||
| 149 | uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1); | ||
| 150 | |||
| 151 | /** Audio class driver callback for the setting and retrieval of streaming interface properties. This callback must be implemented | ||
| 152 | * in the user application to handle property manipulations on streaming audio interfaces. | ||
| 153 | * | ||
| 154 | * When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for | ||
| 155 | * the given entity and should return as fast as possible. When non-NULL, this value may be altered for GET operations | ||
| 156 | * to indicate the size of the retrieved data. | ||
| 157 | * | ||
| 158 | * \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value | ||
| 159 | * of the \c DataLength parameter. | ||
| 160 | * | ||
| 161 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 162 | * \param[in] Property Property of the interface to get or set, a value from \ref Audio_ClassRequests_t. | ||
| 163 | * \param[in] EntityAddress Address of the audio entity whose property is being referenced. | ||
| 164 | * \param[in] Parameter Parameter of the entity to get or set, specific to each type of entity (see USB Audio specification). | ||
| 165 | * \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum | ||
| 166 | * length of the retrieved data. When NULL, the function should return whether the given property | ||
| 167 | * and parameter is valid for the requested endpoint without reading or modifying the Data buffer. | ||
| 168 | * \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where | ||
| 169 | * the retrieved data is to be stored for GET operations. | ||
| 170 | * | ||
| 171 | * \return Boolean \c true if the property GET/SET was successful, \c false otherwise | ||
| 172 | */ | ||
| 173 | bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 174 | const uint8_t Property, | ||
| 175 | const uint8_t EntityAddress, | ||
| 176 | const uint16_t Parameter, | ||
| 177 | uint16_t* const DataLength, | ||
| 178 | uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1); | ||
| 179 | |||
| 180 | /** Audio class driver event for an Audio Stream start/stop change. This event fires each time the device receives a stream enable or | ||
| 181 | * disable control request from the host, to start and stop the audio stream. The current state of the stream can be determined by the | ||
| 182 | * State.InterfaceEnabled value inside the Audio interface structure passed as a parameter. | ||
| 183 | * | ||
| 184 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 185 | */ | ||
| 186 | void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo); | ||
| 187 | |||
| 188 | /* Inline Functions: */ | ||
| 189 | /** General management task for a given Audio class interface, required for the correct operation of the interface. This should | ||
| 190 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 191 | * | ||
| 192 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 193 | */ | ||
| 194 | static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 195 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 196 | static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 197 | { | ||
| 198 | (void)AudioInterfaceInfo; | ||
| 199 | } | ||
| 200 | |||
| 201 | /** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming | ||
| 202 | * OUT endpoint ready for reading. | ||
| 203 | * | ||
| 204 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 205 | * the call will fail. | ||
| 206 | * | ||
| 207 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 208 | * | ||
| 209 | * \return Boolean \c true if the given Audio interface has a sample to be read, \c false otherwise. | ||
| 210 | */ | ||
| 211 | static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 212 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 213 | static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 214 | { | ||
| 215 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled)) | ||
| 216 | return false; | ||
| 217 | |||
| 218 | Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 219 | return Endpoint_IsOUTReceived(); | ||
| 220 | } | ||
| 221 | |||
| 222 | /** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects | ||
| 223 | * the streaming IN endpoint ready for writing. | ||
| 224 | * | ||
| 225 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 226 | * the call will fail. | ||
| 227 | * | ||
| 228 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 229 | * | ||
| 230 | * \return Boolean \c true if the given Audio interface is ready to accept the next sample, \c false otherwise. | ||
| 231 | */ | ||
| 232 | static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 233 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 234 | static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 235 | { | ||
| 236 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled)) | ||
| 237 | return false; | ||
| 238 | |||
| 239 | Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 240 | return Endpoint_IsINReady(); | ||
| 241 | } | ||
| 242 | |||
| 243 | /** Reads the next 8-bit audio sample from the current audio interface. | ||
| 244 | * | ||
| 245 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||
| 246 | * that the correct endpoint is selected and ready for data. | ||
| 247 | * | ||
| 248 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 249 | * | ||
| 250 | * \return Signed 8-bit audio sample from the audio interface. | ||
| 251 | */ | ||
| 252 | static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 253 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 254 | static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 255 | { | ||
| 256 | int8_t Sample; | ||
| 257 | |||
| 258 | (void)AudioInterfaceInfo; | ||
| 259 | |||
| 260 | Sample = Endpoint_Read_8(); | ||
| 261 | |||
| 262 | if (!(Endpoint_BytesInEndpoint())) | ||
| 263 | Endpoint_ClearOUT(); | ||
| 264 | |||
| 265 | return Sample; | ||
| 266 | } | ||
| 267 | |||
| 268 | /** Reads the next 16-bit audio sample from the current audio interface. | ||
| 269 | * | ||
| 270 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||
| 271 | * that the correct endpoint is selected and ready for data. | ||
| 272 | * | ||
| 273 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 274 | * | ||
| 275 | * \return Signed 16-bit audio sample from the audio interface. | ||
| 276 | */ | ||
| 277 | static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 278 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 279 | static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 280 | { | ||
| 281 | int16_t Sample; | ||
| 282 | |||
| 283 | (void)AudioInterfaceInfo; | ||
| 284 | |||
| 285 | Sample = (int16_t)Endpoint_Read_16_LE(); | ||
| 286 | |||
| 287 | if (!(Endpoint_BytesInEndpoint())) | ||
| 288 | Endpoint_ClearOUT(); | ||
| 289 | |||
| 290 | return Sample; | ||
| 291 | } | ||
| 292 | |||
| 293 | /** Reads the next 24-bit audio sample from the current audio interface. | ||
| 294 | * | ||
| 295 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure | ||
| 296 | * that the correct endpoint is selected and ready for data. | ||
| 297 | * | ||
| 298 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 299 | * | ||
| 300 | * \return Signed 24-bit audio sample from the audio interface. | ||
| 301 | */ | ||
| 302 | static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 303 | ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 304 | static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 305 | { | ||
| 306 | int32_t Sample; | ||
| 307 | |||
| 308 | (void)AudioInterfaceInfo; | ||
| 309 | |||
| 310 | Sample = (((uint32_t)Endpoint_Read_8() << 16) | Endpoint_Read_16_LE()); | ||
| 311 | |||
| 312 | if (!(Endpoint_BytesInEndpoint())) | ||
| 313 | Endpoint_ClearOUT(); | ||
| 314 | |||
| 315 | return Sample; | ||
| 316 | } | ||
| 317 | |||
| 318 | /** Writes the next 8-bit audio sample to the current audio interface. | ||
| 319 | * | ||
| 320 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||
| 321 | * ensure that the correct endpoint is selected and ready for data. | ||
| 322 | * | ||
| 323 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 324 | * \param[in] Sample Signed 8-bit audio sample. | ||
| 325 | */ | ||
| 326 | static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 327 | const int8_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 328 | static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 329 | const int8_t Sample) | ||
| 330 | { | ||
| 331 | Endpoint_Write_8(Sample); | ||
| 332 | |||
| 333 | if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||
| 334 | Endpoint_ClearIN(); | ||
| 335 | } | ||
| 336 | |||
| 337 | /** Writes the next 16-bit audio sample to the current audio interface. | ||
| 338 | * | ||
| 339 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||
| 340 | * ensure that the correct endpoint is selected and ready for data. | ||
| 341 | * | ||
| 342 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 343 | * \param[in] Sample Signed 16-bit audio sample. | ||
| 344 | */ | ||
| 345 | static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 346 | const int16_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 347 | static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 348 | const int16_t Sample) | ||
| 349 | { | ||
| 350 | Endpoint_Write_16_LE(Sample); | ||
| 351 | |||
| 352 | if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||
| 353 | Endpoint_ClearIN(); | ||
| 354 | } | ||
| 355 | |||
| 356 | /** Writes the next 24-bit audio sample to the current audio interface. | ||
| 357 | * | ||
| 358 | * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to | ||
| 359 | * ensure that the correct endpoint is selected and ready for data. | ||
| 360 | * | ||
| 361 | * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. | ||
| 362 | * \param[in] Sample Signed 24-bit audio sample. | ||
| 363 | */ | ||
| 364 | static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 365 | const int32_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; | ||
| 366 | static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, | ||
| 367 | const int32_t Sample) | ||
| 368 | { | ||
| 369 | Endpoint_Write_16_LE(Sample); | ||
| 370 | Endpoint_Write_8(Sample >> 16); | ||
| 371 | |||
| 372 | if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size) | ||
| 373 | Endpoint_ClearIN(); | ||
| 374 | } | ||
| 375 | |||
| 376 | /* Private Interface - For use in library only: */ | ||
| 377 | #if !defined(__DOXYGEN__) | ||
| 378 | /* Function Prototypes: */ | ||
| 379 | #if defined(__INCLUDE_FROM_AUDIO_DEVICE_C) | ||
| 380 | void Audio_Device_Event_Stub(void) ATTR_CONST; | ||
| 381 | |||
| 382 | void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) | ||
| 383 | ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(Audio_Device_Event_Stub); | ||
| 384 | #endif | ||
| 385 | |||
| 386 | #endif | ||
| 387 | |||
| 388 | /* Disable C linkage for C++ Compilers: */ | ||
| 389 | #if defined(__cplusplus) | ||
| 390 | } | ||
| 391 | #endif | ||
| 392 | |||
| 393 | #endif | ||
| 394 | |||
| 395 | /** @} */ | ||
| 396 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c new file mode 100644 index 000000000..867548c00 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c | |||
| @@ -0,0 +1,362 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_CDC_DRIVER | ||
| 37 | #define __INCLUDE_FROM_CDC_DEVICE_C | ||
| 38 | #include "CDCClassDevice.h" | ||
| 39 | |||
| 40 | void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 41 | { | ||
| 42 | if (!(Endpoint_IsSETUPReceived())) | ||
| 43 | return; | ||
| 44 | |||
| 45 | if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber) | ||
| 46 | return; | ||
| 47 | |||
| 48 | switch (USB_ControlRequest.bRequest) | ||
| 49 | { | ||
| 50 | case CDC_REQ_GetLineEncoding: | ||
| 51 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 52 | { | ||
| 53 | Endpoint_ClearSETUP(); | ||
| 54 | |||
| 55 | while (!(Endpoint_IsINReady())); | ||
| 56 | |||
| 57 | Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS); | ||
| 58 | Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat); | ||
| 59 | Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType); | ||
| 60 | Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits); | ||
| 61 | |||
| 62 | Endpoint_ClearIN(); | ||
| 63 | Endpoint_ClearStatusStage(); | ||
| 64 | } | ||
| 65 | |||
| 66 | break; | ||
| 67 | case CDC_REQ_SetLineEncoding: | ||
| 68 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 69 | { | ||
| 70 | Endpoint_ClearSETUP(); | ||
| 71 | |||
| 72 | while (!(Endpoint_IsOUTReceived())) | ||
| 73 | { | ||
| 74 | if (USB_DeviceState == DEVICE_STATE_Unattached) | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | |||
| 78 | CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE(); | ||
| 79 | CDCInterfaceInfo->State.LineEncoding.CharFormat = Endpoint_Read_8(); | ||
| 80 | CDCInterfaceInfo->State.LineEncoding.ParityType = Endpoint_Read_8(); | ||
| 81 | CDCInterfaceInfo->State.LineEncoding.DataBits = Endpoint_Read_8(); | ||
| 82 | |||
| 83 | Endpoint_ClearOUT(); | ||
| 84 | Endpoint_ClearStatusStage(); | ||
| 85 | |||
| 86 | EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo); | ||
| 87 | } | ||
| 88 | |||
| 89 | break; | ||
| 90 | case CDC_REQ_SetControlLineState: | ||
| 91 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 92 | { | ||
| 93 | Endpoint_ClearSETUP(); | ||
| 94 | Endpoint_ClearStatusStage(); | ||
| 95 | |||
| 96 | CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue; | ||
| 97 | |||
| 98 | EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo); | ||
| 99 | } | ||
| 100 | |||
| 101 | break; | ||
| 102 | case CDC_REQ_SendBreak: | ||
| 103 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 104 | { | ||
| 105 | Endpoint_ClearSETUP(); | ||
| 106 | Endpoint_ClearStatusStage(); | ||
| 107 | |||
| 108 | EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue); | ||
| 109 | } | ||
| 110 | |||
| 111 | break; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 116 | { | ||
| 117 | memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); | ||
| 118 | |||
| 119 | CDCInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK; | ||
| 120 | CDCInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||
| 121 | CDCInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT; | ||
| 122 | |||
| 123 | if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 124 | return false; | ||
| 125 | |||
| 126 | if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 127 | return false; | ||
| 128 | |||
| 129 | if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1))) | ||
| 130 | return false; | ||
| 131 | |||
| 132 | return true; | ||
| 133 | } | ||
| 134 | |||
| 135 | void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 136 | { | ||
| 137 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 138 | return; | ||
| 139 | |||
| 140 | #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||
| 141 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 142 | |||
| 143 | if (Endpoint_IsINReady()) | ||
| 144 | CDC_Device_Flush(CDCInterfaceInfo); | ||
| 145 | #endif | ||
| 146 | } | ||
| 147 | |||
| 148 | uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 149 | const char* const String) | ||
| 150 | { | ||
| 151 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 152 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 153 | |||
| 154 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 155 | return Endpoint_Write_Stream_LE(String, strlen(String), NULL); | ||
| 156 | } | ||
| 157 | |||
| 158 | uint8_t CDC_Device_SendString_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 159 | const char* const String) | ||
| 160 | { | ||
| 161 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 162 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 163 | |||
| 164 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 165 | return Endpoint_Write_PStream_LE(String, strlen_P(String), NULL); | ||
| 166 | } | ||
| 167 | |||
| 168 | uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 169 | const void* const Buffer, | ||
| 170 | const uint16_t Length) | ||
| 171 | { | ||
| 172 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 173 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 174 | |||
| 175 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 176 | return Endpoint_Write_Stream_LE(Buffer, Length, NULL); | ||
| 177 | } | ||
| 178 | |||
| 179 | uint8_t CDC_Device_SendData_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 180 | const void* const Buffer, | ||
| 181 | const uint16_t Length) | ||
| 182 | { | ||
| 183 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 184 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 185 | |||
| 186 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 187 | return Endpoint_Write_PStream_LE(Buffer, Length, NULL); | ||
| 188 | } | ||
| 189 | |||
| 190 | uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 191 | const uint8_t Data) | ||
| 192 | { | ||
| 193 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 194 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 195 | |||
| 196 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 197 | |||
| 198 | if (!(Endpoint_IsReadWriteAllowed())) | ||
| 199 | { | ||
| 200 | Endpoint_ClearIN(); | ||
| 201 | |||
| 202 | uint8_t ErrorCode; | ||
| 203 | |||
| 204 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 205 | return ErrorCode; | ||
| 206 | } | ||
| 207 | |||
| 208 | Endpoint_Write_8(Data); | ||
| 209 | return ENDPOINT_READYWAIT_NoError; | ||
| 210 | } | ||
| 211 | |||
| 212 | uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 213 | { | ||
| 214 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 215 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 216 | |||
| 217 | uint8_t ErrorCode; | ||
| 218 | |||
| 219 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 220 | |||
| 221 | if (!(Endpoint_BytesInEndpoint())) | ||
| 222 | return ENDPOINT_READYWAIT_NoError; | ||
| 223 | |||
| 224 | bool BankFull = !(Endpoint_IsReadWriteAllowed()); | ||
| 225 | |||
| 226 | Endpoint_ClearIN(); | ||
| 227 | |||
| 228 | if (BankFull) | ||
| 229 | { | ||
| 230 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 231 | return ErrorCode; | ||
| 232 | |||
| 233 | Endpoint_ClearIN(); | ||
| 234 | } | ||
| 235 | |||
| 236 | return ENDPOINT_READYWAIT_NoError; | ||
| 237 | } | ||
| 238 | |||
| 239 | uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 240 | { | ||
| 241 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 242 | return 0; | ||
| 243 | |||
| 244 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 245 | |||
| 246 | if (Endpoint_IsOUTReceived()) | ||
| 247 | { | ||
| 248 | if (!(Endpoint_BytesInEndpoint())) | ||
| 249 | { | ||
| 250 | Endpoint_ClearOUT(); | ||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | else | ||
| 254 | { | ||
| 255 | return Endpoint_BytesInEndpoint(); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | else | ||
| 259 | { | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 265 | { | ||
| 266 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 267 | return -1; | ||
| 268 | |||
| 269 | int16_t ReceivedByte = -1; | ||
| 270 | |||
| 271 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 272 | |||
| 273 | if (Endpoint_IsOUTReceived()) | ||
| 274 | { | ||
| 275 | if (Endpoint_BytesInEndpoint()) | ||
| 276 | ReceivedByte = Endpoint_Read_8(); | ||
| 277 | |||
| 278 | if (!(Endpoint_BytesInEndpoint())) | ||
| 279 | Endpoint_ClearOUT(); | ||
| 280 | } | ||
| 281 | |||
| 282 | return ReceivedByte; | ||
| 283 | } | ||
| 284 | |||
| 285 | void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 286 | { | ||
| 287 | if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) | ||
| 288 | return; | ||
| 289 | |||
| 290 | Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpoint.Address); | ||
| 291 | |||
| 292 | USB_Request_Header_t Notification = (USB_Request_Header_t) | ||
| 293 | { | ||
| 294 | .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), | ||
| 295 | .bRequest = CDC_NOTIF_SerialState, | ||
| 296 | .wValue = CPU_TO_LE16(0), | ||
| 297 | .wIndex = CPU_TO_LE16(0), | ||
| 298 | .wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)), | ||
| 299 | }; | ||
| 300 | |||
| 301 | Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL); | ||
| 302 | Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost, | ||
| 303 | sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), | ||
| 304 | NULL); | ||
| 305 | Endpoint_ClearIN(); | ||
| 306 | } | ||
| 307 | |||
| 308 | #if defined(FDEV_SETUP_STREAM) | ||
| 309 | void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 310 | FILE* const Stream) | ||
| 311 | { | ||
| 312 | *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW); | ||
| 313 | fdev_set_udata(Stream, CDCInterfaceInfo); | ||
| 314 | } | ||
| 315 | |||
| 316 | void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 317 | FILE* const Stream) | ||
| 318 | { | ||
| 319 | *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW); | ||
| 320 | fdev_set_udata(Stream, CDCInterfaceInfo); | ||
| 321 | } | ||
| 322 | |||
| 323 | static int CDC_Device_putchar(char c, | ||
| 324 | FILE* Stream) | ||
| 325 | { | ||
| 326 | return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int CDC_Device_getchar(FILE* Stream) | ||
| 330 | { | ||
| 331 | int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream)); | ||
| 332 | |||
| 333 | if (ReceivedByte < 0) | ||
| 334 | return _FDEV_EOF; | ||
| 335 | |||
| 336 | return ReceivedByte; | ||
| 337 | } | ||
| 338 | |||
| 339 | static int CDC_Device_getchar_Blocking(FILE* Stream) | ||
| 340 | { | ||
| 341 | int16_t ReceivedByte; | ||
| 342 | |||
| 343 | while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0) | ||
| 344 | { | ||
| 345 | if (USB_DeviceState == DEVICE_STATE_Unattached) | ||
| 346 | return _FDEV_EOF; | ||
| 347 | |||
| 348 | CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream)); | ||
| 349 | USB_USBTask(); | ||
| 350 | } | ||
| 351 | |||
| 352 | return ReceivedByte; | ||
| 353 | } | ||
| 354 | #endif | ||
| 355 | |||
| 356 | void CDC_Device_Event_Stub(void) | ||
| 357 | { | ||
| 358 | |||
| 359 | } | ||
| 360 | |||
| 361 | #endif | ||
| 362 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h new file mode 100644 index 000000000..9d5c4e5a0 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h | |||
| @@ -0,0 +1,386 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB CDC Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB CDC Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassCDC | ||
| 41 | * \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassCDCDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassCDCDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the CDC USB Class driver. | ||
| 49 | * | ||
| 50 | * \note There are several major drawbacks to the CDC-ACM standard USB class, however | ||
| 51 | * it is very standardized and thus usually available as a built-in driver on | ||
| 52 | * most platforms, and so is a better choice than a proprietary serial class. | ||
| 53 | * | ||
| 54 | * One major issue with CDC-ACM is that it requires two Interface descriptors, | ||
| 55 | * which will upset most hosts when part of a multi-function "Composite" USB | ||
| 56 | * device. This is because each interface will be loaded into a separate driver | ||
| 57 | * instance, causing the two interfaces be become unlinked. To prevent this, you | ||
| 58 | * should use the "Interface Association Descriptor" addendum to the USB 2.0 standard | ||
| 59 | * which is available on most OSes when creating Composite devices. | ||
| 60 | * | ||
| 61 | * Another major oversight is that there is no mechanism for the host to notify the | ||
| 62 | * device that there is a data sink on the host side ready to accept data. This | ||
| 63 | * means that the device may try to send data while the host isn't listening, causing | ||
| 64 | * lengthy blocking timeouts in the transmission routines. It is thus highly recommended | ||
| 65 | * that the virtual serial line DTR (Data Terminal Ready) signal be used where possible | ||
| 66 | * to determine if a host application is ready for data. | ||
| 67 | * | ||
| 68 | * @{ | ||
| 69 | */ | ||
| 70 | |||
| 71 | #ifndef _CDC_CLASS_DEVICE_H_ | ||
| 72 | #define _CDC_CLASS_DEVICE_H_ | ||
| 73 | |||
| 74 | /* Includes: */ | ||
| 75 | #include "../../USB.h" | ||
| 76 | #include "../Common/CDCClassCommon.h" | ||
| 77 | |||
| 78 | #include <stdio.h> | ||
| 79 | |||
| 80 | /* Enable C linkage for C++ Compilers: */ | ||
| 81 | #if defined(__cplusplus) | ||
| 82 | extern "C" { | ||
| 83 | #endif | ||
| 84 | |||
| 85 | /* Preprocessor Checks: */ | ||
| 86 | #if !defined(__INCLUDE_FROM_CDC_DRIVER) | ||
| 87 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 88 | #endif | ||
| 89 | |||
| 90 | /* Public Interface - May be used in end-application: */ | ||
| 91 | /* Type Defines: */ | ||
| 92 | /** \brief CDC Class Device Mode Configuration and State Structure. | ||
| 93 | * | ||
| 94 | * Class state structure. An instance of this structure should be made for each CDC interface | ||
| 95 | * within the user application, and passed to each of the CDC class driver functions as the | ||
| 96 | * CDCInterfaceInfo parameter. This stores each CDC interface's configuration and state information. | ||
| 97 | */ | ||
| 98 | typedef struct | ||
| 99 | { | ||
| 100 | struct | ||
| 101 | { | ||
| 102 | uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */ | ||
| 103 | |||
| 104 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 105 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 106 | USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */ | ||
| 107 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 108 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 109 | */ | ||
| 110 | struct | ||
| 111 | { | ||
| 112 | struct | ||
| 113 | { | ||
| 114 | uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_* | ||
| 115 | * masks. This value is updated each time \ref CDC_Device_USBTask() is called. | ||
| 116 | */ | ||
| 117 | uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_* | ||
| 118 | * masks - to notify the host of changes to these values, call the | ||
| 119 | * \ref CDC_Device_SendControlLineStateChange() function. | ||
| 120 | */ | ||
| 121 | } ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */ | ||
| 122 | |||
| 123 | CDC_LineEncoding_t LineEncoding; /**< Line encoding used in the virtual serial port, for the device's information. | ||
| 124 | * This is generally only used if the virtual serial port data is to be | ||
| 125 | * reconstructed on a physical UART. | ||
| 126 | */ | ||
| 127 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 128 | * are reset to their defaults when the interface is enumerated. | ||
| 129 | */ | ||
| 130 | } USB_ClassInfo_CDC_Device_t; | ||
| 131 | |||
| 132 | /* Function Prototypes: */ | ||
| 133 | /** Configures the endpoints of a given CDC interface, ready for use. This should be linked to the library | ||
| 134 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing | ||
| 135 | * the given CDC interface is selected. | ||
| 136 | * | ||
| 137 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 138 | * | ||
| 139 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 140 | */ | ||
| 141 | bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 142 | |||
| 143 | /** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be | ||
| 144 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 145 | * | ||
| 146 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 147 | */ | ||
| 148 | void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 149 | |||
| 150 | /** General management task for a given CDC class interface, required for the correct operation of the interface. This should | ||
| 151 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 152 | * | ||
| 153 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 154 | */ | ||
| 155 | void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 156 | |||
| 157 | /** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a | ||
| 158 | * line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the | ||
| 159 | * user program by declaring a handler function with the same name and parameters listed here. The new line encoding | ||
| 160 | * settings are available in the \c LineEncoding structure inside the CDC interface structure passed as a parameter. | ||
| 161 | * | ||
| 162 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 163 | */ | ||
| 164 | void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 165 | |||
| 166 | /** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a | ||
| 167 | * control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the | ||
| 168 | * user program by declaring a handler function with the same name and parameters listed here. The new control line states | ||
| 169 | * are available in the \c ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as | ||
| 170 | * a mask of \c CDC_CONTROL_LINE_OUT_* masks. | ||
| 171 | * | ||
| 172 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 173 | */ | ||
| 174 | void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 175 | |||
| 176 | /** CDC class driver event for a send break request sent to the device from the host. This is generally used to separate | ||
| 177 | * data or to indicate a special condition to the receiving device. | ||
| 178 | * | ||
| 179 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 180 | * \param[in] Duration Duration of the break that has been sent by the host, in milliseconds. | ||
| 181 | */ | ||
| 182 | void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 183 | const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1); | ||
| 184 | |||
| 185 | /** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is | ||
| 186 | * called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank | ||
| 187 | * becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows | ||
| 188 | * for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 189 | * | ||
| 190 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 191 | * the call will fail. | ||
| 192 | * | ||
| 193 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 194 | * \param[in] Buffer Pointer to a buffer containing the data to send to the device. | ||
| 195 | * \param[in] Length Length of the data to send to the host. | ||
| 196 | * | ||
| 197 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 198 | */ | ||
| 199 | uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 200 | const void* const Buffer, | ||
| 201 | const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 202 | |||
| 203 | /** Sends a given data buffer from PROGMEM space to the attached USB host, if connected. If a host is not connected when the | ||
| 204 | * function is called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint | ||
| 205 | * bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows | ||
| 206 | * for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 207 | * | ||
| 208 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 209 | * the call will fail. | ||
| 210 | * | ||
| 211 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 212 | * \param[in] Buffer Pointer to a buffer containing the data to send to the device. | ||
| 213 | * \param[in] Length Length of the data to send to the host. | ||
| 214 | * | ||
| 215 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 216 | */ | ||
| 217 | uint8_t CDC_Device_SendData_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 218 | const void* const Buffer, | ||
| 219 | const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 220 | |||
| 221 | /** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when | ||
| 222 | * the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||
| 223 | * the endpoint bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to | ||
| 224 | * the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 225 | * | ||
| 226 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 227 | * the call will fail. | ||
| 228 | * | ||
| 229 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 230 | * \param[in] String Pointer to the null terminated string to send to the host. | ||
| 231 | * | ||
| 232 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 233 | */ | ||
| 234 | uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 235 | const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 236 | |||
| 237 | /** Sends a given null terminated string from PROGMEM space to the attached USB host, if connected. If a host is not connected | ||
| 238 | * when the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||
| 239 | * the endpoint bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to | ||
| 240 | * the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 241 | * | ||
| 242 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 243 | * the call will fail. | ||
| 244 | * | ||
| 245 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 246 | * \param[in] String Pointer to the null terminated string to send to the host. | ||
| 247 | * | ||
| 248 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 249 | */ | ||
| 250 | uint8_t CDC_Device_SendString_P(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 251 | const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 252 | |||
| 253 | /** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the | ||
| 254 | * byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the | ||
| 255 | * \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be | ||
| 256 | * packed into a single endpoint packet, increasing data throughput. | ||
| 257 | * | ||
| 258 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 259 | * the call will fail. | ||
| 260 | * | ||
| 261 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 262 | * \param[in] Data Byte of data to send to the host. | ||
| 263 | * | ||
| 264 | * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||
| 265 | */ | ||
| 266 | uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 267 | const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1); | ||
| 268 | |||
| 269 | /** Determines the number of bytes received by the CDC interface from the host, waiting to be read. This indicates the number | ||
| 270 | * of bytes in the OUT endpoint bank only, and thus the number of calls to \ref CDC_Device_ReceiveByte() which are guaranteed to | ||
| 271 | * succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint | ||
| 272 | * bank will not be released back to the USB controller until all bytes are read. | ||
| 273 | * | ||
| 274 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 275 | * the call will fail. | ||
| 276 | * | ||
| 277 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 278 | * | ||
| 279 | * \return Total number of buffered bytes received from the host. | ||
| 280 | */ | ||
| 281 | uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 282 | |||
| 283 | /** 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 | ||
| 284 | * returns a negative value. The \ref CDC_Device_BytesReceived() function may be queried in advance to determine how many | ||
| 285 | * bytes are currently buffered in the CDC interface's data receive endpoint bank, and thus how many repeated calls to this | ||
| 286 | * function which are guaranteed to succeed. | ||
| 287 | * | ||
| 288 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 289 | * the call will fail. | ||
| 290 | * | ||
| 291 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 292 | * | ||
| 293 | * \return Next received byte from the host, or a negative value if no data received. | ||
| 294 | */ | ||
| 295 | int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 296 | |||
| 297 | /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared. | ||
| 298 | * | ||
| 299 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 300 | * the call will fail. | ||
| 301 | * | ||
| 302 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 303 | * | ||
| 304 | * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||
| 305 | */ | ||
| 306 | uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 307 | |||
| 308 | /** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial | ||
| 309 | * control lines (DCD, DSR, etc.) have changed states, or to give BREAK notifications to the host. Line states persist | ||
| 310 | * until they are cleared via a second notification. This should be called each time the CDC class driver's | ||
| 311 | * \c ControlLineStates.DeviceToHost value is updated to push the new states to the USB host. | ||
| 312 | * | ||
| 313 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 314 | * the call will fail. | ||
| 315 | * | ||
| 316 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 317 | */ | ||
| 318 | void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 319 | |||
| 320 | #if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__) | ||
| 321 | /** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular | ||
| 322 | * functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created | ||
| 323 | * stream is bidirectional and can be used for both input and output functions. | ||
| 324 | * | ||
| 325 | * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single | ||
| 326 | * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may | ||
| 327 | * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own | ||
| 328 | * line buffering. | ||
| 329 | * | ||
| 330 | * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions | ||
| 331 | * to the given CDC interface. | ||
| 332 | * \n\n | ||
| 333 | * | ||
| 334 | * \note This function is not available on all microcontroller architectures. | ||
| 335 | * | ||
| 336 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 337 | * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. | ||
| 338 | */ | ||
| 339 | void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 340 | FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 341 | |||
| 342 | /** Identical to \ref CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates | ||
| 343 | * the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications. | ||
| 344 | * | ||
| 345 | * \note This function is not available on all microcontroller architectures. | ||
| 346 | * | ||
| 347 | * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. | ||
| 348 | * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. | ||
| 349 | */ | ||
| 350 | void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 351 | FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 352 | #endif | ||
| 353 | |||
| 354 | /* Private Interface - For use in library only: */ | ||
| 355 | #if !defined(__DOXYGEN__) | ||
| 356 | /* Function Prototypes: */ | ||
| 357 | #if defined(__INCLUDE_FROM_CDC_DEVICE_C) | ||
| 358 | #if defined(FDEV_SETUP_STREAM) | ||
| 359 | static int CDC_Device_putchar(char c, | ||
| 360 | FILE* Stream) ATTR_NON_NULL_PTR_ARG(2); | ||
| 361 | static int CDC_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||
| 362 | static int CDC_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||
| 363 | #endif | ||
| 364 | |||
| 365 | void CDC_Device_Event_Stub(void) ATTR_CONST; | ||
| 366 | |||
| 367 | void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 368 | ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); | ||
| 369 | void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) | ||
| 370 | ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); | ||
| 371 | void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, | ||
| 372 | const uint8_t Duration) ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) | ||
| 373 | ATTR_ALIAS(CDC_Device_Event_Stub); | ||
| 374 | #endif | ||
| 375 | |||
| 376 | #endif | ||
| 377 | |||
| 378 | /* Disable C linkage for C++ Compilers: */ | ||
| 379 | #if defined(__cplusplus) | ||
| 380 | } | ||
| 381 | #endif | ||
| 382 | |||
| 383 | #endif | ||
| 384 | |||
| 385 | /** @} */ | ||
| 386 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c new file mode 100644 index 000000000..a8a6e8b50 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_HID_DRIVER | ||
| 37 | #define __INCLUDE_FROM_HID_DEVICE_C | ||
| 38 | #include "HIDClassDevice.h" | ||
| 39 | |||
| 40 | void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||
| 41 | { | ||
| 42 | if (!(Endpoint_IsSETUPReceived())) | ||
| 43 | return; | ||
| 44 | |||
| 45 | if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber) | ||
| 46 | return; | ||
| 47 | |||
| 48 | switch (USB_ControlRequest.bRequest) | ||
| 49 | { | ||
| 50 | case HID_REQ_GetReport: | ||
| 51 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 52 | { | ||
| 53 | uint16_t ReportSize = 0; | ||
| 54 | uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF); | ||
| 55 | uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1; | ||
| 56 | uint8_t ReportData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; | ||
| 57 | |||
| 58 | memset(ReportData, 0, sizeof(ReportData)); | ||
| 59 | |||
| 60 | CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType, ReportData, &ReportSize); | ||
| 61 | |||
| 62 | if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL) | ||
| 63 | { | ||
| 64 | memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportData, | ||
| 65 | HIDInterfaceInfo->Config.PrevReportINBufferSize); | ||
| 66 | } | ||
| 67 | |||
| 68 | Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); | ||
| 69 | |||
| 70 | Endpoint_ClearSETUP(); | ||
| 71 | |||
| 72 | if (ReportID) | ||
| 73 | Endpoint_Write_8(ReportID); | ||
| 74 | |||
| 75 | Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); | ||
| 76 | Endpoint_ClearOUT(); | ||
| 77 | } | ||
| 78 | |||
| 79 | break; | ||
| 80 | case HID_REQ_SetReport: | ||
| 81 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 82 | { | ||
| 83 | uint16_t ReportSize = USB_ControlRequest.wLength; | ||
| 84 | uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF); | ||
| 85 | uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1; | ||
| 86 | uint8_t ReportData[ReportSize]; | ||
| 87 | |||
| 88 | Endpoint_ClearSETUP(); | ||
| 89 | Endpoint_Read_Control_Stream_LE(ReportData, ReportSize); | ||
| 90 | Endpoint_ClearIN(); | ||
| 91 | |||
| 92 | CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportType, | ||
| 93 | &ReportData[ReportID ? 1 : 0], ReportSize - (ReportID ? 1 : 0)); | ||
| 94 | } | ||
| 95 | |||
| 96 | break; | ||
| 97 | case HID_REQ_GetProtocol: | ||
| 98 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 99 | { | ||
| 100 | Endpoint_ClearSETUP(); | ||
| 101 | while (!(Endpoint_IsINReady())); | ||
| 102 | Endpoint_Write_8(HIDInterfaceInfo->State.UsingReportProtocol); | ||
| 103 | Endpoint_ClearIN(); | ||
| 104 | Endpoint_ClearStatusStage(); | ||
| 105 | } | ||
| 106 | |||
| 107 | break; | ||
| 108 | case HID_REQ_SetProtocol: | ||
| 109 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 110 | { | ||
| 111 | Endpoint_ClearSETUP(); | ||
| 112 | Endpoint_ClearStatusStage(); | ||
| 113 | |||
| 114 | HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | ||
| 115 | } | ||
| 116 | |||
| 117 | break; | ||
| 118 | case HID_REQ_SetIdle: | ||
| 119 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 120 | { | ||
| 121 | Endpoint_ClearSETUP(); | ||
| 122 | Endpoint_ClearStatusStage(); | ||
| 123 | |||
| 124 | HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6); | ||
| 125 | } | ||
| 126 | |||
| 127 | break; | ||
| 128 | case HID_REQ_GetIdle: | ||
| 129 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 130 | { | ||
| 131 | Endpoint_ClearSETUP(); | ||
| 132 | while (!(Endpoint_IsINReady())); | ||
| 133 | Endpoint_Write_8(HIDInterfaceInfo->State.IdleCount >> 2); | ||
| 134 | Endpoint_ClearIN(); | ||
| 135 | Endpoint_ClearStatusStage(); | ||
| 136 | } | ||
| 137 | |||
| 138 | break; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||
| 143 | { | ||
| 144 | memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); | ||
| 145 | HIDInterfaceInfo->State.UsingReportProtocol = true; | ||
| 146 | HIDInterfaceInfo->State.IdleCount = 500; | ||
| 147 | |||
| 148 | HIDInterfaceInfo->Config.ReportINEndpoint.Type = EP_TYPE_INTERRUPT; | ||
| 149 | |||
| 150 | if (!(Endpoint_ConfigureEndpointTable(&HIDInterfaceInfo->Config.ReportINEndpoint, 1))) | ||
| 151 | return false; | ||
| 152 | |||
| 153 | return true; | ||
| 154 | } | ||
| 155 | |||
| 156 | void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||
| 157 | { | ||
| 158 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 159 | return; | ||
| 160 | |||
| 161 | if (HIDInterfaceInfo->State.PrevFrameNum == USB_Device_GetFrameNumber()) | ||
| 162 | { | ||
| 163 | #if defined(USB_DEVICE_OPT_LOWSPEED) | ||
| 164 | if (!(USB_Options & USB_DEVICE_OPT_LOWSPEED)) | ||
| 165 | return; | ||
| 166 | #else | ||
| 167 | return; | ||
| 168 | #endif | ||
| 169 | } | ||
| 170 | |||
| 171 | Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address); | ||
| 172 | |||
| 173 | if (Endpoint_IsReadWriteAllowed()) | ||
| 174 | { | ||
| 175 | uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; | ||
| 176 | uint8_t ReportID = 0; | ||
| 177 | uint16_t ReportINSize = 0; | ||
| 178 | |||
| 179 | memset(ReportINData, 0, sizeof(ReportINData)); | ||
| 180 | |||
| 181 | bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, HID_REPORT_ITEM_In, | ||
| 182 | ReportINData, &ReportINSize); | ||
| 183 | bool StatesChanged = false; | ||
| 184 | bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining)); | ||
| 185 | |||
| 186 | if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL) | ||
| 187 | { | ||
| 188 | StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0); | ||
| 189 | memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize); | ||
| 190 | } | ||
| 191 | |||
| 192 | if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed)) | ||
| 193 | { | ||
| 194 | HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount; | ||
| 195 | |||
| 196 | Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address); | ||
| 197 | |||
| 198 | if (ReportID) | ||
| 199 | Endpoint_Write_8(ReportID); | ||
| 200 | |||
| 201 | Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL); | ||
| 202 | |||
| 203 | Endpoint_ClearIN(); | ||
| 204 | } | ||
| 205 | |||
| 206 | HIDInterfaceInfo->State.PrevFrameNum = USB_Device_GetFrameNumber(); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | #endif | ||
| 211 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h new file mode 100644 index 000000000..ae628c87d --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB HID Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB HID Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassHID | ||
| 41 | * \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassHIDDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassHIDDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the HID USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _HID_CLASS_DEVICE_H_ | ||
| 54 | #define _HID_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/HIDClassCommon.h" | ||
| 59 | |||
| 60 | /* Enable C linkage for C++ Compilers: */ | ||
| 61 | #if defined(__cplusplus) | ||
| 62 | extern "C" { | ||
| 63 | #endif | ||
| 64 | |||
| 65 | /* Preprocessor Checks: */ | ||
| 66 | #if !defined(__INCLUDE_FROM_HID_DRIVER) | ||
| 67 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* Public Interface - May be used in end-application: */ | ||
| 71 | /* Type Defines: */ | ||
| 72 | /** \brief HID Class Device Mode Configuration and State Structure. | ||
| 73 | * | ||
| 74 | * Class state structure. An instance of this structure should be made for each HID interface | ||
| 75 | * within the user application, and passed to each of the HID class driver functions as the | ||
| 76 | * \c HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information. | ||
| 77 | * | ||
| 78 | * \note Due to technical limitations, the HID device class driver does not utilize a separate OUT | ||
| 79 | * endpoint for host->device communications. Instead, the host->device data (if any) is sent to | ||
| 80 | * the device via the control endpoint. | ||
| 81 | */ | ||
| 82 | typedef struct | ||
| 83 | { | ||
| 84 | struct | ||
| 85 | { | ||
| 86 | uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */ | ||
| 87 | |||
| 88 | USB_Endpoint_Table_t ReportINEndpoint; /**< Data IN HID report endpoint configuration table. */ | ||
| 89 | |||
| 90 | void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be | ||
| 91 | * stored by the driver, for comparison purposes to detect report changes that | ||
| 92 | * must be sent immediately to the host. This should point to a buffer big enough | ||
| 93 | * to hold the largest HID input report sent from the HID interface. If this is set | ||
| 94 | * to \c NULL, it is up to the user to force transfers when needed in the | ||
| 95 | * \ref CALLBACK_HID_Device_CreateHIDReport() callback function. | ||
| 96 | * | ||
| 97 | * \note Due to the single buffer, the internal driver can only correctly compare | ||
| 98 | * subsequent reports with identical report IDs. In multiple report devices, | ||
| 99 | * this buffer should be set to \c NULL and the decision to send reports made | ||
| 100 | * by the user application instead. | ||
| 101 | */ | ||
| 102 | uint8_t PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a | ||
| 103 | * second buffer of the same size within the driver so that subsequent reports | ||
| 104 | * can be compared. If the user app is to determine when reports are to be sent | ||
| 105 | * exclusively (i.e. \c PrevReportINBuffer is \c NULL) this value must still be | ||
| 106 | * set to the size of the largest report the device can issue to the host. | ||
| 107 | */ | ||
| 108 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 109 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 110 | */ | ||
| 111 | struct | ||
| 112 | { | ||
| 113 | bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode. */ | ||
| 114 | uint16_t PrevFrameNum; /**< Frame number of the previous HID report packet opportunity. */ | ||
| 115 | uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host. */ | ||
| 116 | uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this | ||
| 117 | * should be decremented by the user application if non-zero each millisecond. */ | ||
| 118 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 119 | * are reset to their defaults when the interface is enumerated. | ||
| 120 | */ | ||
| 121 | } USB_ClassInfo_HID_Device_t; | ||
| 122 | |||
| 123 | /* Function Prototypes: */ | ||
| 124 | /** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library | ||
| 125 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||
| 126 | * containing the given HID interface is selected. | ||
| 127 | * | ||
| 128 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 129 | * | ||
| 130 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 131 | */ | ||
| 132 | bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 133 | |||
| 134 | /** Processes incoming control requests from the host, that are directed to the given HID class interface. This should be | ||
| 135 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 136 | * | ||
| 137 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 138 | */ | ||
| 139 | void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 140 | |||
| 141 | /** General management task for a given HID class interface, required for the correct operation of the interface. This should | ||
| 142 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 143 | * | ||
| 144 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 145 | */ | ||
| 146 | void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 147 | |||
| 148 | /** HID class driver callback for the user creation of a HID IN report. This callback may fire in response to either | ||
| 149 | * HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the | ||
| 150 | * user is responsible for the creation of the next HID input report to be sent to the host. | ||
| 151 | * | ||
| 152 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 153 | * \param[in,out] ReportID If preset to a non-zero value, this is the report ID being requested by the host. If zero, | ||
| 154 | * this should be set to the report ID of the generated HID input report (if any). If multiple | ||
| 155 | * reports are not sent via the given HID interface, this parameter should be ignored. | ||
| 156 | * \param[in] ReportType Type of HID report to generate, either \ref HID_REPORT_ITEM_In or \ref HID_REPORT_ITEM_Feature. | ||
| 157 | * \param[out] ReportData Pointer to a buffer where the generated HID report should be stored. | ||
| 158 | * \param[out] ReportSize Number of bytes in the generated input report, or zero if no report is to be sent. | ||
| 159 | * | ||
| 160 | * \return Boolean \c true to force the sending of the report even if it is identical to the previous report and still within | ||
| 161 | * the idle period (useful for devices which report relative movement), \c false otherwise. | ||
| 162 | */ | ||
| 163 | bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, | ||
| 164 | uint8_t* const ReportID, | ||
| 165 | const uint8_t ReportType, | ||
| 166 | void* ReportData, | ||
| 167 | uint16_t* const ReportSize) ATTR_NON_NULL_PTR_ARG(1) | ||
| 168 | ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(4) ATTR_NON_NULL_PTR_ARG(5); | ||
| 169 | |||
| 170 | /** HID class driver callback for the user processing of a received HID OUT report. This callback may fire in response to | ||
| 171 | * either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback | ||
| 172 | * the user is responsible for the processing of the received HID output report from the host. | ||
| 173 | * | ||
| 174 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 175 | * \param[in] ReportID Report ID of the received output report. If multiple reports are not received via the given HID | ||
| 176 | * interface, this parameter should be ignored. | ||
| 177 | * \param[in] ReportType Type of received HID report, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature. | ||
| 178 | * \param[in] ReportData Pointer to a buffer where the received HID report is stored. | ||
| 179 | * \param[in] ReportSize Size in bytes of the received report from the host. | ||
| 180 | */ | ||
| 181 | void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, | ||
| 182 | const uint8_t ReportID, | ||
| 183 | const uint8_t ReportType, | ||
| 184 | const void* ReportData, | ||
| 185 | const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4); | ||
| 186 | |||
| 187 | /* Inline Functions: */ | ||
| 188 | /** Indicates that a millisecond of idle time has elapsed on the given HID interface, and the interface's idle count should be | ||
| 189 | * decremented. This should be called once per millisecond so that hardware key-repeats function correctly. It is recommended | ||
| 190 | * that this be called by the \ref EVENT_USB_Device_StartOfFrame() event, once SOF events have been enabled via | ||
| 191 | * \ref USB_Device_EnableSOFEvents(). | ||
| 192 | * | ||
| 193 | * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. | ||
| 194 | */ | ||
| 195 | static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1); | ||
| 196 | static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) | ||
| 197 | { | ||
| 198 | if (HIDInterfaceInfo->State.IdleMSRemaining) | ||
| 199 | HIDInterfaceInfo->State.IdleMSRemaining--; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* Disable C linkage for C++ Compilers: */ | ||
| 203 | #if defined(__cplusplus) | ||
| 204 | } | ||
| 205 | #endif | ||
| 206 | |||
| 207 | #endif | ||
| 208 | |||
| 209 | /** @} */ | ||
| 210 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c new file mode 100644 index 000000000..a35c4082b --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_MIDI_DRIVER | ||
| 37 | #define __INCLUDE_FROM_MIDI_DEVICE_C | ||
| 38 | #include "MIDIClassDevice.h" | ||
| 39 | |||
| 40 | bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||
| 41 | { | ||
| 42 | memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); | ||
| 43 | |||
| 44 | MIDIInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK; | ||
| 45 | MIDIInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||
| 46 | |||
| 47 | if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 48 | return false; | ||
| 49 | |||
| 50 | if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 51 | return false; | ||
| 52 | |||
| 53 | return true; | ||
| 54 | } | ||
| 55 | |||
| 56 | void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||
| 57 | { | ||
| 58 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 59 | return; | ||
| 60 | |||
| 61 | #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||
| 62 | Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 63 | |||
| 64 | if (Endpoint_IsINReady()) | ||
| 65 | MIDI_Device_Flush(MIDIInterfaceInfo); | ||
| 66 | #endif | ||
| 67 | } | ||
| 68 | |||
| 69 | uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||
| 70 | const MIDI_EventPacket_t* const Event) | ||
| 71 | { | ||
| 72 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 73 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 74 | |||
| 75 | uint8_t ErrorCode; | ||
| 76 | |||
| 77 | Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 78 | |||
| 79 | if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != ENDPOINT_RWSTREAM_NoError) | ||
| 80 | return ErrorCode; | ||
| 81 | |||
| 82 | if (!(Endpoint_IsReadWriteAllowed())) | ||
| 83 | Endpoint_ClearIN(); | ||
| 84 | |||
| 85 | return ENDPOINT_RWSTREAM_NoError; | ||
| 86 | } | ||
| 87 | |||
| 88 | uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||
| 89 | { | ||
| 90 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 91 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 92 | |||
| 93 | uint8_t ErrorCode; | ||
| 94 | |||
| 95 | Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 96 | |||
| 97 | if (Endpoint_BytesInEndpoint()) | ||
| 98 | { | ||
| 99 | Endpoint_ClearIN(); | ||
| 100 | |||
| 101 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 102 | return ErrorCode; | ||
| 103 | } | ||
| 104 | |||
| 105 | return ENDPOINT_READYWAIT_NoError; | ||
| 106 | } | ||
| 107 | |||
| 108 | bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||
| 109 | MIDI_EventPacket_t* const Event) | ||
| 110 | { | ||
| 111 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 112 | return false; | ||
| 113 | |||
| 114 | Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 115 | |||
| 116 | if (!(Endpoint_IsOUTReceived())) | ||
| 117 | return false; | ||
| 118 | |||
| 119 | if (!(Endpoint_IsReadWriteAllowed())) | ||
| 120 | return false; | ||
| 121 | |||
| 122 | Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); | ||
| 123 | |||
| 124 | if (!(Endpoint_IsReadWriteAllowed())) | ||
| 125 | Endpoint_ClearOUT(); | ||
| 126 | |||
| 127 | return true; | ||
| 128 | } | ||
| 129 | |||
| 130 | #endif | ||
| 131 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h new file mode 100644 index 000000000..ee2efd7c1 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB MIDI Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB MIDI Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassMIDI | ||
| 41 | * \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassMIDIDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassMIDIDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the MIDI USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _MIDI_CLASS_DEVICE_H_ | ||
| 54 | #define _MIDI_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/MIDIClassCommon.h" | ||
| 59 | |||
| 60 | /* Enable C linkage for C++ Compilers: */ | ||
| 61 | #if defined(__cplusplus) | ||
| 62 | extern "C" { | ||
| 63 | #endif | ||
| 64 | |||
| 65 | /* Preprocessor Checks: */ | ||
| 66 | #if !defined(__INCLUDE_FROM_MIDI_DRIVER) | ||
| 67 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* Public Interface - May be used in end-application: */ | ||
| 71 | /* Type Define: */ | ||
| 72 | /** \brief MIDI Class Device Mode Configuration and State Structure. | ||
| 73 | * | ||
| 74 | * Class state structure. An instance of this structure should be made for each MIDI interface | ||
| 75 | * within the user application, and passed to each of the MIDI class driver functions as the | ||
| 76 | * \c MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information. | ||
| 77 | */ | ||
| 78 | typedef struct | ||
| 79 | { | ||
| 80 | struct | ||
| 81 | { | ||
| 82 | uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */ | ||
| 83 | |||
| 84 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 85 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 86 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 87 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 88 | */ | ||
| 89 | |||
| 90 | struct | ||
| 91 | { | ||
| 92 | uint8_t RESERVED; // No state information for this class | ||
| 93 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 94 | * are reset to their defaults when the interface is enumerated. | ||
| 95 | */ | ||
| 96 | } USB_ClassInfo_MIDI_Device_t; | ||
| 97 | |||
| 98 | /* Function Prototypes: */ | ||
| 99 | /** Configures the endpoints of a given MIDI interface, ready for use. This should be linked to the library | ||
| 100 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||
| 101 | * containing the given MIDI interface is selected. | ||
| 102 | * | ||
| 103 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 104 | * | ||
| 105 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 106 | */ | ||
| 107 | bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 108 | |||
| 109 | /** General management task for a given MIDI class interface, required for the correct operation of the interface. This should | ||
| 110 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 111 | * | ||
| 112 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 113 | */ | ||
| 114 | void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 115 | |||
| 116 | /** Sends a MIDI event packet to the host. If no host is connected, the event packet is discarded. Events are queued into the | ||
| 117 | * endpoint bank until either the endpoint bank is full, or \ref MIDI_Device_Flush() is called. This allows for multiple | ||
| 118 | * MIDI events to be packed into a single endpoint packet, increasing data throughput. | ||
| 119 | * | ||
| 120 | * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the | ||
| 121 | * call will fail. | ||
| 122 | * | ||
| 123 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 124 | * \param[in] Event Pointer to a populated \ref MIDI_EventPacket_t structure containing the MIDI event to send. | ||
| 125 | * | ||
| 126 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 127 | */ | ||
| 128 | uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||
| 129 | const MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 130 | |||
| 131 | |||
| 132 | /** Flushes the MIDI send buffer, sending any queued MIDI events to the host. This should be called to override the | ||
| 133 | * \ref MIDI_Device_SendEventPacket() function's packing behavior, to flush queued events. | ||
| 134 | * | ||
| 135 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 136 | * | ||
| 137 | * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||
| 138 | */ | ||
| 139 | uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 140 | |||
| 141 | /** Receives a MIDI event packet from the host. Events are unpacked from the endpoint, thus if the endpoint bank contains | ||
| 142 | * multiple MIDI events from the host in the one packet, multiple calls to this function will return each individual event. | ||
| 143 | * | ||
| 144 | * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the | ||
| 145 | * call will fail. | ||
| 146 | * | ||
| 147 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 148 | * \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed. | ||
| 149 | * | ||
| 150 | * \return Boolean \c true if a MIDI event packet was received, \c false otherwise. | ||
| 151 | */ | ||
| 152 | bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, | ||
| 153 | MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 154 | |||
| 155 | /* Inline Functions: */ | ||
| 156 | /** Processes incoming control requests from the host, that are directed to the given MIDI class interface. This should be | ||
| 157 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 158 | * | ||
| 159 | * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. | ||
| 160 | */ | ||
| 161 | static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 162 | static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) | ||
| 163 | { | ||
| 164 | (void)MIDIInterfaceInfo; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* Disable C linkage for C++ Compilers: */ | ||
| 168 | #if defined(__cplusplus) | ||
| 169 | } | ||
| 170 | #endif | ||
| 171 | |||
| 172 | #endif | ||
| 173 | |||
| 174 | /** @} */ | ||
| 175 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c new file mode 100644 index 000000000..1ea30f7cb --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_MS_DRIVER | ||
| 37 | #define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C | ||
| 38 | #include "MassStorageClassDevice.h" | ||
| 39 | |||
| 40 | void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||
| 41 | { | ||
| 42 | if (!(Endpoint_IsSETUPReceived())) | ||
| 43 | return; | ||
| 44 | |||
| 45 | if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber) | ||
| 46 | return; | ||
| 47 | |||
| 48 | switch (USB_ControlRequest.bRequest) | ||
| 49 | { | ||
| 50 | case MS_REQ_MassStorageReset: | ||
| 51 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 52 | { | ||
| 53 | Endpoint_ClearSETUP(); | ||
| 54 | Endpoint_ClearStatusStage(); | ||
| 55 | |||
| 56 | MSInterfaceInfo->State.IsMassStoreReset = true; | ||
| 57 | } | ||
| 58 | |||
| 59 | break; | ||
| 60 | case MS_REQ_GetMaxLUN: | ||
| 61 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 62 | { | ||
| 63 | Endpoint_ClearSETUP(); | ||
| 64 | while (!(Endpoint_IsINReady())); | ||
| 65 | Endpoint_Write_8(MSInterfaceInfo->Config.TotalLUNs - 1); | ||
| 66 | Endpoint_ClearIN(); | ||
| 67 | Endpoint_ClearStatusStage(); | ||
| 68 | } | ||
| 69 | |||
| 70 | break; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||
| 75 | { | ||
| 76 | memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State)); | ||
| 77 | |||
| 78 | MSInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK; | ||
| 79 | MSInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||
| 80 | |||
| 81 | if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 82 | return false; | ||
| 83 | |||
| 84 | if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 85 | return false; | ||
| 86 | |||
| 87 | return true; | ||
| 88 | } | ||
| 89 | |||
| 90 | void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||
| 91 | { | ||
| 92 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 93 | return; | ||
| 94 | |||
| 95 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 96 | |||
| 97 | if (Endpoint_IsOUTReceived()) | ||
| 98 | { | ||
| 99 | if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) | ||
| 100 | { | ||
| 101 | if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) | ||
| 102 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 103 | |||
| 104 | bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo); | ||
| 105 | |||
| 106 | MSInterfaceInfo->State.CommandStatus.Status = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail; | ||
| 107 | MSInterfaceInfo->State.CommandStatus.Signature = CPU_TO_LE32(MS_CSW_SIGNATURE); | ||
| 108 | MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag; | ||
| 109 | MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength; | ||
| 110 | |||
| 111 | if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue))) | ||
| 112 | Endpoint_StallTransaction(); | ||
| 113 | |||
| 114 | MS_Device_ReturnCommandStatus(MSInterfaceInfo); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 119 | { | ||
| 120 | Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 121 | Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 122 | |||
| 123 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 124 | Endpoint_ClearStall(); | ||
| 125 | Endpoint_ResetDataToggle(); | ||
| 126 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 127 | Endpoint_ClearStall(); | ||
| 128 | Endpoint_ResetDataToggle(); | ||
| 129 | |||
| 130 | MSInterfaceInfo->State.IsMassStoreReset = false; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||
| 135 | { | ||
| 136 | uint16_t BytesProcessed; | ||
| 137 | |||
| 138 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 139 | |||
| 140 | BytesProcessed = 0; | ||
| 141 | while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock, | ||
| 142 | (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) == | ||
| 143 | ENDPOINT_RWSTREAM_IncompleteTransfer) | ||
| 144 | { | ||
| 145 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 146 | return false; | ||
| 147 | } | ||
| 148 | |||
| 149 | if ((MSInterfaceInfo->State.CommandBlock.Signature != CPU_TO_LE32(MS_CBW_SIGNATURE)) || | ||
| 150 | (MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) || | ||
| 151 | (MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) || | ||
| 152 | (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) || | ||
| 153 | (MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16)) | ||
| 154 | { | ||
| 155 | Endpoint_StallTransaction(); | ||
| 156 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 157 | Endpoint_StallTransaction(); | ||
| 158 | |||
| 159 | return false; | ||
| 160 | } | ||
| 161 | |||
| 162 | BytesProcessed = 0; | ||
| 163 | while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData, | ||
| 164 | MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) == | ||
| 165 | ENDPOINT_RWSTREAM_IncompleteTransfer) | ||
| 166 | { | ||
| 167 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 168 | return false; | ||
| 169 | } | ||
| 170 | |||
| 171 | Endpoint_ClearOUT(); | ||
| 172 | |||
| 173 | return true; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | ||
| 177 | { | ||
| 178 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 179 | |||
| 180 | while (Endpoint_IsStalled()) | ||
| 181 | { | ||
| 182 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | ||
| 183 | USB_USBTask(); | ||
| 184 | #endif | ||
| 185 | |||
| 186 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 187 | return; | ||
| 188 | } | ||
| 189 | |||
| 190 | Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 191 | |||
| 192 | while (Endpoint_IsStalled()) | ||
| 193 | { | ||
| 194 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | ||
| 195 | USB_USBTask(); | ||
| 196 | #endif | ||
| 197 | |||
| 198 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | |||
| 202 | uint16_t BytesProcessed = 0; | ||
| 203 | while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, | ||
| 204 | sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) == | ||
| 205 | ENDPOINT_RWSTREAM_IncompleteTransfer) | ||
| 206 | { | ||
| 207 | if (MSInterfaceInfo->State.IsMassStoreReset) | ||
| 208 | return; | ||
| 209 | } | ||
| 210 | |||
| 211 | Endpoint_ClearIN(); | ||
| 212 | } | ||
| 213 | |||
| 214 | #endif | ||
| 215 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h new file mode 100644 index 000000000..12b54f8df --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB Mass Storage Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB Mass Storage Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassMS | ||
| 41 | * \defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassMSDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassMSDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _MS_CLASS_DEVICE_H_ | ||
| 54 | #define _MS_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/MassStorageClassCommon.h" | ||
| 59 | |||
| 60 | /* Enable C linkage for C++ Compilers: */ | ||
| 61 | #if defined(__cplusplus) | ||
| 62 | extern "C" { | ||
| 63 | #endif | ||
| 64 | |||
| 65 | /* Preprocessor Checks: */ | ||
| 66 | #if !defined(__INCLUDE_FROM_MS_DRIVER) | ||
| 67 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* Public Interface - May be used in end-application: */ | ||
| 71 | /* Type Defines: */ | ||
| 72 | /** \brief Mass Storage Class Device Mode Configuration and State Structure. | ||
| 73 | * | ||
| 74 | * Class state structure. An instance of this structure should be made for each Mass Storage interface | ||
| 75 | * within the user application, and passed to each of the Mass Storage class driver functions as the | ||
| 76 | * \c MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information. | ||
| 77 | */ | ||
| 78 | typedef struct | ||
| 79 | { | ||
| 80 | struct | ||
| 81 | { | ||
| 82 | uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */ | ||
| 83 | |||
| 84 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 85 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 86 | |||
| 87 | uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */ | ||
| 88 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 89 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 90 | */ | ||
| 91 | struct | ||
| 92 | { | ||
| 93 | MS_CommandBlockWrapper_t CommandBlock; /**< Mass Storage class command block structure, stores the received SCSI | ||
| 94 | * command from the host which is to be processed. | ||
| 95 | */ | ||
| 96 | MS_CommandStatusWrapper_t CommandStatus; /**< Mass Storage class command status structure, set elements to indicate | ||
| 97 | * the issued command's success or failure to the host. | ||
| 98 | */ | ||
| 99 | volatile bool IsMassStoreReset; /**< Flag indicating that the host has requested that the Mass Storage interface be reset | ||
| 100 | * and that all current Mass Storage operations should immediately abort. | ||
| 101 | */ | ||
| 102 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 103 | * are reset to their defaults when the interface is enumerated. | ||
| 104 | */ | ||
| 105 | } USB_ClassInfo_MS_Device_t; | ||
| 106 | |||
| 107 | /* Function Prototypes: */ | ||
| 108 | /** Configures the endpoints of a given Mass Storage interface, ready for use. This should be linked to the library | ||
| 109 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||
| 110 | * containing the given Mass Storage interface is selected. | ||
| 111 | * | ||
| 112 | * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state. | ||
| 113 | * | ||
| 114 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 115 | */ | ||
| 116 | bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 117 | |||
| 118 | /** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be | ||
| 119 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 120 | * | ||
| 121 | * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state. | ||
| 122 | */ | ||
| 123 | void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 124 | |||
| 125 | /** General management task for a given Mass Storage class interface, required for the correct operation of the interface. This should | ||
| 126 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 127 | * | ||
| 128 | * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage configuration and state. | ||
| 129 | */ | ||
| 130 | void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 131 | |||
| 132 | /** Mass Storage class driver callback for the user processing of a received SCSI command. This callback will fire each time the | ||
| 133 | * host sends a SCSI command which requires processing by the user application. Inside this callback the user is responsible | ||
| 134 | * for the processing of the received SCSI command from the host. The SCSI command is available in the CommandBlock structure | ||
| 135 | * inside the Mass Storage class state structure passed as a parameter to the callback function. | ||
| 136 | * | ||
| 137 | * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state. | ||
| 138 | * | ||
| 139 | * \return Boolean \c true if the SCSI command was successfully processed, \c false otherwise. | ||
| 140 | */ | ||
| 141 | bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 142 | |||
| 143 | /* Private Interface - For use in library only: */ | ||
| 144 | #if !defined(__DOXYGEN__) | ||
| 145 | /* Function Prototypes: */ | ||
| 146 | #if defined(__INCLUDE_FROM_MASSSTORAGE_DEVICE_C) | ||
| 147 | static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 148 | static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 149 | #endif | ||
| 150 | |||
| 151 | #endif | ||
| 152 | |||
| 153 | /* Disable C linkage for C++ Compilers: */ | ||
| 154 | #if defined(__cplusplus) | ||
| 155 | } | ||
| 156 | #endif | ||
| 157 | |||
| 158 | #endif | ||
| 159 | |||
| 160 | /** @} */ | ||
| 161 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c new file mode 100644 index 000000000..7209c452d --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c | |||
| @@ -0,0 +1,314 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_PRINTER_DRIVER | ||
| 37 | #define __INCLUDE_FROM_PRINTER_DEVICE_C | ||
| 38 | #include "PrinterClassDevice.h" | ||
| 39 | |||
| 40 | void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 41 | { | ||
| 42 | if (!(Endpoint_IsSETUPReceived())) | ||
| 43 | return; | ||
| 44 | |||
| 45 | if (USB_ControlRequest.wIndex != PRNTInterfaceInfo->Config.InterfaceNumber) | ||
| 46 | return; | ||
| 47 | |||
| 48 | switch (USB_ControlRequest.bRequest) | ||
| 49 | { | ||
| 50 | case PRNT_REQ_GetDeviceID: | ||
| 51 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 52 | { | ||
| 53 | Endpoint_ClearSETUP(); | ||
| 54 | |||
| 55 | while (!(Endpoint_IsINReady())) | ||
| 56 | { | ||
| 57 | if (USB_DeviceState == DEVICE_STATE_Unattached) | ||
| 58 | return; | ||
| 59 | } | ||
| 60 | |||
| 61 | uint16_t IEEEStringLen = strlen(PRNTInterfaceInfo->Config.IEEE1284String); | ||
| 62 | Endpoint_Write_16_BE(IEEEStringLen); | ||
| 63 | Endpoint_Write_Control_Stream_LE(PRNTInterfaceInfo->Config.IEEE1284String, IEEEStringLen); | ||
| 64 | Endpoint_ClearStatusStage(); | ||
| 65 | } | ||
| 66 | |||
| 67 | break; | ||
| 68 | case PRNT_REQ_GetPortStatus: | ||
| 69 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 70 | { | ||
| 71 | Endpoint_ClearSETUP(); | ||
| 72 | |||
| 73 | while (!(Endpoint_IsINReady())) | ||
| 74 | { | ||
| 75 | if (USB_DeviceState == DEVICE_STATE_Unattached) | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | |||
| 79 | Endpoint_Write_8(PRNTInterfaceInfo->State.PortStatus); | ||
| 80 | Endpoint_ClearStatusStage(); | ||
| 81 | } | ||
| 82 | |||
| 83 | break; | ||
| 84 | case PRNT_REQ_SoftReset: | ||
| 85 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 86 | { | ||
| 87 | Endpoint_ClearSETUP(); | ||
| 88 | Endpoint_ClearStatusStage(); | ||
| 89 | |||
| 90 | PRNTInterfaceInfo->State.IsPrinterReset = true; | ||
| 91 | |||
| 92 | EVENT_PRNT_Device_SoftReset(PRNTInterfaceInfo); | ||
| 93 | } | ||
| 94 | |||
| 95 | break; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 100 | { | ||
| 101 | memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State)); | ||
| 102 | PRNTInterfaceInfo->State.PortStatus = PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT; | ||
| 103 | |||
| 104 | PRNTInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK; | ||
| 105 | PRNTInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||
| 106 | |||
| 107 | if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 108 | return false; | ||
| 109 | |||
| 110 | if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 111 | return false; | ||
| 112 | |||
| 113 | return true; | ||
| 114 | } | ||
| 115 | |||
| 116 | void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 117 | { | ||
| 118 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 119 | return; | ||
| 120 | |||
| 121 | #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) | ||
| 122 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 123 | |||
| 124 | if (Endpoint_IsINReady()) | ||
| 125 | PRNT_Device_Flush(PRNTInterfaceInfo); | ||
| 126 | #endif | ||
| 127 | |||
| 128 | if (PRNTInterfaceInfo->State.IsPrinterReset) | ||
| 129 | { | ||
| 130 | Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 131 | Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 132 | |||
| 133 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 134 | Endpoint_ClearStall(); | ||
| 135 | Endpoint_ResetDataToggle(); | ||
| 136 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 137 | Endpoint_ClearStall(); | ||
| 138 | Endpoint_ResetDataToggle(); | ||
| 139 | |||
| 140 | PRNTInterfaceInfo->State.IsPrinterReset = false; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 145 | const char* const String) | ||
| 146 | { | ||
| 147 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 148 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 149 | |||
| 150 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 151 | return Endpoint_Write_Stream_LE(String, strlen(String), NULL); | ||
| 152 | } | ||
| 153 | |||
| 154 | uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 155 | const void* const Buffer, | ||
| 156 | const uint16_t Length) | ||
| 157 | { | ||
| 158 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 159 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 160 | |||
| 161 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 162 | return Endpoint_Write_Stream_LE(Buffer, Length, NULL); | ||
| 163 | } | ||
| 164 | |||
| 165 | uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 166 | const uint8_t Data) | ||
| 167 | { | ||
| 168 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 169 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 170 | |||
| 171 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 172 | |||
| 173 | if (!(Endpoint_IsReadWriteAllowed())) | ||
| 174 | { | ||
| 175 | Endpoint_ClearIN(); | ||
| 176 | |||
| 177 | uint8_t ErrorCode; | ||
| 178 | |||
| 179 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 180 | return ErrorCode; | ||
| 181 | } | ||
| 182 | |||
| 183 | Endpoint_Write_8(Data); | ||
| 184 | return ENDPOINT_READYWAIT_NoError; | ||
| 185 | } | ||
| 186 | |||
| 187 | uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 188 | { | ||
| 189 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 190 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 191 | |||
| 192 | uint8_t ErrorCode; | ||
| 193 | |||
| 194 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 195 | |||
| 196 | if (!(Endpoint_BytesInEndpoint())) | ||
| 197 | return ENDPOINT_READYWAIT_NoError; | ||
| 198 | |||
| 199 | bool BankFull = !(Endpoint_IsReadWriteAllowed()); | ||
| 200 | |||
| 201 | Endpoint_ClearIN(); | ||
| 202 | |||
| 203 | if (BankFull) | ||
| 204 | { | ||
| 205 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 206 | return ErrorCode; | ||
| 207 | |||
| 208 | Endpoint_ClearIN(); | ||
| 209 | } | ||
| 210 | |||
| 211 | return ENDPOINT_READYWAIT_NoError; | ||
| 212 | } | ||
| 213 | |||
| 214 | uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 215 | { | ||
| 216 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 217 | return 0; | ||
| 218 | |||
| 219 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 220 | |||
| 221 | if (Endpoint_IsOUTReceived()) | ||
| 222 | { | ||
| 223 | if (!(Endpoint_BytesInEndpoint())) | ||
| 224 | { | ||
| 225 | Endpoint_ClearOUT(); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | else | ||
| 229 | { | ||
| 230 | return Endpoint_BytesInEndpoint(); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | else | ||
| 234 | { | ||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 240 | { | ||
| 241 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 242 | return -1; | ||
| 243 | |||
| 244 | int16_t ReceivedByte = -1; | ||
| 245 | |||
| 246 | Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 247 | |||
| 248 | if (Endpoint_IsOUTReceived()) | ||
| 249 | { | ||
| 250 | if (Endpoint_BytesInEndpoint()) | ||
| 251 | ReceivedByte = Endpoint_Read_8(); | ||
| 252 | |||
| 253 | if (!(Endpoint_BytesInEndpoint())) | ||
| 254 | Endpoint_ClearOUT(); | ||
| 255 | } | ||
| 256 | |||
| 257 | return ReceivedByte; | ||
| 258 | } | ||
| 259 | |||
| 260 | #if defined(FDEV_SETUP_STREAM) | ||
| 261 | void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 262 | FILE* const Stream) | ||
| 263 | { | ||
| 264 | *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar, _FDEV_SETUP_RW); | ||
| 265 | fdev_set_udata(Stream, PRNTInterfaceInfo); | ||
| 266 | } | ||
| 267 | |||
| 268 | void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 269 | FILE* const Stream) | ||
| 270 | { | ||
| 271 | *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar_Blocking, _FDEV_SETUP_RW); | ||
| 272 | fdev_set_udata(Stream, PRNTInterfaceInfo); | ||
| 273 | } | ||
| 274 | |||
| 275 | static int PRNT_Device_putchar(char c, | ||
| 276 | FILE* Stream) | ||
| 277 | { | ||
| 278 | return PRNT_Device_SendByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int PRNT_Device_getchar(FILE* Stream) | ||
| 282 | { | ||
| 283 | int16_t ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream)); | ||
| 284 | |||
| 285 | if (ReceivedByte < 0) | ||
| 286 | return _FDEV_EOF; | ||
| 287 | |||
| 288 | return ReceivedByte; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int PRNT_Device_getchar_Blocking(FILE* Stream) | ||
| 292 | { | ||
| 293 | int16_t ReceivedByte; | ||
| 294 | |||
| 295 | while ((ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream))) < 0) | ||
| 296 | { | ||
| 297 | if (USB_DeviceState == DEVICE_STATE_Unattached) | ||
| 298 | return _FDEV_EOF; | ||
| 299 | |||
| 300 | PRNT_Device_USBTask((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream)); | ||
| 301 | USB_USBTask(); | ||
| 302 | } | ||
| 303 | |||
| 304 | return ReceivedByte; | ||
| 305 | } | ||
| 306 | #endif | ||
| 307 | |||
| 308 | void PRNT_Device_Event_Stub(void) | ||
| 309 | { | ||
| 310 | |||
| 311 | } | ||
| 312 | |||
| 313 | #endif | ||
| 314 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h new file mode 100644 index 000000000..802c5912d --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h | |||
| @@ -0,0 +1,293 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB Printer Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB Printer Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassPrinter | ||
| 41 | * \defgroup Group_USBClassPrinterDevice Printer Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassPrinterDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassPrinterDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the Printer USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _PRINTER_CLASS_DEVICE_H_ | ||
| 54 | #define _PRINTER_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/PrinterClassCommon.h" | ||
| 59 | |||
| 60 | #include <stdio.h> | ||
| 61 | |||
| 62 | /* Enable C linkage for C++ Compilers: */ | ||
| 63 | #if defined(__cplusplus) | ||
| 64 | extern "C" { | ||
| 65 | #endif | ||
| 66 | |||
| 67 | /* Preprocessor Checks: */ | ||
| 68 | #if !defined(__INCLUDE_FROM_PRINTER_DRIVER) | ||
| 69 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 70 | #endif | ||
| 71 | |||
| 72 | /* Public Interface - May be used in end-application: */ | ||
| 73 | /* Type Defines: */ | ||
| 74 | /** \brief Printer Class Device Mode Configuration and State Structure. | ||
| 75 | * | ||
| 76 | * Class state structure. An instance of this structure should be made for each Printer interface | ||
| 77 | * within the user application, and passed to each of the Printer class driver functions as the | ||
| 78 | * PRNTInterfaceInfo parameter. This stores each Printer interface's configuration and state information. | ||
| 79 | */ | ||
| 80 | typedef struct | ||
| 81 | { | ||
| 82 | struct | ||
| 83 | { | ||
| 84 | uint8_t InterfaceNumber; /**< Interface number of the Printer interface within the device. */ | ||
| 85 | |||
| 86 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 87 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 88 | |||
| 89 | char* IEEE1284String; /**< IEEE 1284 identification string, sent to the host during enumeration | ||
| 90 | * to identify the printer model, manufacturer and other characteristics. | ||
| 91 | */ | ||
| 92 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 93 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 94 | */ | ||
| 95 | struct | ||
| 96 | { | ||
| 97 | uint8_t PortStatus; /**< Current status of the Printer virtual port, a collection of \c PRNT_PORTSTATUS_* | ||
| 98 | * bitmask values. | ||
| 99 | */ | ||
| 100 | |||
| 101 | volatile bool IsPrinterReset; /**< Flag indicating that the host has requested that the Printer interface be reset | ||
| 102 | * and that all current Mass Storage operations should immediately abort. | ||
| 103 | */ | ||
| 104 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 105 | * are reset to their defaults when the interface is enumerated. | ||
| 106 | */ | ||
| 107 | } USB_ClassInfo_PRNT_Device_t; | ||
| 108 | |||
| 109 | /* Function Prototypes: */ | ||
| 110 | /** Configures the endpoints of a given Printer interface, ready for use. This should be linked to the library | ||
| 111 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing | ||
| 112 | * the given Printer interface is selected. | ||
| 113 | * | ||
| 114 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 115 | * | ||
| 116 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 117 | */ | ||
| 118 | bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 119 | |||
| 120 | /** Processes incoming control requests from the host, that are directed to the given Printer class interface. This should be | ||
| 121 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 122 | * | ||
| 123 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 124 | */ | ||
| 125 | void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 126 | |||
| 127 | /** General management task for a given Printer class interface, required for the correct operation of the interface. This should | ||
| 128 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 129 | * | ||
| 130 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 131 | */ | ||
| 132 | void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 133 | |||
| 134 | /** Printer class driver event for a soft reset request on a Printer interface. This event fires each time the host | ||
| 135 | * requests a reset of the printer interface's internal state, and may be hooked in the user program by declaring a | ||
| 136 | * handler function with the same name and parameters listed here. | ||
| 137 | * | ||
| 138 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 139 | */ | ||
| 140 | void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 141 | |||
| 142 | /** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is | ||
| 143 | * called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank | ||
| 144 | * becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows | ||
| 145 | * for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 146 | * | ||
| 147 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 148 | * the call will fail. | ||
| 149 | * | ||
| 150 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 151 | * \param[in] Buffer Pointer to a buffer containing the data to send to the device. | ||
| 152 | * \param[in] Length Length of the data to send to the host. | ||
| 153 | * | ||
| 154 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 155 | */ | ||
| 156 | uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 157 | const void* const Buffer, | ||
| 158 | const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 159 | |||
| 160 | /** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when | ||
| 161 | * the function is called, the string is discarded. Bytes will be queued for transmission to the host until either | ||
| 162 | * the endpoint bank becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to | ||
| 163 | * the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput. | ||
| 164 | * | ||
| 165 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 166 | * the call will fail. | ||
| 167 | * | ||
| 168 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 169 | * \param[in] String Pointer to the null terminated string to send to the host. | ||
| 170 | * | ||
| 171 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 172 | */ | ||
| 173 | uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 174 | const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 175 | |||
| 176 | /** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the | ||
| 177 | * byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the | ||
| 178 | * \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be | ||
| 179 | * packed into a single endpoint packet, increasing data throughput. | ||
| 180 | * | ||
| 181 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 182 | * the call will fail. | ||
| 183 | * | ||
| 184 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 185 | * \param[in] Data Byte of data to send to the host. | ||
| 186 | * | ||
| 187 | * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||
| 188 | */ | ||
| 189 | uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 190 | const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1); | ||
| 191 | |||
| 192 | /** Determines the number of bytes received by the Printer interface from the host, waiting to be read. This indicates the number | ||
| 193 | * of bytes in the OUT endpoint bank only, and thus the number of calls to \ref PRNT_Device_ReceiveByte() which are guaranteed to | ||
| 194 | * succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint | ||
| 195 | * bank will not be released back to the USB controller until all bytes are read. | ||
| 196 | * | ||
| 197 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 198 | * the call will fail. | ||
| 199 | * | ||
| 200 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 201 | * | ||
| 202 | * \return Total number of buffered bytes received from the host. | ||
| 203 | */ | ||
| 204 | uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 205 | |||
| 206 | /** 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 | ||
| 207 | * returns a negative value. The \ref PRNT_Device_BytesReceived() function may be queried in advance to determine how many | ||
| 208 | * bytes are currently buffered in the Printer interface's data receive endpoint bank, and thus how many repeated calls to this | ||
| 209 | * function which are guaranteed to succeed. | ||
| 210 | * | ||
| 211 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 212 | * the call will fail. | ||
| 213 | * | ||
| 214 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 215 | * | ||
| 216 | * \return Next received byte from the host, or a negative value if no data received. | ||
| 217 | */ | ||
| 218 | int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 219 | |||
| 220 | /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared. | ||
| 221 | * | ||
| 222 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or | ||
| 223 | * the call will fail. | ||
| 224 | * | ||
| 225 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 226 | * | ||
| 227 | * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. | ||
| 228 | */ | ||
| 229 | uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 230 | |||
| 231 | #if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__) | ||
| 232 | /** Creates a standard character stream for the given Printer Device instance so that it can be used with all the regular | ||
| 233 | * functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created | ||
| 234 | * stream is bidirectional and can be used for both input and output functions. | ||
| 235 | * | ||
| 236 | * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single | ||
| 237 | * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may | ||
| 238 | * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own | ||
| 239 | * line buffering. | ||
| 240 | * | ||
| 241 | * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions | ||
| 242 | * to the given Printer interface. | ||
| 243 | * \n\n | ||
| 244 | * | ||
| 245 | * \note This function is not available on all microcontroller architectures. | ||
| 246 | * | ||
| 247 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 248 | * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. | ||
| 249 | */ | ||
| 250 | void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 251 | FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 252 | |||
| 253 | /** Identical to \ref PRNT_Device_CreateStream(), except that reads are blocking until the calling stream function terminates | ||
| 254 | * the transfer. While blocking, the USB and Printer service tasks are called repeatedly to maintain USB communications. | ||
| 255 | * | ||
| 256 | * \note This function is not available on all microcontroller architectures. | ||
| 257 | * | ||
| 258 | * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state. | ||
| 259 | * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. | ||
| 260 | */ | ||
| 261 | void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, | ||
| 262 | FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); | ||
| 263 | #endif | ||
| 264 | |||
| 265 | /* Private Interface - For use in library only: */ | ||
| 266 | #if !defined(__DOXYGEN__) | ||
| 267 | /* Function Prototypes: */ | ||
| 268 | #if defined(__INCLUDE_FROM_PRINTER_DEVICE_C) | ||
| 269 | #if defined(FDEV_SETUP_STREAM) | ||
| 270 | static int PRNT_Device_putchar(char c, | ||
| 271 | FILE* Stream) ATTR_NON_NULL_PTR_ARG(2); | ||
| 272 | static int PRNT_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||
| 273 | static int PRNT_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1); | ||
| 274 | #endif | ||
| 275 | |||
| 276 | void PRNT_Device_Event_Stub(void) ATTR_CONST; | ||
| 277 | |||
| 278 | void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) | ||
| 279 | ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(PRNT_Device_Event_Stub); | ||
| 280 | |||
| 281 | #endif | ||
| 282 | |||
| 283 | #endif | ||
| 284 | |||
| 285 | /* Disable C linkage for C++ Compilers: */ | ||
| 286 | #if defined(__cplusplus) | ||
| 287 | } | ||
| 288 | #endif | ||
| 289 | |||
| 290 | #endif | ||
| 291 | |||
| 292 | /** @} */ | ||
| 293 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c b/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c new file mode 100644 index 000000000..45293b12f --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c | |||
| @@ -0,0 +1,508 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define __INCLUDE_FROM_USB_DRIVER | ||
| 32 | #include "../../Core/USBMode.h" | ||
| 33 | |||
| 34 | #if defined(USB_CAN_BE_DEVICE) | ||
| 35 | |||
| 36 | #define __INCLUDE_FROM_RNDIS_DRIVER | ||
| 37 | #define __INCLUDE_FROM_RNDIS_DEVICE_C | ||
| 38 | #include "RNDISClassDevice.h" | ||
| 39 | |||
| 40 | static const uint32_t PROGMEM AdapterSupportedOIDList[] = | ||
| 41 | { | ||
| 42 | CPU_TO_LE32(OID_GEN_SUPPORTED_LIST), | ||
| 43 | CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM), | ||
| 44 | CPU_TO_LE32(OID_GEN_HARDWARE_STATUS), | ||
| 45 | CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED), | ||
| 46 | CPU_TO_LE32(OID_GEN_MEDIA_IN_USE), | ||
| 47 | CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE), | ||
| 48 | CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE), | ||
| 49 | CPU_TO_LE32(OID_GEN_LINK_SPEED), | ||
| 50 | CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE), | ||
| 51 | CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE), | ||
| 52 | CPU_TO_LE32(OID_GEN_VENDOR_ID), | ||
| 53 | CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION), | ||
| 54 | CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER), | ||
| 55 | CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE), | ||
| 56 | CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS), | ||
| 57 | CPU_TO_LE32(OID_GEN_XMIT_OK), | ||
| 58 | CPU_TO_LE32(OID_GEN_RCV_OK), | ||
| 59 | CPU_TO_LE32(OID_GEN_XMIT_ERROR), | ||
| 60 | CPU_TO_LE32(OID_GEN_RCV_ERROR), | ||
| 61 | CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER), | ||
| 62 | CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS), | ||
| 63 | CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS), | ||
| 64 | CPU_TO_LE32(OID_802_3_MULTICAST_LIST), | ||
| 65 | CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE), | ||
| 66 | CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT), | ||
| 67 | CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION), | ||
| 68 | CPU_TO_LE32(OID_802_3_XMIT_MORE_COLLISIONS), | ||
| 69 | }; | ||
| 70 | |||
| 71 | void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 72 | { | ||
| 73 | if (!(Endpoint_IsSETUPReceived())) | ||
| 74 | return; | ||
| 75 | |||
| 76 | if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber) | ||
| 77 | return; | ||
| 78 | |||
| 79 | switch (USB_ControlRequest.bRequest) | ||
| 80 | { | ||
| 81 | case RNDIS_REQ_SendEncapsulatedCommand: | ||
| 82 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 83 | { | ||
| 84 | Endpoint_ClearSETUP(); | ||
| 85 | Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength); | ||
| 86 | Endpoint_ClearIN(); | ||
| 87 | |||
| 88 | RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo); | ||
| 89 | } | ||
| 90 | |||
| 91 | break; | ||
| 92 | case RNDIS_REQ_GetEncapsulatedResponse: | ||
| 93 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||
| 94 | { | ||
| 95 | RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 96 | |||
| 97 | if (!(MessageHeader->MessageLength)) | ||
| 98 | { | ||
| 99 | RNDISInterfaceInfo->Config.MessageBuffer[0] = 0; | ||
| 100 | MessageHeader->MessageLength = CPU_TO_LE32(1); | ||
| 101 | } | ||
| 102 | |||
| 103 | Endpoint_ClearSETUP(); | ||
| 104 | Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength)); | ||
| 105 | Endpoint_ClearOUT(); | ||
| 106 | |||
| 107 | MessageHeader->MessageLength = CPU_TO_LE32(0); | ||
| 108 | } | ||
| 109 | |||
| 110 | break; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 115 | { | ||
| 116 | memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); | ||
| 117 | |||
| 118 | RNDISInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK; | ||
| 119 | RNDISInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK; | ||
| 120 | RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT; | ||
| 121 | |||
| 122 | if (RNDISInterfaceInfo->Config.MessageBuffer == NULL) | ||
| 123 | return false; | ||
| 124 | |||
| 125 | if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH) | ||
| 126 | return false; | ||
| 127 | |||
| 128 | if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1))) | ||
| 129 | return false; | ||
| 130 | |||
| 131 | if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1))) | ||
| 132 | return false; | ||
| 133 | |||
| 134 | if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1))) | ||
| 135 | return false; | ||
| 136 | |||
| 137 | return true; | ||
| 138 | } | ||
| 139 | |||
| 140 | void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 141 | { | ||
| 142 | if (USB_DeviceState != DEVICE_STATE_Configured) | ||
| 143 | return; | ||
| 144 | |||
| 145 | Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address); | ||
| 146 | |||
| 147 | if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) | ||
| 148 | { | ||
| 149 | USB_Request_Header_t Notification = (USB_Request_Header_t) | ||
| 150 | { | ||
| 151 | .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), | ||
| 152 | .bRequest = RNDIS_NOTIF_ResponseAvailable, | ||
| 153 | .wValue = CPU_TO_LE16(0), | ||
| 154 | .wIndex = CPU_TO_LE16(0), | ||
| 155 | .wLength = CPU_TO_LE16(0), | ||
| 156 | }; | ||
| 157 | |||
| 158 | Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL); | ||
| 159 | |||
| 160 | Endpoint_ClearIN(); | ||
| 161 | |||
| 162 | RNDISInterfaceInfo->State.ResponseReady = false; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 167 | { | ||
| 168 | /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of | ||
| 169 | this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */ | ||
| 170 | |||
| 171 | RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 172 | |||
| 173 | switch (le32_to_cpu(MessageHeader->MessageType)) | ||
| 174 | { | ||
| 175 | case REMOTE_NDIS_INITIALIZE_MSG: | ||
| 176 | RNDISInterfaceInfo->State.ResponseReady = true; | ||
| 177 | |||
| 178 | RNDIS_Initialize_Message_t* INITIALIZE_Message = | ||
| 179 | (RNDIS_Initialize_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 180 | RNDIS_Initialize_Complete_t* INITIALIZE_Response = | ||
| 181 | (RNDIS_Initialize_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 182 | |||
| 183 | INITIALIZE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT); | ||
| 184 | INITIALIZE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t)); | ||
| 185 | INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId; | ||
| 186 | INITIALIZE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||
| 187 | |||
| 188 | INITIALIZE_Response->MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR); | ||
| 189 | INITIALIZE_Response->MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR); | ||
| 190 | INITIALIZE_Response->DeviceFlags = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS); | ||
| 191 | INITIALIZE_Response->Medium = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3); | ||
| 192 | INITIALIZE_Response->MaxPacketsPerTransfer = CPU_TO_LE32(1); | ||
| 193 | INITIALIZE_Response->MaxTransferSize = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX); | ||
| 194 | INITIALIZE_Response->PacketAlignmentFactor = CPU_TO_LE32(0); | ||
| 195 | INITIALIZE_Response->AFListOffset = CPU_TO_LE32(0); | ||
| 196 | INITIALIZE_Response->AFListSize = CPU_TO_LE32(0); | ||
| 197 | |||
| 198 | RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized; | ||
| 199 | break; | ||
| 200 | case REMOTE_NDIS_HALT_MSG: | ||
| 201 | RNDISInterfaceInfo->State.ResponseReady = false; | ||
| 202 | |||
| 203 | MessageHeader->MessageLength = CPU_TO_LE32(0); | ||
| 204 | |||
| 205 | RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized; | ||
| 206 | break; | ||
| 207 | case REMOTE_NDIS_QUERY_MSG: | ||
| 208 | RNDISInterfaceInfo->State.ResponseReady = true; | ||
| 209 | |||
| 210 | RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 211 | RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 212 | uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid); | ||
| 213 | |||
| 214 | void* QueryData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) + | ||
| 215 | le32_to_cpu(QUERY_Message->InformationBufferOffset)]; | ||
| 216 | void* ResponseData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Query_Complete_t)]; | ||
| 217 | uint16_t ResponseSize; | ||
| 218 | |||
| 219 | QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT); | ||
| 220 | |||
| 221 | if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength), | ||
| 222 | ResponseData, &ResponseSize)) | ||
| 223 | { | ||
| 224 | QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||
| 225 | QUERY_Response->MessageLength = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize); | ||
| 226 | |||
| 227 | QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize); | ||
| 228 | QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t)); | ||
| 229 | } | ||
| 230 | else | ||
| 231 | { | ||
| 232 | QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED); | ||
| 233 | QUERY_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t)); | ||
| 234 | |||
| 235 | QUERY_Response->InformationBufferLength = CPU_TO_LE32(0); | ||
| 236 | QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0); | ||
| 237 | } | ||
| 238 | |||
| 239 | break; | ||
| 240 | case REMOTE_NDIS_SET_MSG: | ||
| 241 | RNDISInterfaceInfo->State.ResponseReady = true; | ||
| 242 | |||
| 243 | RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 244 | RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 245 | uint32_t SET_Oid = le32_to_cpu(SET_Message->Oid); | ||
| 246 | |||
| 247 | SET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT); | ||
| 248 | SET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t)); | ||
| 249 | SET_Response->RequestId = SET_Message->RequestId; | ||
| 250 | |||
| 251 | void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) + | ||
| 252 | le32_to_cpu(SET_Message->InformationBufferOffset)]; | ||
| 253 | |||
| 254 | SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, | ||
| 255 | le32_to_cpu(SET_Message->InformationBufferLength)) ? | ||
| 256 | REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED; | ||
| 257 | break; | ||
| 258 | case REMOTE_NDIS_RESET_MSG: | ||
| 259 | RNDISInterfaceInfo->State.ResponseReady = true; | ||
| 260 | |||
| 261 | RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 262 | |||
| 263 | RESET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT); | ||
| 264 | RESET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t)); | ||
| 265 | RESET_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||
| 266 | RESET_Response->AddressingReset = CPU_TO_LE32(0); | ||
| 267 | |||
| 268 | break; | ||
| 269 | case REMOTE_NDIS_KEEPALIVE_MSG: | ||
| 270 | RNDISInterfaceInfo->State.ResponseReady = true; | ||
| 271 | |||
| 272 | RNDIS_KeepAlive_Message_t* KEEPALIVE_Message = | ||
| 273 | (RNDIS_KeepAlive_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 274 | RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = | ||
| 275 | (RNDIS_KeepAlive_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer; | ||
| 276 | |||
| 277 | KEEPALIVE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT); | ||
| 278 | KEEPALIVE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t)); | ||
| 279 | KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId; | ||
| 280 | KEEPALIVE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS); | ||
| 281 | |||
| 282 | break; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 287 | const uint32_t OId, | ||
| 288 | void* const QueryData, | ||
| 289 | const uint16_t QuerySize, | ||
| 290 | void* ResponseData, | ||
| 291 | uint16_t* const ResponseSize) | ||
| 292 | { | ||
| 293 | (void)QueryData; | ||
| 294 | (void)QuerySize; | ||
| 295 | |||
| 296 | switch (OId) | ||
| 297 | { | ||
| 298 | case OID_GEN_SUPPORTED_LIST: | ||
| 299 | *ResponseSize = sizeof(AdapterSupportedOIDList); | ||
| 300 | |||
| 301 | memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList)); | ||
| 302 | |||
| 303 | return true; | ||
| 304 | case OID_GEN_PHYSICAL_MEDIUM: | ||
| 305 | *ResponseSize = sizeof(uint32_t); | ||
| 306 | |||
| 307 | /* Indicate that the device is a true ethernet link */ | ||
| 308 | *((uint32_t*)ResponseData) = CPU_TO_LE32(0); | ||
| 309 | |||
| 310 | return true; | ||
| 311 | case OID_GEN_HARDWARE_STATUS: | ||
| 312 | *ResponseSize = sizeof(uint32_t); | ||
| 313 | |||
| 314 | *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready); | ||
| 315 | |||
| 316 | return true; | ||
| 317 | case OID_GEN_MEDIA_SUPPORTED: | ||
| 318 | case OID_GEN_MEDIA_IN_USE: | ||
| 319 | *ResponseSize = sizeof(uint32_t); | ||
| 320 | |||
| 321 | *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3); | ||
| 322 | |||
| 323 | return true; | ||
| 324 | case OID_GEN_VENDOR_ID: | ||
| 325 | *ResponseSize = sizeof(uint32_t); | ||
| 326 | |||
| 327 | /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */ | ||
| 328 | *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF); | ||
| 329 | |||
| 330 | return true; | ||
| 331 | case OID_GEN_MAXIMUM_FRAME_SIZE: | ||
| 332 | case OID_GEN_TRANSMIT_BLOCK_SIZE: | ||
| 333 | case OID_GEN_RECEIVE_BLOCK_SIZE: | ||
| 334 | *ResponseSize = sizeof(uint32_t); | ||
| 335 | |||
| 336 | *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX); | ||
| 337 | |||
| 338 | return true; | ||
| 339 | case OID_GEN_VENDOR_DESCRIPTION: | ||
| 340 | *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1); | ||
| 341 | |||
| 342 | memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize); | ||
| 343 | |||
| 344 | return true; | ||
| 345 | case OID_GEN_MEDIA_CONNECT_STATUS: | ||
| 346 | *ResponseSize = sizeof(uint32_t); | ||
| 347 | |||
| 348 | *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED); | ||
| 349 | |||
| 350 | return true; | ||
| 351 | case OID_GEN_LINK_SPEED: | ||
| 352 | *ResponseSize = sizeof(uint32_t); | ||
| 353 | |||
| 354 | /* Indicate 10Mb/s link speed */ | ||
| 355 | *((uint32_t*)ResponseData) = CPU_TO_LE32(100000); | ||
| 356 | |||
| 357 | return true; | ||
| 358 | case OID_802_3_PERMANENT_ADDRESS: | ||
| 359 | case OID_802_3_CURRENT_ADDRESS: | ||
| 360 | *ResponseSize = sizeof(MAC_Address_t); | ||
| 361 | |||
| 362 | memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t)); | ||
| 363 | |||
| 364 | return true; | ||
| 365 | case OID_802_3_MAXIMUM_LIST_SIZE: | ||
| 366 | *ResponseSize = sizeof(uint32_t); | ||
| 367 | |||
| 368 | /* Indicate only one multicast address supported */ | ||
| 369 | *((uint32_t*)ResponseData) = CPU_TO_LE32(1); | ||
| 370 | |||
| 371 | return true; | ||
| 372 | case OID_GEN_CURRENT_PACKET_FILTER: | ||
| 373 | *ResponseSize = sizeof(uint32_t); | ||
| 374 | |||
| 375 | *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter); | ||
| 376 | |||
| 377 | return true; | ||
| 378 | case OID_GEN_XMIT_OK: | ||
| 379 | case OID_GEN_RCV_OK: | ||
| 380 | case OID_GEN_XMIT_ERROR: | ||
| 381 | case OID_GEN_RCV_ERROR: | ||
| 382 | case OID_GEN_RCV_NO_BUFFER: | ||
| 383 | case OID_802_3_RCV_ERROR_ALIGNMENT: | ||
| 384 | case OID_802_3_XMIT_ONE_COLLISION: | ||
| 385 | case OID_802_3_XMIT_MORE_COLLISIONS: | ||
| 386 | *ResponseSize = sizeof(uint32_t); | ||
| 387 | |||
| 388 | /* Unused statistic OIDs - always return 0 for each */ | ||
| 389 | *((uint32_t*)ResponseData) = CPU_TO_LE32(0); | ||
| 390 | |||
| 391 | return true; | ||
| 392 | case OID_GEN_MAXIMUM_TOTAL_SIZE: | ||
| 393 | *ResponseSize = sizeof(uint32_t); | ||
| 394 | |||
| 395 | /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */ | ||
| 396 | *((uint32_t*)ResponseData) = CPU_TO_LE32(RNDISInterfaceInfo->Config.MessageBufferLength + ETHERNET_FRAME_SIZE_MAX); | ||
| 397 | |||
| 398 | return true; | ||
| 399 | default: | ||
| 400 | return false; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 405 | const uint32_t OId, | ||
| 406 | const void* SetData, | ||
| 407 | const uint16_t SetSize) | ||
| 408 | { | ||
| 409 | (void)SetSize; | ||
| 410 | |||
| 411 | switch (OId) | ||
| 412 | { | ||
| 413 | case OID_GEN_CURRENT_PACKET_FILTER: | ||
| 414 | RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData)); | ||
| 415 | RNDISInterfaceInfo->State.CurrRNDISState = (RNDISInterfaceInfo->State.CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Initialized; | ||
| 416 | |||
| 417 | return true; | ||
| 418 | case OID_802_3_MULTICAST_LIST: | ||
| 419 | /* Do nothing - throw away the value from the host as it is unused */ | ||
| 420 | |||
| 421 | return true; | ||
| 422 | default: | ||
| 423 | return false; | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 428 | { | ||
| 429 | if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||
| 430 | (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||
| 431 | { | ||
| 432 | return false; | ||
| 433 | } | ||
| 434 | |||
| 435 | Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 436 | return Endpoint_IsOUTReceived(); | ||
| 437 | } | ||
| 438 | |||
| 439 | uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 440 | void* Buffer, | ||
| 441 | uint16_t* const PacketLength) | ||
| 442 | { | ||
| 443 | if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||
| 444 | (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||
| 445 | { | ||
| 446 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 447 | } | ||
| 448 | |||
| 449 | Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address); | ||
| 450 | |||
| 451 | *PacketLength = 0; | ||
| 452 | |||
| 453 | if (!(Endpoint_IsOUTReceived())) | ||
| 454 | return ENDPOINT_RWSTREAM_NoError; | ||
| 455 | |||
| 456 | RNDIS_Packet_Message_t RNDISPacketHeader; | ||
| 457 | Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); | ||
| 458 | |||
| 459 | if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX) | ||
| 460 | { | ||
| 461 | Endpoint_StallTransaction(); | ||
| 462 | |||
| 463 | return RNDIS_ERROR_LOGICAL_CMD_FAILED; | ||
| 464 | } | ||
| 465 | |||
| 466 | *PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength); | ||
| 467 | |||
| 468 | Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL); | ||
| 469 | Endpoint_ClearOUT(); | ||
| 470 | |||
| 471 | return ENDPOINT_RWSTREAM_NoError; | ||
| 472 | } | ||
| 473 | |||
| 474 | uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 475 | void* Buffer, | ||
| 476 | const uint16_t PacketLength) | ||
| 477 | { | ||
| 478 | uint8_t ErrorCode; | ||
| 479 | |||
| 480 | if ((USB_DeviceState != DEVICE_STATE_Configured) || | ||
| 481 | (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized)) | ||
| 482 | { | ||
| 483 | return ENDPOINT_RWSTREAM_DeviceDisconnected; | ||
| 484 | } | ||
| 485 | |||
| 486 | Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address); | ||
| 487 | |||
| 488 | if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) | ||
| 489 | return ErrorCode; | ||
| 490 | |||
| 491 | RNDIS_Packet_Message_t RNDISPacketHeader; | ||
| 492 | |||
| 493 | memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t)); | ||
| 494 | |||
| 495 | RNDISPacketHeader.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG); | ||
| 496 | RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength); | ||
| 497 | RNDISPacketHeader.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); | ||
| 498 | RNDISPacketHeader.DataLength = cpu_to_le32(PacketLength); | ||
| 499 | |||
| 500 | Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); | ||
| 501 | Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL); | ||
| 502 | Endpoint_ClearIN(); | ||
| 503 | |||
| 504 | return ENDPOINT_RWSTREAM_NoError; | ||
| 505 | } | ||
| 506 | |||
| 507 | #endif | ||
| 508 | |||
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h b/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h new file mode 100644 index 000000000..761bc2790 --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h | |||
| @@ -0,0 +1,207 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * \brief Device mode driver for the library USB RNDIS Class driver. | ||
| 33 | * | ||
| 34 | * Device mode driver for the library USB RNDIS Class driver. | ||
| 35 | * | ||
| 36 | * \note This file should not be included directly. It is automatically included as needed by the USB module driver | ||
| 37 | * dispatch header located in LUFA/Drivers/USB.h. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /** \ingroup Group_USBClassRNDIS | ||
| 41 | * \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver | ||
| 42 | * | ||
| 43 | * \section Sec_USBClassRNDISDevice_Dependencies Module Source Dependencies | ||
| 44 | * The following files must be built with any user project that uses this module: | ||
| 45 | * - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i> | ||
| 46 | * | ||
| 47 | * \section Sec_USBClassRNDISDevice_ModDescription Module Description | ||
| 48 | * Device Mode USB Class driver framework interface, for the RNDIS USB Class driver. | ||
| 49 | * | ||
| 50 | * @{ | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef _RNDIS_CLASS_DEVICE_H_ | ||
| 54 | #define _RNDIS_CLASS_DEVICE_H_ | ||
| 55 | |||
| 56 | /* Includes: */ | ||
| 57 | #include "../../USB.h" | ||
| 58 | #include "../Common/RNDISClassCommon.h" | ||
| 59 | |||
| 60 | /* Enable C linkage for C++ Compilers: */ | ||
| 61 | #if defined(__cplusplus) | ||
| 62 | extern "C" { | ||
| 63 | #endif | ||
| 64 | |||
| 65 | /* Preprocessor Checks: */ | ||
| 66 | #if !defined(__INCLUDE_FROM_RNDIS_DRIVER) | ||
| 67 | #error Do not include this file directly. Include LUFA/Drivers/USB.h instead. | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* Public Interface - May be used in end-application: */ | ||
| 71 | /* Type Defines: */ | ||
| 72 | /** \brief RNDIS Class Device Mode Configuration and State Structure. | ||
| 73 | * | ||
| 74 | * Class state structure. An instance of this structure should be made for each RNDIS interface | ||
| 75 | * within the user application, and passed to each of the RNDIS class driver functions as the | ||
| 76 | * \c RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information. | ||
| 77 | */ | ||
| 78 | typedef struct | ||
| 79 | { | ||
| 80 | struct | ||
| 81 | { | ||
| 82 | uint8_t ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */ | ||
| 83 | |||
| 84 | USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */ | ||
| 85 | USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */ | ||
| 86 | USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */ | ||
| 87 | |||
| 88 | char* AdapterVendorDescription; /**< String description of the adapter vendor. */ | ||
| 89 | MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */ | ||
| 90 | |||
| 91 | uint8_t* MessageBuffer; /**< Buffer where RNDIS messages can be stored by the internal driver. This | ||
| 92 | * should be at least 132 bytes in length for minimal functionality. */ | ||
| 93 | uint16_t MessageBufferLength; /**< Length in bytes of the \ref MessageBuffer RNDIS buffer. */ | ||
| 94 | } Config; /**< Config data for the USB class interface within the device. All elements in this section | ||
| 95 | * <b>must</b> be set or the interface will fail to enumerate and operate correctly. | ||
| 96 | */ | ||
| 97 | struct | ||
| 98 | { | ||
| 99 | bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */ | ||
| 100 | uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \ref RNDIS_States_t enum. */ | ||
| 101 | uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver. */ | ||
| 102 | } State; /**< State data for the USB class interface within the device. All elements in this section | ||
| 103 | * are reset to their defaults when the interface is enumerated. | ||
| 104 | */ | ||
| 105 | } USB_ClassInfo_RNDIS_Device_t; | ||
| 106 | |||
| 107 | /* Function Prototypes: */ | ||
| 108 | /** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library | ||
| 109 | * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration | ||
| 110 | * containing the given RNDIS interface is selected. | ||
| 111 | * | ||
| 112 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. | ||
| 113 | * | ||
| 114 | * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise. | ||
| 115 | */ | ||
| 116 | bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 117 | |||
| 118 | /** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be | ||
| 119 | * linked to the library \ref EVENT_USB_Device_ControlRequest() event. | ||
| 120 | * | ||
| 121 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. | ||
| 122 | */ | ||
| 123 | void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 124 | |||
| 125 | /** General management task for a given RNDIS class interface, required for the correct operation of the interface. This should | ||
| 126 | * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). | ||
| 127 | * | ||
| 128 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. | ||
| 129 | */ | ||
| 130 | void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 131 | |||
| 132 | /** Determines if a packet is currently waiting for the device to read in and process. | ||
| 133 | * | ||
| 134 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||
| 135 | * call will fail. | ||
| 136 | * | ||
| 137 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state. | ||
| 138 | * | ||
| 139 | * \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise. | ||
| 140 | */ | ||
| 141 | bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); | ||
| 142 | |||
| 143 | /** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave | ||
| 144 | * only the packet contents for processing by the device in the nominated buffer. | ||
| 145 | * | ||
| 146 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||
| 147 | * call will fail. | ||
| 148 | * | ||
| 149 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state. | ||
| 150 | * \param[out] Buffer Pointer to a buffer where the packer data is to be written to. | ||
| 151 | * \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored. | ||
| 152 | * | ||
| 153 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 154 | */ | ||
| 155 | uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 156 | void* Buffer, | ||
| 157 | uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1); | ||
| 158 | |||
| 159 | /** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header. | ||
| 160 | * | ||
| 161 | * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the | ||
| 162 | * call will fail. | ||
| 163 | * | ||
| 164 | * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state. | ||
| 165 | * \param[in] Buffer Pointer to a buffer where the packer data is to be read from. | ||
| 166 | * \param[in] PacketLength Length in bytes of the packet to send. | ||
| 167 | * | ||
| 168 | * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. | ||
| 169 | */ | ||
| 170 | uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 171 | void* Buffer, | ||
| 172 | const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1); | ||
| 173 | |||
| 174 | /* Private Interface - For use in library only: */ | ||
| 175 | #if !defined(__DOXYGEN__) | ||
| 176 | /* Macros: */ | ||
| 177 | #define RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_Query_Complete_t) | ||
| 178 | |||
| 179 | /* Function Prototypes: */ | ||
| 180 | #if defined(__INCLUDE_FROM_RNDIS_DEVICE_C) | ||
| 181 | static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) | ||
| 182 | ATTR_NON_NULL_PTR_ARG(1); | ||
| 183 | static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 184 | const uint32_t OId, | ||
| 185 | void* const QueryData, | ||
| 186 | const uint16_t QuerySize, | ||
| 187 | void* ResponseData, | ||
| 188 | uint16_t* const ResponseSize) ATTR_NON_NULL_PTR_ARG(1) | ||
| 189 | ATTR_NON_NULL_PTR_ARG(5) ATTR_NON_NULL_PTR_ARG(6); | ||
| 190 | static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, | ||
| 191 | const uint32_t OId, | ||
| 192 | const void* SetData, | ||
| 193 | const uint16_t SetSize) ATTR_NON_NULL_PTR_ARG(1) | ||
| 194 | ATTR_NON_NULL_PTR_ARG(3); | ||
| 195 | #endif | ||
| 196 | |||
| 197 | #endif | ||
| 198 | |||
| 199 | /* Disable C linkage for C++ Compilers: */ | ||
| 200 | #if defined(__cplusplus) | ||
| 201 | } | ||
| 202 | #endif | ||
| 203 | |||
| 204 | #endif | ||
| 205 | |||
| 206 | /** @} */ | ||
| 207 | |||
