summaryrefslogtreecommitdiff
path: root/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c
diff options
context:
space:
mode:
Diffstat (limited to 'digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c')
-rw-r--r--digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c
new file mode 100644
index 00000000..9ea3f417
--- /dev/null
+++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/DevChapter9.c
@@ -0,0 +1,313 @@
+/*
+ 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 "USBMode.h"
+#if defined(USB_CAN_BE_DEVICE)
+
+#define INCLUDE_FROM_DEVCHAPTER9_C
+#include "DevChapter9.h"
+
+uint8_t USB_ConfigurationNumber;
+bool USB_RemoteWakeupEnabled;
+bool USB_CurrentlySelfPowered;
+
+void USB_Device_ProcessControlPacket(void)
+{
+ uint8_t bmRequestType = Endpoint_Read_Byte();
+ uint8_t bRequest = Endpoint_Read_Byte();
+ bool RequestHandled = false;
+
+ switch (bRequest)
+ {
+ case REQ_GetStatus:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
+ {
+ USB_Device_GetStatus(bmRequestType);
+ RequestHandled = true;
+ }
+
+ break;
+#if !defined(NO_CLEARSET_FEATURE_REQUEST)
+ case REQ_ClearFeature:
+ case REQ_SetFeature:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT))
+ {
+ USB_Device_ClearSetFeature(bRequest, bmRequestType);
+ RequestHandled = true;
+ }
+
+ break;
+#endif
+ case REQ_SetAddress:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_SetAddress();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_GetDescriptor:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
+ {
+ USB_Device_GetDescriptor();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_GetConfiguration:
+ if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_GetConfiguration();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_SetConfiguration:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_SetConfiguration();
+ RequestHandled = true;
+ }
+
+ break;
+ }
+
+ if (!(RequestHandled))
+ RAISE_EVENT(USB_UnhandledControlPacket, bRequest, bmRequestType);
+
+ if (Endpoint_IsSetupReceived())
+ {
+ Endpoint_StallTransaction();
+ Endpoint_ClearSetupReceived();
+ }
+}
+
+static void USB_Device_SetAddress(void)
+{
+ uint8_t wValue_LSB = Endpoint_Read_Byte();
+
+ Endpoint_ClearSetupReceived();
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ UDADDR = ((1 << ADDEN) | (wValue_LSB & 0x7F));
+
+ return;
+}
+
+static void USB_Device_SetConfiguration(void)
+{
+ uint8_t wValue_LSB = Endpoint_Read_Byte();
+ bool AlreadyConfigured = (USB_ConfigurationNumber != 0);
+
+#if defined(USE_SINGLE_DEVICE_CONFIGURATION)
+ if (wValue_LSB > 1)
+#else
+ USB_Descriptor_Device_t* DevDescriptorPtr;
+
+ if ((USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr) == NO_DESCRIPTOR) ||
+ #if defined(USE_RAM_DESCRIPTORS)
+ (wValue_LSB > DevDescriptorPtr->NumberOfConfigurations))
+ #elif defined (USE_EEPROM_DESCRIPTORS)
+ (wValue_LSB > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ #else
+ (wValue_LSB > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ #endif
+#endif
+ {
+ return;
+ }
+
+ Endpoint_ClearSetupReceived();
+
+ USB_ConfigurationNumber = wValue_LSB;
+
+ Endpoint_ClearSetupIN();
+
+ if (!(AlreadyConfigured) && USB_ConfigurationNumber)
+ RAISE_EVENT(USB_DeviceEnumerationComplete);
+
+ RAISE_EVENT(USB_ConfigurationChanged);
+}
+
+void USB_Device_GetConfiguration(void)
+{
+ Endpoint_ClearSetupReceived();
+
+ Endpoint_Write_Byte(USB_ConfigurationNumber);
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+static void USB_Device_GetDescriptor(void)
+{
+ uint16_t wValue = Endpoint_Read_Word_LE();
+ uint16_t wIndex = Endpoint_Read_Word_LE();
+ uint16_t wLength = Endpoint_Read_Word_LE();
+
+ void* DescriptorPointer;
+ uint16_t DescriptorSize;
+
+ bool SendZLP;
+
+ if ((DescriptorSize = USB_GetDescriptor(wValue, wIndex, &DescriptorPointer)) == NO_DESCRIPTOR)
+ return;
+
+ Endpoint_ClearSetupReceived();
+
+ if (wLength > DescriptorSize)
+ wLength = DescriptorSize;
+
+ while (wLength)
+ {
+ while (!(Endpoint_IsSetupINReady()))
+ {
+ if (Endpoint_IsSetupOUTReceived())
+ {
+ Endpoint_ClearSetupOUT();
+ return;
+ }
+ }
+
+ while (wLength && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
+ {
+ #if defined(USE_RAM_DESCRIPTORS)
+ Endpoint_Write_Byte(*((uint8_t*)DescriptorPointer++));
+ #elif defined (USE_EEPROM_DESCRIPTORS)
+ Endpoint_Write_Byte(eeprom_read_byte(DescriptorPointer++));
+ #else
+ Endpoint_Write_Byte(pgm_read_byte(DescriptorPointer++));
+ #endif
+
+ wLength--;
+ }
+
+ SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
+ Endpoint_ClearSetupIN();
+ }
+
+ if (SendZLP)
+ {
+ while (!(Endpoint_IsSetupINReady()));
+ Endpoint_ClearSetupIN();
+ }
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+static void USB_Device_GetStatus(const uint8_t bmRequestType)
+{
+ uint8_t CurrentStatus = 0;
+
+ Endpoint_Discard_Word();
+
+ uint8_t wIndex_LSB = Endpoint_Read_Byte();
+
+ switch (bmRequestType)
+ {
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
+ if (USB_CurrentlySelfPowered)
+ CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
+
+ if (USB_RemoteWakeupEnabled)
+ CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
+
+ break;
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
+ Endpoint_SelectEndpoint(wIndex_LSB);
+
+ CurrentStatus = Endpoint_IsStalled();
+
+ break;
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ Endpoint_ClearSetupReceived();
+ Endpoint_Write_Word_LE(CurrentStatus);
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+#if !defined(NO_CLEARSET_FEATURE_REQUEST)
+static void USB_Device_ClearSetFeature(const uint8_t bRequest, const uint8_t bmRequestType)
+{
+ uint16_t wValue = Endpoint_Read_Word_LE();
+ uint16_t wIndex = Endpoint_Read_Word_LE();
+
+ switch (bmRequestType & CONTROL_REQTYPE_RECIPIENT)
+ {
+ case REQREC_ENDPOINT:
+ if (wValue == FEATURE_ENDPOINT_HALT)
+ {
+ uint8_t EndpointIndex = (wIndex & ENDPOINT_EPNUM_MASK);
+
+ if (EndpointIndex != ENDPOINT_CONTROLEP)
+ {
+ Endpoint_SelectEndpoint(EndpointIndex);
+
+ if (Endpoint_IsEnabled())
+ {
+ if (bRequest == REQ_ClearFeature)
+ {
+ Endpoint_ClearStall();
+ Endpoint_ResetFIFO(EndpointIndex);
+ Endpoint_ResetDataToggle();
+ }
+ else
+ {
+ Endpoint_StallTransaction();
+ }
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ Endpoint_ClearSetupReceived();
+ Endpoint_ClearSetupIN();
+ }
+ }
+
+ break;
+ }
+}
+#endif
+
+#endif