From df5500e81cc40633eb5edee59410030f0aa77c2d Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Thu, 13 Aug 2009 06:43:17 +0000 Subject: Added CDC_Device_Flush() command to the CDC Device mode class driver. Minor updates to the unfinished SideShow demo for clarity. Added unfinished MassStorageHost class driver demo. --- LUFA/Drivers/USB/Class/Device/CDC.c | 32 ++++++----- LUFA/Drivers/USB/Class/Device/CDC.h | 6 ++ LUFA/Drivers/USB/Class/Host/HID.c | 10 ++-- LUFA/Drivers/USB/Class/Host/HID.h | 2 +- LUFA/Drivers/USB/Class/Host/MassStorage.c | 95 +++++++++++++++++++++++++++++++ LUFA/Drivers/USB/Class/Host/MassStorage.h | 59 +++++++++++++++++++ LUFA/Drivers/USB/LowLevel/LowLevel.c | 4 -- LUFA/ManPages/ChangeLog.txt | 1 + LUFA/ManPages/LUFAPoweredProjects.txt | 5 +- 9 files changed, 190 insertions(+), 24 deletions(-) (limited to 'LUFA') diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c index a6e5e2689..cbb9a8585 100644 --- a/LUFA/Drivers/USB/Class/Device/CDC.c +++ b/LUFA/Drivers/USB/Class/Device/CDC.c @@ -115,21 +115,10 @@ bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo) void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo) { - if (USB_DeviceState != DEVICE_STATE_Configured) + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) return; - Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); - - if (!(Endpoint_BytesInEndpoint())) - return; - - if (!(Endpoint_IsReadWriteAllowed())) - { - Endpoint_ClearIN(); - Endpoint_WaitUntilReady(); - } - - Endpoint_ClearIN(); + CDC_Device_Flush(CDCInterfaceInfo); } void CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length) @@ -157,6 +146,23 @@ void CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, con Endpoint_Write_Byte(Data); } +void CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); + + if (Endpoint_BytesInEndpoint()) + { + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); + } + + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); +} + uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) { Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h index 7513f9fda..a58bea24b 100644 --- a/LUFA/Drivers/USB/Class/Device/CDC.h +++ b/LUFA/Drivers/USB/Class/Device/CDC.h @@ -185,6 +185,12 @@ */ uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo); + /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + */ + void CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo); + /** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial * control lines (DCD, DSR, etc.) have changed states, or to give BREAK notfications to the host. Line states persist * until they are cleared via a second notification. This should be called each time the CDC class driver's diff --git a/LUFA/Drivers/USB/Class/Host/HID.c b/LUFA/Drivers/USB/Class/Host/HID.c index dc6997736..793523866 100644 --- a/LUFA/Drivers/USB/Class/Host/HID.c +++ b/LUFA/Drivers/USB/Class/Host/HID.c @@ -39,7 +39,7 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, uint16_t ConfigDescriptorSize, uint8_t* ConfigDescriptorData) { - uint8_t FoundEndpoints = 0; + uint8_t FoundEndpoints = 0; memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); @@ -68,7 +68,7 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, uint #endif HIDInterfaceInfo->State.SupportsBootSubClass = (CurrentHIDInterface->SubClass != 0); - while (FoundEndpoints != ((1 << HID_FOUND_DATAPIPE_IN) | (1 << HID_FOUND_DATAPIPE_OUT))) + while (FoundEndpoints != (HID_FOUND_DATAPIPE_IN | HID_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_HID_Host_NextInterfaceHIDDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) @@ -85,15 +85,17 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, uint { Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); + HIDInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; - FoundEndpoints |= (1 << HID_FOUND_DATAPIPE_IN); + FoundEndpoints |= HID_FOUND_DATAPIPE_IN; } else { Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); + HIDInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; - FoundEndpoints |= (1 << HID_FOUND_DATAPIPE_OUT); + FoundEndpoints |= HID_FOUND_DATAPIPE_OUT; } } diff --git a/LUFA/Drivers/USB/Class/Host/HID.h b/LUFA/Drivers/USB/Class/Host/HID.h index d94fa2e0e..3d7a5390a 100644 --- a/LUFA/Drivers/USB/Class/Host/HID.h +++ b/LUFA/Drivers/USB/Class/Host/HID.h @@ -100,7 +100,7 @@ HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */ HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */ HID_ENUMERROR_NoHIDInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor */ - HID_ENUMERROR_EndpointsNotFound = 3, /**< Compatible HID endpoints were not found in the device's CDC interface */ + HID_ENUMERROR_EndpointsNotFound = 3, /**< Compatible HID endpoints were not found in the device's HID interface */ } HIDHost_EnumerationFailure_ErrorCodes_t; /* Function Prototypes: */ diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c index 17b393973..6332d3a61 100644 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.c +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c @@ -36,4 +36,99 @@ #warning The Mass Storage Host mode Class driver is currently incomplete and is for preview purposes only. +uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint16_t ConfigDescriptorLength, + uint8_t* DeviceConfigDescriptor) +{ + uint8_t FoundEndpoints = 0; + + memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State)); + + if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration) + return MS_ENUMERROR_InvalidConfigDescriptor; + + if (USB_GetNextDescriptorComp(&ConfigDescriptorLength, &DeviceConfigDescriptor, + DComp_NextMassStorageInterface) != DESCRIPTOR_SEARCH_COMP_Found) + { + return MS_ENUMERROR_NoMSInterfaceFound; + } + + MSInterfaceInfo->State.InterfaceNumber = + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) + DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t)->InterfaceNumber; + #else + DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t)->bInterfaceNumber; + #endif + + while (FoundEndpoints != (MS_FOUND_DATAPIPE_IN | MS_FOUND_DATAPIPE_OUT)) + { + if (USB_GetNextDescriptorComp(&ConfigDescriptorLength, &DeviceConfigDescriptor, + DComp_NextInterfaceBulkDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) + { + return MS_ENUMERROR_EndpointsNotFound; + } + + USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t); + + if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) + { + Pipe_ConfigurePipe(MSInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, + EndpointData->EndpointAddress, EndpointData->EndpointSize, + PIPE_BANK_DOUBLE); + MSInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; + + FoundEndpoints |= MS_FOUND_DATAPIPE_IN; + } + else + { + Pipe_ConfigurePipe(MSInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, + EndpointData->EndpointAddress, EndpointData->EndpointSize, + PIPE_BANK_DOUBLE); + MSInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; + + FoundEndpoints |= MS_FOUND_DATAPIPE_OUT; + } + } + + MSInterfaceInfo->State.Active = true; + return MS_ENUMERROR_NoError; +} + +static uint8_t DComp_NextMassStorageInterface(void* CurrentDescriptor) +{ + if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) + { + if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == MASS_STORE_CLASS) && + (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == MASS_STORE_SUBCLASS) && + (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == MASS_STORE_PROTOCOL)) + { + return DESCRIPTOR_SEARCH_Found; + } + } + + return DESCRIPTOR_SEARCH_NotFound; +} + +static uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor) +{ + if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) + { + uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor, + USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK); + + if (EndpointType == EP_TYPE_BULK) + return DESCRIPTOR_SEARCH_Found; + } + else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) + { + return DESCRIPTOR_SEARCH_Fail; + } + + return DESCRIPTOR_SEARCH_NotFound; +} + +void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* MSInterfaceInfo) +{ + +} + #endif diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.h b/LUFA/Drivers/USB/Class/Host/MassStorage.h index 0f4bdd17b..18b2cf4ae 100644 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.h +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.h @@ -54,8 +54,67 @@ #endif /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** Class state structure. An instance of this structure should be made within the user application, + * and passed to each of the HID class driver functions as the HIDInterfaceInfo parameter. This + * stores each HID interface's configuration and state information. + */ + typedef struct + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the MS interface's IN data pipe */ + uint8_t DataOUTPipeNumber; /**< Pipe number of the MS interface's OUT data pipe */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must be set or the interface will fail to enumerate and operate correctly. + */ + struct + { + bool Active; /**< Indicates if the current interface instance is connected to an attached device, valid + * after \ref HID_Host_ConfigurePipes() is called and the Host state machine is in the + * Configured state + */ + uint8_t InterfaceNumber; /**< Interface index of the HID interface within the attached device */ + + uint16_t DataINPipeSize; /**< Size in bytes of the MS interface's IN data pipe */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the MS interface's OUT data pipe */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * may be set to initial values, but may also be ignored to default to sane values when + * the interface is enumerated. + */ + } USB_ClassInfo_MS_Host_t; + + /* Enums: */ + enum + { + MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */ + MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */ + MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor */ + MS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces */ + } MSHost_EnumerationFailure_ErrorCodes_t; + /* Function Prototypes: */ + void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* MSInterfaceInfo); + uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint16_t ConfigDescriptorLength, + uint8_t* DeviceConfigDescriptor); + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define MASS_STORE_CLASS 0x08 + #define MASS_STORE_SUBCLASS 0x06 + #define MASS_STORE_PROTOCOL 0x50 + + #define MS_FOUND_DATAPIPE_IN (1 << 0) + #define MS_FOUND_DATAPIPE_OUT (1 << 1) + + /* Function Prototypes: */ + #if defined(INCLUDE_FROM_MS_CLASS_HOST_C) + static uint8_t DComp_NextMassStorageInterface(void* CurrentDescriptor); + static uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor); + #endif + #endif + /* Disable C linkage for C++ Compilers: */ #if defined(__cplusplus) } diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.c b/LUFA/Drivers/USB/LowLevel/LowLevel.c index e6791098a..f15db40aa 100644 --- a/LUFA/Drivers/USB/LowLevel/LowLevel.c +++ b/LUFA/Drivers/USB/LowLevel/LowLevel.c @@ -213,10 +213,6 @@ void USB_ResetInterface(void) #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) USB_INT_Enable(USB_INT_VBUS); #endif - - #if defined(CONTROL_ONLY_DEVICE) - UENUM = ENDPOINT_CONTROLEP; - #endif #elif defined(USB_HOST_ONLY) USB_Host_HostMode_On(); diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 059734f2f..24e6b8d11 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -15,6 +15,7 @@ * Changed: * - SetIdle requests to the HID device driver with a 0 idle period (send changes only) now only affect the requested * HID interface within the device, not all HID interfaces. + * - Added new CDC_Device_Flush() command to the CDC Class device driver. * * Fixed: * - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the diff --git a/LUFA/ManPages/LUFAPoweredProjects.txt b/LUFA/ManPages/LUFAPoweredProjects.txt index dad5c9b90..752bf7b2b 100644 --- a/LUFA/ManPages/LUFAPoweredProjects.txt +++ b/LUFA/ManPages/LUFAPoweredProjects.txt @@ -27,7 +27,7 @@ * * \section Sec_LUFAProjects Projects Using LUFA (Hobbyist) * - * The following are hobbyist projects using LUFA. Most are open source, and show off interesting ways that the LUFA library + * The following are known hobbyist projects using LUFA. Most are open source, and show off interesting ways that the LUFA library * can be incorporated into many different applications. * * - Bicycle POV: http://www.code.google.com/p/bicycleledpov/ @@ -36,8 +36,9 @@ * - Opendous-JTAG, an open source JTAG device: http://code.google.com/p/opendous-jtag/ * - Openkubus, an open source hardware-based authentication dongle: http://code.google.com/p/openkubus/ * - Orbee, a USB connected RGB Orb for notifications: http://www.franksworkshop.com.au/Electronics/Orbee/Orbee.htm + * - NES Controller USB modification: http://projects.peterpolidoro.net/video/NESUSB.htm * - Reprap with LUFA, a LUFA powered 3D printer: http://code.google.com/p/at90usb1287-code-for-arduino-and-eclipse/ - * - SEGA Megadrive/Genesis Development Cartridge: http://www.spritesmind.net/_GenDev/forum/viewtopic.php?t=464 + * - SEGA Megadrive/Genesis Development Cartridge: http://www.makestuff.eu/wordpress/?page_id=398 * - Stripe Snoop, a Magnetic Card reader: http://www.ossguy.com/ss_usb/ * - USB Interface for Playstation Portable Devices: http://forums.ps2dev.org/viewtopic.php?t=11001 * - USB to Serial Bridge, via SPI and I2C: http://www.tty1.net/userial/ -- cgit v1.2.3