diff options
Diffstat (limited to 'LUFA/Drivers/USB')
24 files changed, 2124 insertions, 21 deletions
diff --git a/LUFA/Drivers/USB/Class/Device/Audio.c b/LUFA/Drivers/USB/Class/Device/Audio.c new file mode 100644 index 000000000..b0800ba0f --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/Audio.c @@ -0,0 +1,154 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "Audio.h"
+
+void USB_Audio_ProcessControlPacket(USB_ClassInfo_Audio_t* AudioInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+// if (USB_ControlRequest.wIndex != AudioInterfaceInfo->InterfaceNumber)
+// return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_SetInterface:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ AudioInterfaceInfo->InterfaceEnabled = (USB_ControlRequest.wValue != 0);
+
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ }
+}
+
+bool USB_Audio_ConfigureEndpoints(USB_ClassInfo_Audio_t* AudioInterfaceInfo)
+{
+ if (AudioInterfaceInfo->DataINEndpointNumber)
+ {
+ if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->DataINEndpointNumber, EP_TYPE_ISOCHRONOUS,
+ ENDPOINT_DIR_IN, AudioInterfaceInfo->DataINEndpointSize,
+ ENDPOINT_BANK_DOUBLE)))
+ {
+ return false;
+ }
+ }
+
+ if (AudioInterfaceInfo->DataOUTEndpointNumber)
+ {
+ if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_ISOCHRONOUS,
+ ENDPOINT_DIR_OUT, AudioInterfaceInfo->DataOUTEndpointSize,
+ ENDPOINT_BANK_DOUBLE)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int8_t USB_Audio_ReadSample8(void)
+{
+ int8_t Sample;
+
+ Sample = Endpoint_Read_Byte();
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+}
+
+int16_t USB_Audio_ReadSample16(void)
+{
+ int16_t Sample;
+
+ Sample = (int16_t)Endpoint_Read_Word_LE();
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+}
+
+int32_t USB_Audio_ReadSample24(void)
+{
+ int32_t Sample;
+
+ Sample = (((uint32_t)Endpoint_Read_Byte() << 16) | Endpoint_Read_Word_LE());
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+}
+
+void USB_Audio_WriteSample8(int8_t Sample)
+{
+ Endpoint_Write_Byte(Sample);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearIN();
+}
+
+void USB_Audio_WriteSample16(int16_t Sample)
+{
+ Endpoint_Write_Word_LE(Sample);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearIN();
+}
+
+void USB_Audio_WriteSample24(int32_t Sample)
+{
+ Endpoint_Write_Byte(Sample >> 16);
+ Endpoint_Write_Word_LE(Sample);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearIN();
+}
+
+bool USB_Audio_IsSampleReceived(USB_ClassInfo_Audio_t* AudioInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->DataOUTEndpointNumber);
+ return Endpoint_IsOUTReceived();
+}
+
+bool USB_Audio_IsReadyForNextSample(USB_ClassInfo_Audio_t* AudioInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->DataINEndpointNumber);
+ return Endpoint_IsINReady();
+}
diff --git a/LUFA/Drivers/USB/Class/Device/Audio.h b/LUFA/Drivers/USB/Class/Device/Audio.h new file mode 100644 index 000000000..aa7b4069c --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/Audio.h @@ -0,0 +1,70 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _AUDIO_CLASS_H_
+#define _AUDIO_CLASS_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+
+ #include <string.h>
+
+ /* Macros: */
+
+ /* Enums: */
+
+ /* Type Defines: */
+ typedef struct
+ {
+ uint8_t InterfaceNumber;
+
+ uint8_t DataINEndpointNumber;
+ uint16_t DataINEndpointSize;
+
+ uint8_t DataOUTEndpointNumber;
+ uint16_t DataOUTEndpointSize;
+
+ bool InterfaceEnabled;
+ } USB_ClassInfo_Audio_t;
+
+ /* Function Prototypes: */
+ bool USB_Audio_ConfigureEndpoints(USB_ClassInfo_Audio_t* AudioInterfaceInfo);
+ void USB_Audio_ProcessControlPacket(USB_ClassInfo_Audio_t* AudioInterfaceInfo);
+ void USB_Audio_USBTask(USB_ClassInfo_Audio_t* AudioInterfaceInfo);
+
+ int8_t USB_Audio_ReadSample8(void);
+ int16_t USB_Audio_ReadSample16(void);
+ int32_t USB_Audio_ReadSample24(void);
+ void USB_Audio_WriteSample8(int8_t Sample);
+ void USB_Audio_WriteSample16(int16_t Sample);
+ void USB_Audio_WriteSample24(int32_t Sample);
+ bool USB_Audio_IsSampleReceived(USB_ClassInfo_Audio_t* AudioInterfaceInfo);
+ bool USB_Audio_IsReadyForNextSample(USB_ClassInfo_Audio_t* AudioInterfaceInfo);
+#endif
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c new file mode 100644 index 000000000..8acaac7a1 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDC.c @@ -0,0 +1,185 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define INCLUDE_FROM_CDC_CLASS_C
+#include "CDC.h"
+
+void USB_CDC_Event_Stub(void)
+{
+
+}
+
+void USB_CDC_ProcessControlPacket(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != CDCInterfaceInfo->ControlInterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->LineEncoding, sizeof(CDCInterfaceInfo->LineEncoding));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->LineEncoding, sizeof(CDCInterfaceInfo->LineEncoding));
+ Endpoint_ClearIN();
+
+ EVENT_USB_CDC_LineEncodingChanged(CDCInterfaceInfo);
+ }
+
+ break;
+ case REQ_SetControlLineState:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ CDCInterfaceInfo->ControlLineState = USB_ControlRequest.wValue;
+
+ EVENT_USB_CDC_ControLineStateChanged();
+
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ }
+}
+
+bool USB_CDC_ConfigureEndpoints(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+{
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, CDCInterfaceInfo->DataINEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, CDCInterfaceInfo->DataOUTEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->NotificationEndpointNumber, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, CDCInterfaceInfo->NotificationEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+{
+ if (!(USB_IsConnected))
+ return;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);
+
+ if (!(Endpoint_BytesInEndpoint()))
+ return;
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+ while (!(Endpoint_IsReadWriteAllowed()));
+ }
+
+ Endpoint_ClearIN();
+}
+
+void USB_CDC_SendString(USB_ClassInfo_CDC_t* CDCInterfaceInfo, char* Data, uint16_t Length)
+{
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);
+ Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
+}
+
+void USB_CDC_SendByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint8_t Data)
+{
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataINEndpointNumber);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+ while (!(Endpoint_IsReadWriteAllowed()));
+ }
+
+ Endpoint_Write_Byte(Data);
+}
+
+uint16_t USB_CDC_BytesReceived(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber);
+
+ return Endpoint_BytesInEndpoint();
+}
+
+uint8_t USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->DataOUTEndpointNumber);
+
+ uint8_t DataByte = Endpoint_Read_Byte();
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+
+ return DataByte;
+}
+
+void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask)
+{
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->NotificationEndpointNumber);
+
+ USB_Request_Header_t Notification = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = NOTIF_SerialState,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = sizeof(uint16_t),
+ };
+
+ Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);
+ Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask), NO_STREAM_CALLBACK);
+ Endpoint_ClearIN();
+}
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h new file mode 100644 index 000000000..bbe1c9838 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDC.h @@ -0,0 +1,188 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _CDC_CLASS_H_
+#define _CDC_CLASS_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+
+ #include <string.h>
+
+ /* Macros: */
+ /** CDC Class specific request to get the current virtual serial port configuration settings. */
+ #define REQ_GetLineEncoding 0x21
+
+ /** CDC Class specific request to set the current virtual serial port configuration settings. */
+ #define REQ_SetLineEncoding 0x20
+
+ /** CDC Class specific request to set the current virtual serial port handshake line states. */
+ #define REQ_SetControlLineState 0x22
+
+ /** Notification type constant for a change in the virtual serial port handshake line states, for
+ * use with a USB_Notification_Header_t notification structure when sent to the host via the CDC
+ * notification endpoint.
+ */
+ #define NOTIF_SerialState 0x20
+
+ /** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request
+ * from the host, to indicate that the DTR line state should be high.
+ */
+ #define CONTROL_LINE_OUT_DTR (1 << 0)
+
+ /** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request
+ * from the host, to indicate that theRTS line state should be high.
+ */
+ #define CONTROL_LINE_OUT_RTS (1 << 1)
+
+ /** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification
+ * from the device to the host, to indicate that the DCD line state is currently high.
+ */
+ #define CONTROL_LINE_IN_DCD (1 << 0)
+
+ /** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification
+ * from the device to the host, to indicate that the DSR line state is currently high.
+ */
+ #define CONTROL_LINE_IN_DSR (1 << 1)
+
+ /** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification
+ * from the device to the host, to indicate that the BREAK line state is currently high.
+ */
+ #define CONTROL_LINE_IN_BREAK (1 << 2)
+
+ /** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification
+ * from the device to the host, to indicate that the RING line state is currently high.
+ */
+ #define CONTROL_LINE_IN_RING (1 << 3)
+
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
+ * to indicate that a framing error has occurred on the virtual serial port.
+ */
+ #define CONTROL_LINE_IN_FRAMEERROR (1 << 4)
+
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
+ * to indicate that a parity error has occurred on the virtual serial port.
+ */
+ #define CONTROL_LINE_IN_PARITYERROR (1 << 5)
+
+ /** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
+ * to indicate that a data overrun error has occurred on the virtual serial port.
+ */
+ #define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
+
+ /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
+ * uniform structure but variable sized data payloads, thus cannot be represented accurately by
+ * a single typedef struct. A macro is used instead so that functional descriptors can be created
+ * easily by specifying the size of the payload. This allows sizeof() to work correctly.
+ *
+ * \param DataSize Size in bytes of the CDC functional descriptor's data payload
+ */
+ #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
+ struct \
+ { \
+ USB_Descriptor_Header_t Header; \
+ uint8_t SubType; \
+ uint8_t Data[DataSize]; \
+ }
+
+ /* Enums: */
+ /** Enum for the possible line encoding formats of a virtual serial port. */
+ enum CDCDevice_CDC_LineCodingFormats_t
+ {
+ OneStopBit = 0, /**< Each frame contains one stop bit */
+ OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */
+ TwoStopBits = 2, /**< Each frame contains two stop bits */
+ };
+
+ /** Enum for the possible line encoding parity settings of a virtual serial port. */
+ enum CDCDevice_LineCodingParity_t
+ {
+ Parity_None = 0, /**< No parity bit mode on each frame */
+ Parity_Odd = 1, /**< Odd parity bit mode on each frame */
+ Parity_Even = 2, /**< Even parity bit mode on each frame */
+ Parity_Mark = 3, /**< Mark parity bit mode on each frame */
+ Parity_Space = 4, /**< Space parity bit mode on each frame */
+ };
+
+ /* Type Defines: */
+ /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
+ * as set by the host via a class specific request.
+ */
+ typedef struct
+ {
+ uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
+
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
+ uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
+
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
+
+ uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
+ uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
+
+ uint8_t ControlLineState;
+
+ struct
+ {
+ uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
+ uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
+ * CDCDevice_CDC_LineCodingFormats_t enum
+ */
+ uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
+ * CDCDevice_LineCodingParity_t enum
+ */
+ uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
+ } LineEncoding;
+ } USB_ClassInfo_CDC_t;
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_CDC_CLASS_C)
+ void USB_CDC_Event_Stub(void);
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo)
+ ATTR_WEAK ATTR_ALIAS(USB_CDC_Event_Stub);
+ void EVENT_USB_CDC_ControLineStateChanged(void) ATTR_WEAK ATTR_ALIAS(USB_CDC_Event_Stub);;
+ #endif
+
+ void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ bool USB_CDC_ConfigureEndpoints(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ void USB_CDC_ProcessControlPacket(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ void USB_CDC_USBTask(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+
+ void EVENT_USB_CDC_LineEncodingChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ void EVENT_USB_CDC_ControLineStateChanged(void);
+
+ void USB_CDC_SendString(USB_ClassInfo_CDC_t* CDCInterfaceInfo, char* Data, uint16_t Length);
+ void USB_CDC_SendByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint8_t Data);
+ uint16_t USB_CDC_BytesReceived(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ uint8_t USB_CDC_ReceiveByte(USB_ClassInfo_CDC_t* CDCInterfaceInfo);
+ void USB_CDC_SendSerialLineStateChanged(USB_ClassInfo_CDC_t* CDCInterfaceInfo, uint16_t LineStateMask);
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c new file mode 100644 index 000000000..fbc5e3a5c --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HID.c @@ -0,0 +1,211 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "HID.h"
+
+void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != HIDInterfaceInfo->InterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_GetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ uint8_t ReportINData[HIDInterfaceInfo->ReportBufferSize];
+ uint16_t ReportINSize;
+
+ memset(ReportINData, 0, sizeof(ReportINData));
+
+ ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);
+
+ Endpoint_Write_Control_Stream_LE(ReportINData, ReportINSize);
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case REQ_SetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ uint16_t ReportOUTSize = USB_ControlRequest.wLength;
+ uint8_t ReportOUTData[ReportOUTSize];
+
+ Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);
+ Endpoint_ClearIN();
+
+ CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);
+ }
+
+ break;
+ case REQ_GetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_Byte(HIDInterfaceInfo->UsingReportProtocol);
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsOUTReceived()));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case REQ_SetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ HIDInterfaceInfo->UsingReportProtocol = (USB_ControlRequest.wValue != 0x0000);
+
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ case REQ_SetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ HIDInterfaceInfo->IdleCount = ((USB_ControlRequest.wValue >> 8) << 2);
+
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ case REQ_GetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_Byte(HIDInterfaceInfo->IdleCount >> 2);
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsOUTReceived()));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ }
+}
+
+bool USB_HID_ConfigureEndpoints(USB_ClassInfo_HID_t* HIDInterfaceInfo)
+{
+ HIDInterfaceInfo->UsingReportProtocol = true;
+
+ if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->ReportINEndpointNumber, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, HIDInterfaceInfo->ReportINEndpointSize, ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (HIDInterfaceInfo->ReportOUTEndpointNumber)
+ {
+ if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_OUT, HIDInterfaceInfo->ReportOUTEndpointSize, ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void USB_HID_RegisterStartOfFrame(USB_ClassInfo_HID_t* HIDInterfaceInfo)
+{
+ if (HIDInterfaceInfo->IdleMSRemaining)
+ HIDInterfaceInfo->IdleMSRemaining--;
+}
+
+void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo)
+{
+ if (!(USB_IsConnected))
+ return;
+
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->ReportINEndpointNumber);
+
+ if (Endpoint_IsReadWriteAllowed() &&
+ !(HIDInterfaceInfo->IdleCount && HIDInterfaceInfo->IdleMSRemaining))
+ {
+ if (HIDInterfaceInfo->IdleCount && !(HIDInterfaceInfo->IdleMSRemaining))
+ HIDInterfaceInfo->IdleMSRemaining = HIDInterfaceInfo->IdleCount;
+
+ uint8_t ReportINData[HIDInterfaceInfo->ReportBufferSize];
+ uint16_t ReportINSize;
+
+ memset(ReportINData, 0, sizeof(ReportINData));
+
+ ReportINSize = CALLBACK_USB_HID_CreateNextHIDReport(HIDInterfaceInfo, ReportINData);
+
+ if (ReportINSize)
+ {
+ Endpoint_Write_Stream_LE(ReportINData, ReportINSize
+ #if !defined(NO_STREAM_CALLBACKS)
+ , NO_STREAM_CALLBACK
+ #endif
+ );
+ }
+
+ Endpoint_ClearIN();
+ }
+
+ if (HIDInterfaceInfo->ReportOUTEndpointNumber)
+ {
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->ReportOUTEndpointNumber);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ uint16_t ReportOUTSize = Endpoint_BytesInEndpoint();
+ uint8_t ReportOUTData[ReportOUTSize];
+
+ if (ReportOUTSize)
+ {
+ Endpoint_Read_Stream_LE(ReportOUTData, ReportOUTSize
+ #if !defined(NO_STREAM_CALLBACKS)
+ , NO_STREAM_CALLBACK
+ #endif
+ );
+ }
+
+ CALLBACK_USB_HID_ProcessReceivedHIDReport(HIDInterfaceInfo, ReportOUTData, ReportOUTSize);
+
+ Endpoint_ClearOUT();
+ }
+ }
+}
diff --git a/LUFA/Drivers/USB/Class/Device/HID.h b/LUFA/Drivers/USB/Class/Device/HID.h new file mode 100644 index 000000000..8fdeb064a --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HID.h @@ -0,0 +1,115 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _HID_CLASS_H_
+#define _HID_CLASS_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+
+ #include <string.h>
+
+ /* Macros: */
+ /** HID Class Specific Request to get the current HID report from the device. */
+ #define REQ_GetReport 0x01
+
+ /** HID Class Specific Request to get the current device idle count. */
+ #define REQ_GetIdle 0x02
+
+ /** HID Class Specific Request to set the current HID report to the device. */
+ #define REQ_SetReport 0x09
+
+ /** HID Class Specific Request to set the device's idle count. */
+ #define REQ_SetIdle 0x0A
+
+ /** HID Class Specific Request to get the current HID report protocol mode. */
+ #define REQ_GetProtocol 0x03
+
+ /** HID Class Specific Request to set the current HID report protocol mode. */
+ #define REQ_SetProtocol 0x0B
+
+ /** Descriptor header type value, to indicate a HID class HID descriptor. */
+ #define DTYPE_HID 0x21
+
+ /** Descriptor header type value, to indicate a HID class HID report descriptor. */
+ #define DTYPE_Report 0x22
+
+ /* Type Defines: */
+ /** Type define for the HID class specific HID descriptor, to describe the HID device's specifications. Refer to the HID
+ * specification for details on the structure elements.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header;
+
+ uint16_t HIDSpec;
+ uint8_t CountryCode;
+
+ uint8_t TotalReportDescriptors;
+
+ uint8_t HIDReportType;
+ uint16_t HIDReportLength;
+ } USB_Descriptor_HID_t;
+
+ /** Type define for the data type used to store HID report descriptor elements. */
+ typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+
+ /** Class state structure. An instance of this structure should be made for each HID interface
+ * within the user application, and passed to each of the HID class driver functions as the
+ * HIDInterfaceInfo parameter. The contents of this structure should be set to their correct
+ * values when used, or ommitted to force the library to use default values.
+ */
+ typedef struct
+ {
+ uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device */
+
+ uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint */
+ uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint */
+
+ uint8_t ReportOUTEndpointNumber; /**< Endpoint number of the HID interface's OUT report endpoint, if used */
+ uint16_t ReportOUTEndpointSize; /**< Size in bytes of the HID interface's OUT report endpoint, if used */
+
+ uint8_t ReportBufferSize;
+
+ bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode */
+ uint16_t IdleCount; /**< Report idle period, in ms, set by the host */
+ uint16_t IdleMSRemaining; /**< Total number of ms remaining before the idle period elapses */
+ } USB_ClassInfo_HID_t;
+
+ /* Function Prototypes: */
+ bool USB_HID_ConfigureEndpoints(USB_ClassInfo_HID_t* HIDInterfaceInfo);
+ void USB_HID_ProcessControlPacket(USB_ClassInfo_HID_t* HIDInterfaceInfo);
+ void USB_HID_RegisterStartOfFrame(USB_ClassInfo_HID_t* HIDInterfaceInfo);
+ void USB_HID_USBTask(USB_ClassInfo_HID_t* HIDInterfaceInfo);
+
+ uint16_t CALLBACK_USB_HID_CreateNextHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData);
+ void CALLBACK_USB_HID_ProcessReceivedHIDReport(USB_ClassInfo_HID_t* HIDInterfaceInfo, void* ReportData, uint16_t ReportSize);
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.c b/LUFA/Drivers/USB/Class/Device/MassStorage.c new file mode 100644 index 000000000..1c41f6046 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorage.c @@ -0,0 +1,208 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define INCLUDE_FROM_MS_CLASS_C
+#include "MassStorage.h"
+
+static USB_ClassInfo_MS_t* CallbackMSInterfaceInfo;
+
+void USB_MS_ProcessControlPacket(USB_ClassInfo_MS_t* MSInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != MSInterfaceInfo->InterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_MassStorageReset:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ MSInterfaceInfo->IsMassStoreReset = true;
+
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ case REQ_GetMaxLUN:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_Byte(MSInterfaceInfo->TotalLUNs - 1);
+
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsOUTReceived()));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ }
+}
+
+bool USB_MS_ConfigureEndpoints(USB_ClassInfo_MS_t* MSInterfaceInfo)
+{
+ if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, MSInterfaceInfo->DataINEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, MSInterfaceInfo->DataOUTEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void USB_MS_USBTask(USB_ClassInfo_MS_t* MSInterfaceInfo)
+{
+ if (!(USB_IsConnected))
+ return;
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);
+
+ if (Endpoint_IsReadWriteAllowed())
+ {
+ if (USB_MS_ReadInCommandBlock(MSInterfaceInfo))
+ {
+ if (MSInterfaceInfo->CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);
+
+ MSInterfaceInfo->CommandStatus.Status = CALLBACK_USB_MS_SCSICommandReceived(MSInterfaceInfo) ?
+ Command_Pass : Command_Fail;
+ MSInterfaceInfo->CommandStatus.Signature = CSW_SIGNATURE;
+ MSInterfaceInfo->CommandStatus.Tag = MSInterfaceInfo->CommandBlock.Tag;
+ MSInterfaceInfo->CommandStatus.DataTransferResidue = MSInterfaceInfo->CommandBlock.DataTransferLength;
+
+ if ((MSInterfaceInfo->CommandStatus.Status == Command_Fail) && (MSInterfaceInfo->CommandStatus.DataTransferResidue))
+ Endpoint_StallTransaction();
+
+ USB_MS_ReturnCommandStatus(MSInterfaceInfo);
+
+ if (MSInterfaceInfo->IsMassStoreReset)
+ {
+ Endpoint_ResetFIFO(MSInterfaceInfo->DataOUTEndpointNumber);
+ Endpoint_ResetFIFO(MSInterfaceInfo->DataINEndpointNumber);
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);
+ Endpoint_ClearStall();
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);
+ Endpoint_ClearStall();
+
+ MSInterfaceInfo->IsMassStoreReset = false;
+ }
+ }
+ }
+}
+
+static bool USB_MS_ReadInCommandBlock(USB_ClassInfo_MS_t* MSInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);
+
+ CallbackMSInterfaceInfo = MSInterfaceInfo;
+ Endpoint_Read_Stream_LE(&MSInterfaceInfo->CommandBlock,
+ (sizeof(CommandBlockWrapper_t) - MAX_SCSI_COMMAND_LENGTH),
+ StreamCallback_AbortOnMassStoreReset);
+
+ if ((MSInterfaceInfo->CommandBlock.Signature != CBW_SIGNATURE) ||
+ (MSInterfaceInfo->CommandBlock.LUN >= MSInterfaceInfo->TotalLUNs) ||
+ (MSInterfaceInfo->CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))
+ {
+ Endpoint_StallTransaction();
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);
+ Endpoint_StallTransaction();
+
+ return false;
+ }
+
+ CallbackMSInterfaceInfo = MSInterfaceInfo;
+ Endpoint_Read_Stream_LE(&MSInterfaceInfo->CommandBlock.SCSICommandData,
+ MSInterfaceInfo->CommandBlock.SCSICommandLength,
+ StreamCallback_AbortOnMassStoreReset);
+
+ Endpoint_ClearOUT();
+
+ if (MSInterfaceInfo->IsMassStoreReset)
+ return false;
+
+ return true;
+}
+
+static void USB_MS_ReturnCommandStatus(USB_ClassInfo_MS_t* MSInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataOUTEndpointNumber);
+
+ while (Endpoint_IsStalled())
+ {
+ USB_USBTask();
+
+ if (MSInterfaceInfo->IsMassStoreReset)
+ return;
+ }
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->DataINEndpointNumber);
+
+ while (Endpoint_IsStalled())
+ {
+ USB_USBTask();
+
+ if (MSInterfaceInfo->IsMassStoreReset)
+ return;
+ }
+
+ CallbackMSInterfaceInfo = MSInterfaceInfo;
+ Endpoint_Write_Stream_LE(&MSInterfaceInfo->CommandStatus, sizeof(CommandStatusWrapper_t),
+ StreamCallback_AbortOnMassStoreReset);
+
+ Endpoint_ClearIN();
+
+ if (MSInterfaceInfo->IsMassStoreReset)
+ return;
+}
+
+static uint8_t StreamCallback_AbortOnMassStoreReset(void)
+{
+ USB_MS_USBTask(CallbackMSInterfaceInfo);
+
+ if (CallbackMSInterfaceInfo->IsMassStoreReset)
+ return STREAMCALLBACK_Abort;
+ else
+ return STREAMCALLBACK_Continue;
+}
diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.h b/LUFA/Drivers/USB/Class/Device/MassStorage.h new file mode 100644 index 000000000..c1874b218 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorage.h @@ -0,0 +1,127 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _MS_CLASS_H_
+#define _MS_CLASS_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+
+ #include <string.h>
+
+ /* Macros: */
+ /** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */
+ #define REQ_MassStorageReset 0xFF
+
+ /** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */
+ #define REQ_GetMaxLUN 0xFE
+
+ /** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */
+ #define MAX_SCSI_COMMAND_LENGTH 16
+
+ /** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
+ #define CBW_SIGNATURE 0x43425355UL
+
+ /** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
+ #define CSW_SIGNATURE 0x53425355UL
+
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
+ #define COMMAND_DIRECTION_DATA_OUT (0 << 7)
+
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
+ #define COMMAND_DIRECTION_DATA_IN (1 << 7)
+
+ /* Type defines: */
+ /** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
+ typedef struct
+ {
+ uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
+ uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */
+ uint8_t Flags; /**< Command block flags, indicating command data direction */
+ uint8_t LUN; /**< Logical Unit number this command is issued to */
+ uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */
+ uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */
+ } CommandBlockWrapper_t;
+
+ /** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
+ typedef struct
+ {
+ uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
+ uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */
+ uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */
+ } CommandStatusWrapper_t;
+
+ /* Enums: */
+ /** Enum for the possible command status wrapper return status codes. */
+ enum MassStorage_CommandStatusCodes_t
+ {
+ Command_Pass = 0, /**< Command completed with no error */
+ Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */
+ Phase_Error = 2 /**< Command failed due to being invalid in the current phase */
+ };
+
+ /* Type Defines: */
+ /** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
+ * as set by the host via a class specific request.
+ */
+ typedef struct
+ {
+ uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device */
+
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint */
+ uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint */
+
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint */
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint */
+
+ uint8_t TotalLUNs;
+
+ CommandBlockWrapper_t CommandBlock;
+ CommandStatusWrapper_t CommandStatus;
+
+ bool IsMassStoreReset;
+ } USB_ClassInfo_MS_t;
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_MS_CLASS_C)
+ static void USB_MS_ReturnCommandStatus(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static bool USB_MS_ReadInCommandBlock(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ static uint8_t StreamCallback_AbortOnMassStoreReset(void);
+ #endif
+
+ void USB_MS_USBTask(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ bool USB_MS_ConfigureEndpoints(USB_ClassInfo_MS_t* MSInterfaceInfo);
+ void USB_MS_ProcessControlPacket(USB_ClassInfo_MS_t* MSInterfaceInfo);
+
+ bool CALLBACK_USB_MS_SCSICommandReceived(USB_ClassInfo_MS_t* MSInterfaceInfo);
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.c b/LUFA/Drivers/USB/Class/Device/RNDIS.c new file mode 100644 index 000000000..49c7df01d --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDIS.c @@ -0,0 +1,456 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define INCLUDE_FROM_RNDIS_CLASS_C
+#include "RNDIS.h"
+
+static const uint32_t PROGMEM AdapterSupportedOIDList[] =
+ {
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_PHYSICAL_MEDIUM,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+ };
+
+void USB_RNDIS_ProcessControlPacket(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->ControlInterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_SendEncapsulatedCommand:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->RNDISMessageBuffer, USB_ControlRequest.wLength);
+ Endpoint_ClearIN();
+
+ USB_RNDIS_ProcessRNDISControlMessage(RNDISInterfaceInfo);
+ }
+
+ break;
+ case REQ_GetEncapsulatedResponse:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ if (!(MessageHeader->MessageLength))
+ {
+ RNDISInterfaceInfo->RNDISMessageBuffer[0] = 0;
+ MessageHeader->MessageLength = 1;
+ }
+
+ Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->RNDISMessageBuffer, MessageHeader->MessageLength);
+ Endpoint_ClearOUT();
+
+ MessageHeader->MessageLength = 0;
+ }
+
+ break;
+ }
+}
+
+bool USB_RNDIS_ConfigureEndpoints(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
+{
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, RNDISInterfaceInfo->DataINEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, RNDISInterfaceInfo->DataOUTEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, RNDISInterfaceInfo->NotificationEndpointSize,
+ ENDPOINT_BANK_SINGLE)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
+{
+ if (!(USB_IsConnected))
+ return;
+
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber);
+
+ if (Endpoint_IsINReady() && RNDISInterfaceInfo->ResponseReady)
+ {
+ USB_Request_Header_t Notification = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = NOTIF_ResponseAvailable,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);
+
+ Endpoint_ClearIN();
+
+ RNDISInterfaceInfo->ResponseReady = false;
+ }
+
+ if ((RNDISInterfaceInfo->CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
+ {
+ RNDIS_PACKET_MSG_t RNDISPacketHeader;
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber);
+
+ if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->FrameIN.FrameInBuffer))
+ {
+ Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t), NO_STREAM_CALLBACK);
+
+ if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
+ {
+ Endpoint_StallTransaction();
+ return;
+ }
+
+ Endpoint_Read_Stream_LE(RNDISInterfaceInfo->FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
+
+ Endpoint_ClearOUT();
+
+ RNDISInterfaceInfo->FrameIN.FrameLength = RNDISPacketHeader.DataLength;
+
+ RNDISInterfaceInfo->FrameIN.FrameInBuffer = true;
+ }
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataINEndpointNumber);
+
+ if (Endpoint_IsINReady() && RNDISInterfaceInfo->FrameOUT.FrameInBuffer)
+ {
+ memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t));
+
+ RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
+ RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + RNDISInterfaceInfo->FrameOUT.FrameLength);
+ RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t));
+ RNDISPacketHeader.DataLength = RNDISInterfaceInfo->FrameOUT.FrameLength;
+
+ Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t), NO_STREAM_CALLBACK);
+ Endpoint_Write_Stream_LE(RNDISInterfaceInfo->FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
+ Endpoint_ClearIN();
+
+ RNDISInterfaceInfo->FrameOUT.FrameInBuffer = false;
+ }
+ }
+}
+
+void USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
+{
+ /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
+ this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
+
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ switch (MessageHeader->MessageType)
+ {
+ case REMOTE_NDIS_INITIALIZE_MSG:
+ RNDISInterfaceInfo->ResponseReady = true;
+
+ RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
+ INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);
+ INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
+ INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
+
+ INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
+ INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
+ INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
+ INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
+ INITIALIZE_Response->MaxPacketsPerTransfer = 1;
+ INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);
+ INITIALIZE_Response->PacketAlignmentFactor = 0;
+ INITIALIZE_Response->AFListOffset = 0;
+ INITIALIZE_Response->AFListSize = 0;
+
+ RNDISInterfaceInfo->CurrRNDISState = RNDIS_Initialized;
+
+ break;
+ case REMOTE_NDIS_HALT_MSG:
+ RNDISInterfaceInfo->ResponseReady = false;
+ MessageHeader->MessageLength = 0;
+
+ RNDISInterfaceInfo->CurrRNDISState = RNDIS_Uninitialized;
+
+ break;
+ case REMOTE_NDIS_QUERY_MSG:
+ RNDISInterfaceInfo->ResponseReady = true;
+
+ RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ uint32_t Query_Oid = QUERY_Message->Oid;
+
+ void* QueryData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ QUERY_Message->InformationBufferOffset];
+ void* ResponseData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)];
+ uint16_t ResponseSize;
+
+ QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
+ QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);
+
+ if (USB_RNDIS_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
+ ResponseData, &ResponseSize))
+ {
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
+ QUERY_Response->MessageLength += ResponseSize;
+
+ QUERY_Response->InformationBufferLength = ResponseSize;
+ QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));
+ }
+ else
+ {
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
+
+ QUERY_Response->InformationBufferLength = 0;
+ QUERY_Response->InformationBufferOffset = 0;
+ }
+
+ break;
+ case REMOTE_NDIS_SET_MSG:
+ RNDISInterfaceInfo->ResponseReady = true;
+
+ RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ uint32_t SET_Oid = SET_Message->Oid;
+
+ SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
+ SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);
+ SET_Response->RequestId = SET_Message->RequestId;
+
+ void* SetData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ SET_Message->InformationBufferOffset];
+
+ if (USB_RNDIS_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, SET_Message->InformationBufferLength))
+ SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
+ else
+ SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ case REMOTE_NDIS_RESET_MSG:
+ RNDISInterfaceInfo->ResponseReady = true;
+
+ RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
+ RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);
+ RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
+ RESET_Response->AddressingReset = 0;
+
+ break;
+ case REMOTE_NDIS_KEEPALIVE_MSG:
+ RNDISInterfaceInfo->ResponseReady = true;
+
+ RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+ RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
+
+ KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
+ KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);
+ KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
+ KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
+
+ break;
+ }
+}
+
+static bool USB_RNDIS_ProcessNDISQuery(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo,
+ uint32_t OId, void* QueryData, uint16_t QuerySize,
+ void* ResponseData, uint16_t* ResponseSize)
+{
+ switch (OId)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+ *ResponseSize = sizeof(AdapterSupportedOIDList);
+
+ memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
+
+ return true;
+ case OID_GEN_PHYSICAL_MEDIUM:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate that the device is a true ethernet link */
+ *((uint32_t*)ResponseData) = 0;
+
+ return true;
+ case OID_GEN_HARDWARE_STATUS:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = NdisHardwareStatusReady;
+
+ return true;
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
+
+ return true;
+ case OID_GEN_VENDOR_ID:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
+ *((uint32_t*)ResponseData) = 0x00FFFFFF;
+
+ return true;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
+
+ return true;
+ case OID_GEN_VENDOR_DESCRIPTION:
+ *ResponseSize = (strlen(RNDISInterfaceInfo->AdapterVendorDescription) + 1);
+
+ memcpy(ResponseData, RNDISInterfaceInfo->AdapterVendorDescription, *ResponseSize);
+
+ return true;
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
+
+ return true;
+ case OID_GEN_LINK_SPEED:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate 10Mb/s link speed */
+ *((uint32_t*)ResponseData) = 100000;
+
+ return true;
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ *ResponseSize = sizeof(MAC_Address_t);
+
+ memcpy(ResponseData, &RNDISInterfaceInfo->AdapterMACAddress, sizeof(MAC_Address_t));
+
+ return true;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate only one multicast address supported */
+ *((uint32_t*)ResponseData) = 1;
+
+ return true;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = RNDISInterfaceInfo->CurrPacketFilter;
+
+ return true;
+ case OID_GEN_XMIT_OK:
+ case OID_GEN_RCV_OK:
+ case OID_GEN_XMIT_ERROR:
+ case OID_GEN_RCV_ERROR:
+ case OID_GEN_RCV_NO_BUFFER:
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Unused statistic OIDs - always return 0 for each */
+ *((uint32_t*)ResponseData) = 0;
+
+ return true;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
+ *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
+
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool USB_RNDIS_ProcessNDISSet(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, uint32_t OId, void* SetData, uint16_t SetSize)
+{
+ switch (OId)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ RNDISInterfaceInfo->CurrPacketFilter = *((uint32_t*)SetData);
+ RNDISInterfaceInfo->CurrRNDISState = ((RNDISInterfaceInfo->CurrPacketFilter) ?
+ RNDIS_Data_Initialized : RNDIS_Data_Initialized);
+
+ return true;
+ case OID_802_3_MULTICAST_LIST:
+ /* Do nothing - throw away the value from the host as it is unused */
+
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.h b/LUFA/Drivers/USB/Class/Device/RNDIS.h new file mode 100644 index 000000000..73622a4dc --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDIS.h @@ -0,0 +1,260 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _RNDIS_CLASS_H_
+#define _RNDIS_CLASS_H_
+
+ /* Includes: */
+ #include <string.h>
+
+ #include "../../USB.h"
+ #include "RNDISConstants.h"
+
+ /* Macros: */
+ /** Implemented RNDIS Version Major */
+ #define REMOTE_NDIS_VERSION_MAJOR 0x01
+
+ /** Implemented RNDIS Version Minor */
+ #define REMOTE_NDIS_VERSION_MINOR 0x00
+
+ /** RNDIS request to issue a host-to-device NDIS command */
+ #define REQ_SendEncapsulatedCommand 0x00
+
+ /** RNDIS request to issue a device-to-host NDIS response */
+ #define REQ_GetEncapsulatedResponse 0x01
+
+ #define RNDIS_MESSAGE_BUFFER_SIZE 128
+
+ #define ETHERNET_FRAME_SIZE_MAX 1500
+
+ #define NOTIF_ResponseAvailable 1
+
+ /* Enums: */
+ /** Enum for the possible NDIS adapter states. */
+ enum RNDIS_States_t
+ {
+ RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */
+ RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */
+ RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */
+ };
+
+ /** Enum for the NDIS hardware states */
+ enum NDIS_Hardware_Status_t
+ {
+ NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */
+ NdisHardwareStatusInitializing, /**< Hardware busy initializing */
+ NdisHardwareStatusReset, /**< Hardware reset */
+ NdisHardwareStatusClosing, /**< Hardware currently closing */
+ NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */
+ };
+
+ /* Type Defines: */
+ /** Type define for a physical MAC address of a device on a network */
+ typedef struct
+ {
+ uint8_t Octets[6]; /**< Individual bytes of a MAC address */
+ } MAC_Address_t;
+
+ /** Type define for a RNDIS message header, sent before RNDIS messages */
+ typedef struct
+ {
+ uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */
+ uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */
+ } RNDIS_Message_Header_t;
+
+ /** Type define for an Ethernet frame buffer. */
+ typedef struct
+ {
+ uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */
+ uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */
+ bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */
+ } Ethernet_Frame_Info_t;
+
+ /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t DataOffset;
+ uint32_t DataLength;
+ uint32_t OOBDataOffset;
+ uint32_t OOBDataLength;
+ uint32_t NumOOBDataElements;
+ uint32_t PerPacketInfoOffset;
+ uint32_t PerPacketInfoLength;
+ uint32_t VcHandle;
+ uint32_t Reserved;
+ } RNDIS_PACKET_MSG_t;
+
+ typedef struct
+ {
+ uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
+
+ uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
+ uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
+
+ uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
+ uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
+
+ uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
+ uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
+
+ char* AdapterVendorDescription;
+ MAC_Address_t AdapterMACAddress;
+
+ uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE];
+ bool ResponseReady;
+ uint8_t CurrRNDISState;
+ uint32_t CurrPacketFilter;
+ Ethernet_Frame_Info_t FrameIN;
+ Ethernet_Frame_Info_t FrameOUT;
+ } USB_ClassInfo_RNDIS_t;
+
+ /** Type define for a RNDIS Initialize command message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t MajorVersion;
+ uint32_t MinorVersion;
+ uint32_t MaxTransferSize;
+ } RNDIS_INITIALIZE_MSG_t;
+
+ /** Type define for a RNDIS Initialize complete response message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+
+ uint32_t MajorVersion;
+ uint32_t MinorVersion;
+ uint32_t DeviceFlags;
+ uint32_t Medium;
+ uint32_t MaxPacketsPerTransfer;
+ uint32_t MaxTransferSize;
+ uint32_t PacketAlignmentFactor;
+ uint32_t AFListOffset;
+ uint32_t AFListSize;
+ } RNDIS_INITIALIZE_CMPLT_t;
+
+ /** Type define for a RNDIS Keepalive command message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ } RNDIS_KEEPALIVE_MSG_t;
+
+ /** Type define for a RNDIS Keepalive complete message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+ } RNDIS_KEEPALIVE_CMPLT_t;
+
+ /** Type define for a RNDIS Reset complete message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t Status;
+
+ uint32_t AddressingReset;
+ } RNDIS_RESET_CMPLT_t;
+
+ /** Type define for a RNDIS Set command message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t Oid;
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ uint32_t DeviceVcHandle;
+ } RNDIS_SET_MSG_t;
+
+ /** Type define for a RNDIS Set complete response message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+ } RNDIS_SET_CMPLT_t;
+
+ /** Type define for a RNDIS Query command message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t Oid;
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ uint32_t DeviceVcHandle;
+ } RNDIS_QUERY_MSG_t;
+
+ /** Type define for a RNDIS Query complete response message */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ } RNDIS_QUERY_CMPLT_t;
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_RNDIS_CLASS_C)
+ static void USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
+ static bool USB_RNDIS_ProcessNDISQuery(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo,
+ uint32_t OId, void* QueryData, uint16_t QuerySize,
+ void* ResponseData, uint16_t* ResponseSize);
+ static bool USB_RNDIS_ProcessNDISSet(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, uint32_t OId,
+ void* SetData, uint16_t SetSize);
+ #endif
+
+ void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
+ bool USB_RNDIS_ConfigureEndpoints(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
+ void USB_RNDIS_ProcessControlPacket(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
+ void USB_RNDIS_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/Device/RNDISConstants.h b/LUFA/Drivers/USB/Class/Device/RNDISConstants.h new file mode 100644 index 000000000..ad66f62db --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDISConstants.h @@ -0,0 +1,99 @@ +/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * RNDIS specification related constants. For more information on these
+ * constants, please refer to the Microsoft RNDIS specification.
+ */
+
+#ifndef _RNDIS_CONSTANTS_H_
+#define _RNDIS_CONSTANTS_H_
+
+ /* Macros: */
+ #define REMOTE_NDIS_PACKET_MSG 0x00000001UL
+ #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL
+ #define REMOTE_NDIS_HALT_MSG 0x00000003UL
+ #define REMOTE_NDIS_QUERY_MSG 0x00000004UL
+ #define REMOTE_NDIS_SET_MSG 0x00000005UL
+ #define REMOTE_NDIS_RESET_MSG 0x00000006UL
+ #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL
+ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL
+
+ #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL
+ #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL
+ #define REMOTE_NDIS_SET_CMPLT 0x80000005UL
+ #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL
+ #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL
+
+ #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL
+ #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL
+ #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL
+ #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL
+ #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL
+ #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL
+
+ #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL
+ #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL
+
+ #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL
+
+ #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL
+ #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL
+
+ #define OID_GEN_SUPPORTED_LIST 0x00010101UL
+ #define OID_GEN_HARDWARE_STATUS 0x00010102UL
+ #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL
+ #define OID_GEN_MEDIA_IN_USE 0x00010104UL
+ #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
+ #define OID_GEN_LINK_SPEED 0x00010107UL
+ #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL
+ #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL
+ #define OID_GEN_VENDOR_ID 0x0001010CUL
+ #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL
+ #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
+ #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
+ #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL
+ #define OID_GEN_XMIT_OK 0x00020101UL
+ #define OID_GEN_RCV_OK 0x00020102UL
+ #define OID_GEN_XMIT_ERROR 0x00020103UL
+ #define OID_GEN_RCV_ERROR 0x00020104UL
+ #define OID_GEN_RCV_NO_BUFFER 0x00020105UL
+ #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL
+ #define OID_802_3_CURRENT_ADDRESS 0x01010102UL
+ #define OID_802_3_MULTICAST_LIST 0x01010103UL
+ #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL
+ #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL
+ #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL
+ #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/HIDParser.c b/LUFA/Drivers/USB/Class/Host/HIDParser.c index 5fb29aa0a..5fb29aa0a 100644 --- a/LUFA/Drivers/USB/Class/HIDParser.c +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.c diff --git a/LUFA/Drivers/USB/Class/HIDParser.h b/LUFA/Drivers/USB/Class/Host/HIDParser.h index 49e57c295..4acce2462 100644 --- a/LUFA/Drivers/USB/Class/HIDParser.h +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.h @@ -63,7 +63,7 @@ #include "HIDReportData.h"
- #include "../../../Common/Common.h"
+ #include "../../../../Common/Common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
diff --git a/LUFA/Drivers/USB/Class/HIDReportData.h b/LUFA/Drivers/USB/Class/Host/HIDReportData.h index eee38be04..eee38be04 100644 --- a/LUFA/Drivers/USB/Class/HIDReportData.h +++ b/LUFA/Drivers/USB/Class/Host/HIDReportData.h diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h index e6d2beaa7..ded027b12 100644 --- a/LUFA/Drivers/USB/HighLevel/Events.h +++ b/LUFA/Drivers/USB/HighLevel/Events.h @@ -267,6 +267,11 @@ * \ref Group_USBManagement documentation).
*/
void EVENT_USB_Reset(void);
+
+ /** Event for the USB start of frame interrupt, firing once each millisecond in either device or host
+ * mode, while USB frames are being generated or recieved.
+ */
+ void EVENT_USB_StartOfFrame(void);
#endif
/* Private Interface - For use in library only: */
@@ -303,6 +308,7 @@ void EVENT_USB_Suspend(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_WakeUp(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Reset(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
#endif
#endif
diff --git a/LUFA/Drivers/USB/HighLevel/USBInterrupt.c b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c index 0b9d08223..0ccbe6155 100644 --- a/LUFA/Drivers/USB/HighLevel/USBInterrupt.c +++ b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c @@ -180,6 +180,15 @@ ISR(USB_GEN_vect, ISR_BLOCK) EVENT_USB_Reset();
}
+
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ FrameElapsed = true;
+
+ EVENT_USB_StartOfFrame();
+ }
#endif
#if defined(USB_CAN_BE_HOST)
@@ -232,6 +241,15 @@ ISR(USB_GEN_vect, ISR_BLOCK) USB_ResetInterface();
}
+
+ if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ FrameElapsed = true;
+
+ EVENT_USB_StartOfFrame();
+ }
#endif
#if defined(USB_CAN_BE_BOTH)
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.c b/LUFA/Drivers/USB/HighLevel/USBTask.c index e2b7e91d5..46fcd5709 100644 --- a/LUFA/Drivers/USB/HighLevel/USBTask.c +++ b/LUFA/Drivers/USB/HighLevel/USBTask.c @@ -42,7 +42,7 @@ USB_Request_Header_t USB_ControlRequest; volatile uint8_t USB_HostState;
#endif
-TASK(USB_USBTask)
+void USB_USBTask(void)
{
#if defined(USB_HOST_ONLY)
USB_HostTask();
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.h b/LUFA/Drivers/USB/HighLevel/USBTask.h index 1e1209a5f..e4c8a02ae 100644 --- a/LUFA/Drivers/USB/HighLevel/USBTask.h +++ b/LUFA/Drivers/USB/HighLevel/USBTask.h @@ -38,7 +38,6 @@ #include <stdbool.h>
#include <stddef.h>
- #include "../../../Scheduler/Scheduler.h"
#include "../LowLevel/LowLevel.h"
#include "StdRequestType.h"
#include "USBMode.h"
@@ -122,11 +121,11 @@ extern volatile uint8_t USB_HostState;
#endif
- /* Tasks: */
+ /* Function Prototypes: */
/** This is the main USB management task. The USB driver requires that this task be executed
* continuously when the USB system is active (device attached in host mode, or attached to a host
* in device mode) in order to manage USB communications. This task may be executed inside an RTOS,
- * scheduler (e.g. the simple LUFA Scheduler), fast timer ISR or the main user application loop.
+ * fast timer ISR or the main user application loop.
*
* The USB task must be serviced within 30ms while in device mode, or within 1ms while in host mode.
* The task may be serviced at all times, or (for minimum CPU consumption):
@@ -145,7 +144,7 @@ *
* \ingroup Group_USBManagement
*/
- TASK(USB_USBTask);
+ void USB_USBTask(void);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c index 099022c1c..d02071bbd 100644 --- a/LUFA/Drivers/USB/LowLevel/Endpoint.c +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c @@ -80,8 +80,6 @@ uint8_t Endpoint_WaitUntilReady(void) uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#endif
- USB_INT_Clear(USB_INT_SOFI);
-
for (;;)
{
if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
@@ -100,9 +98,9 @@ uint8_t Endpoint_WaitUntilReady(void) else if (Endpoint_IsStalled())
return ENDPOINT_READYWAIT_EndpointStalled;
- if (USB_INT_HasOccurred(USB_INT_SOFI))
+ if (FrameElapsed)
{
- USB_INT_Clear(USB_INT_SOFI);
+ FrameElapsed = false;
if (!(TimeoutMSRem--))
return ENDPOINT_READYWAIT_Timeout;
diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c index b606515e6..02a1c2171 100644 --- a/LUFA/Drivers/USB/LowLevel/Host.c +++ b/LUFA/Drivers/USB/LowLevel/Host.c @@ -210,14 +210,13 @@ uint8_t USB_Host_WaitMS(uint8_t MS) bool BusSuspended = USB_Host_IsBusSuspended();
uint8_t ErrorCode = HOST_WAITERROR_Successful;
- USB_INT_Clear(USB_INT_HSOFI);
USB_Host_ResumeBus();
while (MS)
{
- if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ if (FrameElapsed)
{
- USB_INT_Clear(USB_INT_HSOFI);
+ FrameElapsed = false;
MS--;
}
@@ -260,9 +259,10 @@ static void USB_Host_ResetDevice(void) USB_Host_ResetBus();
while (!(USB_Host_IsBusResetComplete()));
- USB_INT_Clear(USB_INT_HSOFI);
USB_Host_ResumeBus();
+ FrameElapsed = false;
+
for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
{
/* Workaround for powerless-pull-up devices. After a USB bus reset,
@@ -270,8 +270,10 @@ static void USB_Host_ResetDevice(void) looked for - if it is found within 10ms, the device is still
present. */
- if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ if (FrameElapsed)
{
+ FrameElapsed = false;
+
USB_INT_Clear(USB_INT_DDISCI);
break;
}
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.c b/LUFA/Drivers/USB/LowLevel/LowLevel.c index 8b395be98..255a6ef29 100644 --- a/LUFA/Drivers/USB/LowLevel/LowLevel.c +++ b/LUFA/Drivers/USB/LowLevel/LowLevel.c @@ -38,6 +38,8 @@ volatile uint8_t USB_CurrentMode = USB_MODE_NONE; volatile uint8_t USB_Options;
#endif
+volatile bool FrameElapsed;
+
void USB_Init(
#if defined(USB_CAN_BE_BOTH)
const uint8_t Mode
@@ -150,6 +152,8 @@ void USB_ResetInterface(void) USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
+ FrameElapsed = false;
+
USB_IsConnected = false;
#if defined(USB_CAN_BE_HOST)
@@ -224,6 +228,7 @@ void USB_ResetInterface(void) #if defined(USB_DEVICE_ONLY)
USB_INT_Enable(USB_INT_SUSPEND);
USB_INT_Enable(USB_INT_EORSTI);
+ USB_INT_Enable(USB_INT_SOFI);
#if defined(CONTROL_ONLY_DEVICE)
UENUM = ENDPOINT_CONTROLEP;
@@ -240,11 +245,13 @@ void USB_ResetInterface(void) USB_INT_Enable(USB_INT_SRPI);
USB_INT_Enable(USB_INT_BCERRI);
+ USB_INT_Enable(USB_INT_HSOFI);
#else
if (USB_CurrentMode == USB_MODE_DEVICE)
{
USB_INT_Enable(USB_INT_SUSPEND);
USB_INT_Enable(USB_INT_EORSTI);
+ USB_INT_Enable(USB_INT_SOFI);
#if defined(CONTROL_ONLY_DEVICE)
UENUM = ENDPOINT_CONTROLEP;
@@ -262,6 +269,7 @@ void USB_ResetInterface(void) USB_INT_Enable(USB_INT_SRPI);
USB_INT_Enable(USB_INT_BCERRI);
+ USB_INT_Enable(USB_INT_HSOFI);
}
#endif
}
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.h b/LUFA/Drivers/USB/LowLevel/LowLevel.h index 41b0ff5f6..4279ca315 100644 --- a/LUFA/Drivers/USB/LowLevel/LowLevel.h +++ b/LUFA/Drivers/USB/LowLevel/LowLevel.h @@ -350,6 +350,9 @@ return USB_MODE_HOST;
}
#endif
+
+ /* External Variables: */
+ extern volatile bool FrameElapsed;
#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c index 71a33d62f..720da1772 100644 --- a/LUFA/Drivers/USB/LowLevel/Pipe.c +++ b/LUFA/Drivers/USB/LowLevel/Pipe.c @@ -76,8 +76,6 @@ uint8_t Pipe_WaitUntilReady(void) uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#endif
- USB_INT_Clear(USB_INT_HSOFI);
-
for (;;)
{
if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
@@ -96,9 +94,9 @@ uint8_t Pipe_WaitUntilReady(void) else if (!(USB_IsConnected))
return PIPE_READYWAIT_DeviceDisconnected;
- if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ if (FrameElapsed)
{
- USB_INT_Clear(USB_INT_HSOFI);
+ FrameElapsed = false;
if (!(TimeoutMSRem--))
return PIPE_READYWAIT_Timeout;
diff --git a/LUFA/Drivers/USB/USB.h b/LUFA/Drivers/USB/USB.h index 6d66c4d14..3c8f06237 100644 --- a/LUFA/Drivers/USB/USB.h +++ b/LUFA/Drivers/USB/USB.h @@ -49,7 +49,6 @@ * - LUFA/Drivers/USB/HighLevel/USBInterrupt.c
* - LUFA/Drivers/USB/HighLevel/USBTask.c
* - LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c
- * - LUFA/Drivers/USB/Class/HIDParser.c
*
* \section Module Description
* Functions, macros, variables, enums and types related to the management of USB communications.
@@ -97,7 +96,6 @@ #endif
#include "HighLevel/ConfigDescriptor.h"
- #include "Class/HIDParser.h"
#endif
|