Commit of new class abstraction APIs for all device demos other than the MIDI demo - not documented yet.
Removed scheduler and memory allocation libraries. Added new EVENT_USB_StartOfFrame event in the library to indicate the start of each USB frame (when generated). Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt.
This commit is contained in:
parent
2440ca268a
commit
d1e5266036
106 changed files with 3072 additions and 5760 deletions
|
|
@ -4,6 +4,14 @@
|
|||
* documentation pages. It is not a project source file.
|
||||
*/
|
||||
|
||||
========== TODO: ===========
|
||||
- Document new class drivers
|
||||
- Re-document all demos now that they have changed
|
||||
- Add standardized descriptor names to class driver structures, controlled by USE_NONSTANDARD_DESCRIPTOR_NAMES
|
||||
- Add C++ compatibility to class drivers
|
||||
- Disable JTAG in demos
|
||||
============================
|
||||
|
||||
/** \page Page_ChangeLog Project Changelog
|
||||
*
|
||||
* \section Sec_ChangeLogXXXXXX Version XXXXXX
|
||||
|
|
@ -30,6 +38,8 @@
|
|||
* LUFA/Drivers/USB/Class/ directory to LUFA/Drivers/USB/HighLevel/ in preperation for the new USB class APIs
|
||||
* - Moved out each demos' functionality library files (e.g. Ring Buffer library) to /Lib directories for a better directory structure
|
||||
* - Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt
|
||||
* - Added new EVENT_USB_StartOfFrame event in the library to indicate the start of each USB frame (when generated)
|
||||
* - Removed psuedo-scheduler, dynamic memory block allocator from the library (no longer needed and not used respectively)
|
||||
*
|
||||
*
|
||||
* \section Sec_ChangeLog090510 Version 090510
|
||||
|
|
|
|||
|
|
@ -10,19 +10,6 @@
|
|||
* This folder contains header files which are common to all parts of the LUFA library. They may be used freely in
|
||||
* user applications.
|
||||
*
|
||||
* \dir MemoryAllocator
|
||||
* \brief Auto-defragmenting dynamic memory allocation library.
|
||||
*
|
||||
* This folder contains a simple handle-based dynamic memory allocation library, capable of handing out memory in
|
||||
* block chunks. As new memory is allocated, the library will defragment the already allocated memory to ensure
|
||||
* optimal memory usage. It is not used within the LUFA library, and is provided as a convenience for user applications.
|
||||
*
|
||||
* \dir Scheduler
|
||||
* \brief Simple round-robbin scheduler.
|
||||
*
|
||||
* This folder contains the simple LUFA round-robbin scheduler, provided as a convenience for user applications. It
|
||||
* is very simple in design, and is intended to make code easier to read, rather than providing a complete RTOS kernel.
|
||||
*
|
||||
* \dir Drivers
|
||||
* \brief Library hardware and software drivers.
|
||||
*
|
||||
|
|
|
|||
154
LUFA/Drivers/USB/Class/Device/Audio.c
Normal file
154
LUFA/Drivers/USB/Class/Device/Audio.c
Normal file
|
|
@ -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();
|
||||
}
|
||||
70
LUFA/Drivers/USB/Class/Device/Audio.h
Normal file
70
LUFA/Drivers/USB/Class/Device/Audio.h
Normal file
|
|
@ -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
|
||||
185
LUFA/Drivers/USB/Class/Device/CDC.c
Normal file
185
LUFA/Drivers/USB/Class/Device/CDC.c
Normal file
|
|
@ -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();
|
||||
}
|
||||
188
LUFA/Drivers/USB/Class/Device/CDC.h
Normal file
188
LUFA/Drivers/USB/Class/Device/CDC.h
Normal file
|
|
@ -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
|
||||
211
LUFA/Drivers/USB/Class/Device/HID.c
Normal file
211
LUFA/Drivers/USB/Class/Device/HID.c
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
115
LUFA/Drivers/USB/Class/Device/HID.h
Normal file
115
LUFA/Drivers/USB/Class/Device/HID.h
Normal file
|
|
@ -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
|
||||
208
LUFA/Drivers/USB/Class/Device/MassStorage.c
Normal file
208
LUFA/Drivers/USB/Class/Device/MassStorage.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
127
LUFA/Drivers/USB/Class/Device/MassStorage.h
Normal file
127
LUFA/Drivers/USB/Class/Device/MassStorage.h
Normal file
|
|
@ -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
|
||||
456
LUFA/Drivers/USB/Class/Device/RNDIS.c
Normal file
456
LUFA/Drivers/USB/Class/Device/RNDIS.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
260
LUFA/Drivers/USB/Class/Device/RNDIS.h
Normal file
260
LUFA/Drivers/USB/Class/Device/RNDIS.h
Normal file
|
|
@ -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
|
||||
99
LUFA/Drivers/USB/Class/Device/RNDISConstants.h
Normal file
99
LUFA/Drivers/USB/Class/Device/RNDISConstants.h
Normal file
|
|
@ -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
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
#include "HIDReportData.h"
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
#include "../../../../Common/Common.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -350,6 +350,9 @@
|
|||
return USB_MODE_HOST;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* External Variables: */
|
||||
extern volatile bool FrameElapsed;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
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_DYNALLOC_C
|
||||
#include "DynAlloc.h"
|
||||
|
||||
struct
|
||||
{
|
||||
char Mem_Heap[NUM_BLOCKS * BLOCK_SIZE];
|
||||
void* Mem_Handles[NUM_HANDLES];
|
||||
uint8_t Mem_Block_Flags[(NUM_BLOCKS / 4) + ((NUM_BLOCKS % 4) ? 1 : 0)];
|
||||
uint8_t FlagMaskLookupMask[4];
|
||||
uint8_t FlagMaskLookupNum[4];
|
||||
} Mem_MemData = {.FlagMaskLookupMask = {(3 << 0), (3 << 2), (3 << 4), (3 << 6)},
|
||||
.FlagMaskLookupNum = { 0, 2, 4, 6}};
|
||||
|
||||
static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum)
|
||||
{
|
||||
const Block_Number_t BlockIndex = (BlockNum >> 2);
|
||||
const uint8_t FlagMask = Mem_MemData.FlagMaskLookupMask[BlockNum & 0x03];
|
||||
const uint8_t FlagMaskShift = Mem_MemData.FlagMaskLookupNum[BlockNum & 0x03];
|
||||
|
||||
return ((Mem_MemData.Mem_Block_Flags[BlockIndex] & FlagMask) >> FlagMaskShift);
|
||||
}
|
||||
|
||||
static void Mem_SetBlockFlags(const Block_Number_t BlockNum, const uint8_t Flags)
|
||||
{
|
||||
const Block_Number_t BlockIndex = (BlockNum >> 2);
|
||||
const uint8_t FlagMask = Mem_MemData.FlagMaskLookupMask[BlockNum & 0x03];
|
||||
const uint8_t FlagMaskShift = Mem_MemData.FlagMaskLookupNum[BlockNum & 0x03];
|
||||
|
||||
Mem_MemData.Mem_Block_Flags[BlockIndex] &= ~FlagMask;
|
||||
Mem_MemData.Mem_Block_Flags[BlockIndex] |= (Flags << FlagMaskShift);
|
||||
}
|
||||
|
||||
static inline void Mem_Defrag(void)
|
||||
{
|
||||
Block_Number_t FreeStartBlock = 0;
|
||||
char* FreeStartPtr = NULL;
|
||||
char* UsedStartPtr = NULL;
|
||||
Block_Number_t CurrBlock;
|
||||
|
||||
for (CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)
|
||||
{
|
||||
if (!(Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK))
|
||||
{
|
||||
FreeStartPtr = &Mem_MemData.Mem_Heap[CurrBlock * BLOCK_SIZE];
|
||||
FreeStartBlock = CurrBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FreeStartPtr == NULL)
|
||||
return;
|
||||
|
||||
while (++CurrBlock < NUM_BLOCKS)
|
||||
{
|
||||
uint8_t CurrBlockFlags = Mem_GetBlockFlags(CurrBlock);
|
||||
|
||||
if (CurrBlockFlags & BLOCK_USED_MASK)
|
||||
{
|
||||
UsedStartPtr = &Mem_MemData.Mem_Heap[CurrBlock * BLOCK_SIZE];
|
||||
|
||||
for (Handle_Number_t HandleNum = 0; HandleNum < NUM_HANDLES; HandleNum++)
|
||||
{
|
||||
if (Mem_MemData.Mem_Handles[HandleNum] == UsedStartPtr)
|
||||
{
|
||||
Mem_MemData.Mem_Handles[HandleNum] = FreeStartPtr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(FreeStartPtr, UsedStartPtr, BLOCK_SIZE);
|
||||
FreeStartPtr += BLOCK_SIZE;
|
||||
|
||||
Mem_SetBlockFlags(FreeStartBlock++, CurrBlockFlags);
|
||||
Mem_SetBlockFlags(CurrBlock, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool Mem_FindFreeBlocks(Block_Number_t* const RetStartPtr, const Block_Number_t Blocks)
|
||||
{
|
||||
Block_Number_t FreeInCurrSec = 0;
|
||||
|
||||
for (Block_Number_t CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)
|
||||
{
|
||||
if (Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK)
|
||||
FreeInCurrSec = 0;
|
||||
else
|
||||
FreeInCurrSec++;
|
||||
|
||||
if (FreeInCurrSec >= Blocks)
|
||||
{
|
||||
*RetStartPtr = CurrBlock;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Mem_Handle_t Mem_Alloc(const Alloc_Size_t Bytes)
|
||||
{
|
||||
Block_Number_t ReqBlocks = (Bytes / BLOCK_SIZE);
|
||||
Block_Number_t StartBlock;
|
||||
|
||||
if (Bytes % BLOCK_SIZE)
|
||||
ReqBlocks++;
|
||||
|
||||
if (!(Mem_FindFreeBlocks(&StartBlock, ReqBlocks)))
|
||||
{
|
||||
Mem_Defrag();
|
||||
|
||||
if (!(Mem_FindFreeBlocks(&StartBlock, ReqBlocks)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (Block_Number_t UsedBlock = 0; UsedBlock < (ReqBlocks - 1); UsedBlock++)
|
||||
Mem_SetBlockFlags((StartBlock + UsedBlock), (BLOCK_USED_MASK | BLOCK_LINKED_MASK));
|
||||
|
||||
Mem_SetBlockFlags((StartBlock + (ReqBlocks - 1)), BLOCK_USED_MASK);
|
||||
|
||||
for (Handle_Number_t AllocEntry = 0; AllocEntry < NUM_HANDLES; AllocEntry++)
|
||||
{
|
||||
Mem_Handle_t CurrHdl = (Mem_Handle_t)&Mem_MemData.Mem_Handles[AllocEntry];
|
||||
|
||||
if (DEREF(CurrHdl, void*) == NULL)
|
||||
{
|
||||
DEREF(CurrHdl, void*) = &Mem_MemData.Mem_Heap[StartBlock * BLOCK_SIZE];
|
||||
return CurrHdl;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Mem_Handle_t Mem_Realloc(Mem_Handle_t CurrAllocHdl, const Alloc_Size_t Bytes)
|
||||
{
|
||||
Mem_Free(CurrAllocHdl);
|
||||
return Mem_Alloc(Bytes);
|
||||
}
|
||||
|
||||
Mem_Handle_t Mem_Calloc(const Alloc_Size_t Bytes)
|
||||
{
|
||||
Mem_Handle_t AllocHdl = Mem_Alloc(Bytes);
|
||||
|
||||
if (AllocHdl != NULL)
|
||||
memset(DEREF(AllocHdl, void*), 0x00, Bytes);
|
||||
|
||||
return AllocHdl;
|
||||
}
|
||||
|
||||
void Mem_Free(Mem_Handle_t CurrAllocHdl)
|
||||
{
|
||||
char* MemBlockPtr = DEREF(CurrAllocHdl, char*);
|
||||
Block_Number_t CurrBlock = ((uint16_t)(MemBlockPtr - Mem_MemData.Mem_Heap) / BLOCK_SIZE);
|
||||
uint8_t CurrBlockFlags;
|
||||
|
||||
if ((CurrAllocHdl == NULL) || (MemBlockPtr == NULL))
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
CurrBlockFlags = Mem_GetBlockFlags(CurrBlock);
|
||||
Mem_SetBlockFlags(CurrBlock, 0);
|
||||
|
||||
CurrBlock++;
|
||||
}
|
||||
while (CurrBlockFlags & BLOCK_LINKED_MASK);
|
||||
|
||||
DEREF(CurrAllocHdl, void*) = NULL;
|
||||
}
|
||||
|
||||
Block_Number_t Mem_TotalFreeBlocks(void)
|
||||
{
|
||||
Block_Number_t FreeBlocks = 0;
|
||||
|
||||
for (Block_Number_t CurrBlock = 0; CurrBlock < NUM_BLOCKS; CurrBlock++)
|
||||
{
|
||||
if (!(Mem_GetBlockFlags(CurrBlock) & BLOCK_USED_MASK))
|
||||
FreeBlocks++;
|
||||
}
|
||||
|
||||
return FreeBlocks;
|
||||
}
|
||||
|
||||
Handle_Number_t Mem_TotalFreeHandles(void)
|
||||
{
|
||||
Handle_Number_t FreeHandles = 0;
|
||||
|
||||
for (Handle_Number_t CurrHandle = 0; CurrHandle < NUM_HANDLES; CurrHandle++)
|
||||
{
|
||||
if (Mem_MemData.Mem_Handles[CurrHandle] == NULL)
|
||||
FreeHandles++;
|
||||
}
|
||||
|
||||
return FreeHandles;
|
||||
}
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
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
|
||||
*
|
||||
* Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for
|
||||
* the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the
|
||||
* management memory overhead.
|
||||
*/
|
||||
|
||||
/** @defgroup Group_MemoryAllocator Dynamic Block Memory Allocator - LUFA/MemoryAllocator/DynAlloc.h
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/MemoryAllocator/DynAlloc.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for
|
||||
* the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the
|
||||
* management memory overhead.
|
||||
*
|
||||
* Unlike the normal memory allocation routines, this library gives out handles to memory which must be dereferenced
|
||||
* at the exact time of use, rather than handing back direct memory pointers. By using library managed handles
|
||||
* instead of pointers, allocated memory blocks can be shifted around as needed transparently to defragment the
|
||||
* memory as more blocks are requested.
|
||||
*
|
||||
* The memory heap is static, thus the total memory usage of the compiled application (as reported by the avr-size
|
||||
* tool of the AVR-GCC toolchain) includes the dynamic memory heap.
|
||||
*
|
||||
* The constants NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined in the project makefile (and passed to the
|
||||
* preprocessor via the -D GCC switch) for this library to compile.
|
||||
*
|
||||
* NUM_BLOCKS indicates the number of memory blocks in the memory psudoheap which can be chained together and handed
|
||||
* to the application via a memory handle. NUM_HANDLES is the maximum number of memory handles (pointing to one or
|
||||
* more chained memory blocks) which can be handed out simultaneously before requiring a handle (and its associated
|
||||
* memory) to be freed. BLOCK_SIZE gives the number of bytes in each memory block.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __DYN_ALLOC__
|
||||
#define __DYN_ALLOC__
|
||||
|
||||
/* Includes : */
|
||||
#include <avr/io.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if (!defined(NUM_BLOCKS) || !defined(BLOCK_SIZE) || !defined(NUM_HANDLES))
|
||||
#error NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined before use via makefile.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Macro to dereference a given memory handle into the given type. The given type should be a pointer
|
||||
* if the memory is to contain an array of items, or should be a standard type (such as a primitive or
|
||||
* structure) if the memory is to hold a single item of a single type. */
|
||||
#define DEREF(handle, type) (*(type*)handle)
|
||||
|
||||
/** Constant, giving the total heap size in bytes. */
|
||||
#define ALLOCABLE_BYTES (1UL * NUM_BLOCKS * BLOCK_SIZE)
|
||||
|
||||
/* Type Defines: */
|
||||
/** Memory handle type, used to store handles given by the library functions. */
|
||||
typedef const void** Mem_Handle_t;
|
||||
|
||||
#if (ALLOCABLE_BYTES > 0xFFFF) || defined(__DOXYGEN__)
|
||||
/** Type define for the size (in bytes) for an allocation for passing to the library functions.
|
||||
* The exact type width varies depending on the value of ALLOCABLE_BYTES to ensure that a single
|
||||
* allocation can request the entire heap if needed.
|
||||
*/
|
||||
typedef uint32_t Alloc_Size_t;
|
||||
#elif (ALLOCABLE_BYTES > 0xFF)
|
||||
typedef uint16_t Alloc_Size_t;
|
||||
#else
|
||||
typedef uint8_t Alloc_Size_t;
|
||||
#endif
|
||||
|
||||
#if (NUM_BLOCKS > 0xFFFF) || defined(__DOXYGEN__)
|
||||
/** Type define for a block number in the heap. The exact type width varies depending on the
|
||||
* value of NUM_BLOCKS to ensure that the type can store an index to any block in the block pool.
|
||||
*/
|
||||
typedef uint32_t Block_Number_t;
|
||||
#elif (NUM_BLOCKS > 0xFF)
|
||||
typedef uint16_t Block_Number_t;
|
||||
#else
|
||||
typedef uint8_t Block_Number_t;
|
||||
#endif
|
||||
|
||||
#if (NUM_HANDLES > 0xFFFF) || defined(__DOXYGEN__)
|
||||
/** Type define for a handle number. The exact type width varies depending on the value of NUM_HANDLES
|
||||
* to ensure that the type can store the index of any handle in the handle pool.
|
||||
*/
|
||||
typedef uint32_t Handle_Number_t;
|
||||
#elif (NUM_HANDLES > 0xFF)
|
||||
typedef uint16_t Handle_Number_t;
|
||||
#else
|
||||
typedef uint8_t Handle_Number_t;
|
||||
#endif
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and
|
||||
* returns a handle to the newly allocated memory.
|
||||
*
|
||||
* \param Bytes The number of bytes requested to be allocated from the heap
|
||||
*
|
||||
* \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
|
||||
*/
|
||||
Mem_Handle_t Mem_Alloc(const Alloc_Size_t Bytes);
|
||||
|
||||
/** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and
|
||||
* returns a handle to the newly allocated memory. Calloced memory is automatically cleared to all 0x00
|
||||
* values at the time of allocation.
|
||||
*
|
||||
* \param Bytes The number of pre-cleared bytes requested to be allocated from the heap
|
||||
*
|
||||
* \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
|
||||
*/
|
||||
Mem_Handle_t Mem_Calloc(const Alloc_Size_t Bytes);
|
||||
|
||||
/** Deallocates a given memory handle, and attempts to allocates the given number of blocks from the heap
|
||||
* (calculated from the requested number of bytes) immediately following the deallocation. The new memory
|
||||
* may be located in the same area as the previous memory, but this is not guaranteed.
|
||||
*
|
||||
* \param CurrAllocHdl Handle to an already allocated section of memory in the heap to deallocate
|
||||
* \param Bytes The number of bytes requested to be allocated from the heap following the
|
||||
* deallocation
|
||||
*
|
||||
* \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
|
||||
*
|
||||
* \warning Even if the allocation fails, the deallocation will still occur. Care should be taken to ensure
|
||||
* that the previously allocated memory is not used following an unsuccessful realloc().
|
||||
*/
|
||||
Mem_Handle_t Mem_Realloc(Mem_Handle_t CurrAllocHdl, const Alloc_Size_t Bytes);
|
||||
|
||||
/** Deallocates a given previously allocated section of memory from the heap.
|
||||
*
|
||||
* \param CurrAllocHdl Handle to a previously allocated section of memory in the heap
|
||||
*/
|
||||
void Mem_Free(Mem_Handle_t CurrAllocHdl);
|
||||
|
||||
/** Returns the total number of unallocated blocks in the heap.
|
||||
*
|
||||
* \return Number of free blocks in the heap, as a Block_Number_t integer
|
||||
*/
|
||||
Block_Number_t Mem_TotalFreeBlocks(void);
|
||||
|
||||
/** Returns the total number of unallocated handles in the handle pool.
|
||||
*
|
||||
* \return Number of free handles in the handle pool, as a Handle_Number_t integer
|
||||
*/
|
||||
Handle_Number_t Mem_TotalFreeHandles(void);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define BLOCK_USED_MASK (1 << 0)
|
||||
#define BLOCK_LINKED_MASK (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(INCLUDE_FROM_DYNALLOC_C)
|
||||
static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum);
|
||||
static void Mem_SetBlockFlags(const Block_Number_t BlockNum, const uint8_t Flags);
|
||||
static void Mem_Defrag(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
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 "Scheduler.h"
|
||||
|
||||
volatile SchedulerDelayCounter_t Scheduler_TickCounter;
|
||||
volatile uint8_t Scheduler_TotalTasks;
|
||||
|
||||
bool Scheduler_HasDelayElapsed(const uint16_t Delay, SchedulerDelayCounter_t* const DelayCounter)
|
||||
{
|
||||
SchedulerDelayCounter_t CurrentTickValue_LCL;
|
||||
SchedulerDelayCounter_t DelayCounter_LCL;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
CurrentTickValue_LCL = Scheduler_TickCounter;
|
||||
}
|
||||
|
||||
DelayCounter_LCL = *DelayCounter;
|
||||
|
||||
if (CurrentTickValue_LCL >= DelayCounter_LCL)
|
||||
{
|
||||
if ((CurrentTickValue_LCL - DelayCounter_LCL) >= Delay)
|
||||
{
|
||||
*DelayCounter = CurrentTickValue_LCL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((MAX_DELAYCTR_COUNT - DelayCounter_LCL) + CurrentTickValue_LCL) >= Delay)
|
||||
{
|
||||
*DelayCounter = CurrentTickValue_LCL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus)
|
||||
{
|
||||
TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
|
||||
|
||||
while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks])
|
||||
{
|
||||
if (CurrTask->Task == Task)
|
||||
{
|
||||
CurrTask->TaskStatus = TaskStatus;
|
||||
break;
|
||||
}
|
||||
|
||||
CurrTask++;
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus)
|
||||
{
|
||||
TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
|
||||
|
||||
while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks])
|
||||
{
|
||||
if (CurrTask->GroupID == GroupID)
|
||||
CurrTask->TaskStatus = TaskStatus;
|
||||
|
||||
CurrTask++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
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
|
||||
*
|
||||
* Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
|
||||
* to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
|
||||
*/
|
||||
|
||||
/** @defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Scheduler/Scheduler.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
|
||||
* to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
|
||||
*
|
||||
* For a task to yield it must return, thus each task should have persistent data marked with the static attribute.
|
||||
*
|
||||
* Usage Example:
|
||||
* \code
|
||||
* #include <LUFA/Scheduler/Scheduler.h>
|
||||
*
|
||||
* TASK(MyTask1);
|
||||
* TASK(MyTask2);
|
||||
*
|
||||
* TASK_LIST
|
||||
* {
|
||||
* { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
|
||||
* { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 },
|
||||
* }
|
||||
*
|
||||
* int main(void)
|
||||
* {
|
||||
* Scheduler_Start();
|
||||
* }
|
||||
*
|
||||
* TASK(MyTask1)
|
||||
* {
|
||||
* // Implementation Here
|
||||
* }
|
||||
*
|
||||
* TASK(MyTask2)
|
||||
* {
|
||||
* // Implementation Here
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __SCHEDULER_H__
|
||||
#define __SCHEDULER_H__
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <util/atomic.h>
|
||||
|
||||
#include "../Common/Common.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Creates a new scheduler task body or prototype. Should be used in the form:
|
||||
* \code
|
||||
* TASK(TaskName); // Prototype
|
||||
*
|
||||
* TASK(TaskName)
|
||||
* {
|
||||
* // Task body
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
#define TASK(name) void name (void)
|
||||
|
||||
/** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list
|
||||
* should be encased in curly braces and ended with a comma.
|
||||
*
|
||||
* Usage Example:
|
||||
* \code
|
||||
* TASK_LIST
|
||||
* {
|
||||
* { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
|
||||
* // More task entries here
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
#define TASK_LIST TaskEntry_t Scheduler_TaskList[] =
|
||||
|
||||
/** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type
|
||||
* SchedulerDelayCounter_t.
|
||||
*/
|
||||
#define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)
|
||||
|
||||
/** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
|
||||
#define TASK_RUN true
|
||||
|
||||
/** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
|
||||
#define TASK_STOP false
|
||||
|
||||
/* Pseudo-Function Macros: */
|
||||
#if defined(__DOXYGEN__)
|
||||
/** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end
|
||||
* of the user application's main() function, as it can never return to the calling function.
|
||||
*/
|
||||
void Scheduler_Start(void);
|
||||
|
||||
/** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself
|
||||
* is started. This must be executed before any scheduler function calls other than Scheduler_Start(),
|
||||
* and can be omitted if no such functions could be called before the scheduler is started.
|
||||
*/
|
||||
void Scheduler_Init(void);
|
||||
#else
|
||||
#define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);
|
||||
|
||||
#define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);
|
||||
#endif
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for a pointer to a scheduler task. */
|
||||
typedef void (*TaskPtr_t)(void);
|
||||
|
||||
/** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay
|
||||
* possible.
|
||||
*/
|
||||
typedef uint16_t SchedulerDelayCounter_t;
|
||||
|
||||
/** Structure for holding a single task's information in the scheduler task list. */
|
||||
typedef struct
|
||||
{
|
||||
TaskPtr_t Task; /**< Pointer to the task to execute. */
|
||||
bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */
|
||||
uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */
|
||||
} TaskEntry_t;
|
||||
|
||||
/* Global Variables: */
|
||||
/** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type
|
||||
* TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler
|
||||
* functions should be used instead of direct manipulation.
|
||||
*/
|
||||
extern TaskEntry_t Scheduler_TaskList[];
|
||||
|
||||
/** Contains the total number of tasks in the task list, irrespective of if the task's status is set to
|
||||
* TASK_RUN or TASK_STOP.
|
||||
*
|
||||
* \note This value should be treated as read-only, and never altered in user-code.
|
||||
*/
|
||||
extern volatile uint8_t Scheduler_TotalTasks;
|
||||
|
||||
/** Contains the current scheduler tick count, for use with the delay functions. If the delay functions
|
||||
* are used in the user code, this should be incremented each tick period so that the delays can be
|
||||
* calculated.
|
||||
*/
|
||||
extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Resets the delay counter value to the current tick count. This should be called to reset the period
|
||||
* for a delay in a task which is dependant on the current tick value.
|
||||
*
|
||||
* \param DelayCounter Counter which is storing the starting tick count for a given delay.
|
||||
*/
|
||||
static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
|
||||
static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
*DelayCounter = Scheduler_TickCounter;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Determines if the given tick delay has elapsed, based on the given .
|
||||
*
|
||||
* \param Delay The delay to test for, measured in ticks
|
||||
* \param DelayCounter The counter which is storing the starting tick value for the delay
|
||||
*
|
||||
* \return Boolean true if the delay has elapsed, false otherwise
|
||||
*
|
||||
* Usage Example:
|
||||
* \code
|
||||
* static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up
|
||||
*
|
||||
* // Task runs every 10000 ticks, 10 seconds for this demo
|
||||
* if (Scheduler_HasDelayElapsed(10000, &DelayCounter))
|
||||
* {
|
||||
* // Code to execute after delay interval elapsed here
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
bool Scheduler_HasDelayElapsed(const uint16_t Delay,
|
||||
SchedulerDelayCounter_t* const DelayCounter)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sets the task mode for a given task.
|
||||
*
|
||||
* \param Task Name of the task whose status is to be changed
|
||||
* \param TaskStatus New task status for the task (TASK_RUN or TASK_STOP)
|
||||
*/
|
||||
void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus);
|
||||
|
||||
/** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their
|
||||
* statuses changed at once.
|
||||
*
|
||||
* \param GroupID Value of the task group ID whose status is to be changed
|
||||
* \param TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP)
|
||||
*/
|
||||
void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))
|
||||
#define MAX_DELAYCTR_COUNT 0xFFFF
|
||||
|
||||
/* Inline Functions: */
|
||||
static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE;
|
||||
static inline void Scheduler_InitScheduler(const uint8_t TotalTasks)
|
||||
{
|
||||
Scheduler_TotalTasks = TotalTasks;
|
||||
}
|
||||
|
||||
static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE;
|
||||
static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)
|
||||
{
|
||||
Scheduler_InitScheduler(TotalTasks);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
|
||||
|
||||
while (CurrTask != &Scheduler_TaskList[TotalTasks])
|
||||
{
|
||||
if (CurrTask->TaskStatus == TASK_RUN)
|
||||
CurrTask->Task();
|
||||
|
||||
CurrTask++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/** \file
|
||||
*
|
||||
* This file contains special DoxyGen information for the generation of the main page and other special
|
||||
* documentation pages. It is not a project source file.
|
||||
*/
|
||||
|
||||
/** \page Page_SchedulerOverview LUFA Scheduler Overview
|
||||
*
|
||||
* The LUFA library comes with a small, basic round-robbin scheduler which allows for small "tasks" to be executed
|
||||
* continuously in sequence, and enabled/disabled at runtime. Unlike a conventional, complex RTOS scheduler, the
|
||||
* LUFA scheduler is very simple in design and operation and is essentially a loop conditionally executing a series
|
||||
* of functions.
|
||||
*
|
||||
* Each LUFA scheduler task should be written similar to an ISR; it should execute quickly (so that no one task
|
||||
* hogs the processor, preventing another from running before some sort of timeout is exceeded). Unlike normal RTOS
|
||||
* tasks, each LUFA scheduler task is a regular function, and thus must be designed to be called, and designed to
|
||||
* return to the calling scheduler function repeatedly. Data which must be preserved between task calls should be
|
||||
* declared as global or (preferably) as a static local variable inside the task.
|
||||
*
|
||||
* The scheduler consists of a task list, listing all the tasks which can be executed by the scheduler. Once started,
|
||||
* each task is then called one after another, unless the task is stopped by another running task or interrupt.
|
||||
*
|
||||
*
|
||||
* If desired, the LUFA scheduler <b>does not need to be used</b> in a LUFA powered application. A more conventional
|
||||
* approach to application design can be used, or a proper scheduling RTOS inserted in the place of the LUFA scheduler.
|
||||
* In the case of the former the USB task must be run manually repeatedly to maintain USB communications, and in the
|
||||
* case of the latter a proper RTOS task must be set up to do the same.
|
||||
*
|
||||
*
|
||||
* For more information on the LUFA scheduler, see the Scheduler.h file documentation.
|
||||
*/
|
||||
|
|
@ -15,13 +15,9 @@ LUFA_SRC_FILES = ./Drivers/USB/LowLevel/DevChapter9.c \
|
|||
./Drivers/USB/LowLevel/LowLevel.c \
|
||||
./Drivers/USB/LowLevel/Pipe.c \
|
||||
./Drivers/USB/HighLevel/Events.c \
|
||||
./Drivers/USB/HighLevel/StdDescriptors.c \
|
||||
./Drivers/USB/HighLevel/USBInterrupt.c \
|
||||
./Drivers/USB/HighLevel/USBTask.c \
|
||||
./Drivers/USB/Class/ConfigDescriptor.c \
|
||||
./Drivers/USB/Class/HIDParser.c \
|
||||
./Scheduler/Scheduler.c \
|
||||
./MemoryAllocator/DynAlloc.c \
|
||||
./Drivers/USB/HighLevel/ConfigDescriptor.c \
|
||||
./Drivers/Board/Temperature.c \
|
||||
./Drivers/Peripheral/Serial.c \
|
||||
./Drivers/Peripheral/SerialStream.c \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue