void Pipe_ClearPipes(void) { for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++) { Pipe_SelectPipe(PNum); (&AVR32_USBB.upcfg0)[PNum] = 0; (&AVR32_USBB.upcon0clr)[PNum] = -1; USB_Pipe_FIFOPos[PNum] = &AVR32_USBB_SLAVE[PNum * 0x10000]; Pipe_DisablePipe(); } }
void Pipe_ClearPipes(void) { UPINT = 0; for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++) { Pipe_SelectPipe(PNum); UPIENX = 0; UPINTX = 0; UPCFG1X = 0; Pipe_DisablePipe(); } }
void Pipe_ClearPipes(void) { UPINT = 0; for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++) { Pipe_ResetPipe(PNum); Pipe_SelectPipe(PNum); UPIENX = 0; UPINTX = 0; Pipe_ClearError(); Pipe_ClearErrorFlags(); Pipe_DeallocateMemory(); Pipe_DisablePipe(); } }
bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks) { uint8_t Number = (Address & PIPE_EPNUM_MASK); uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT; if (Number >= PIPE_TOTAL_PIPES) return false; if (Type == EP_TYPE_CONTROL) Token = PIPE_TOKEN_SETUP; #if defined(ORDERED_EP_CONFIG) Pipe_SelectPipe(Number); Pipe_EnablePipe(); UPCFG1X = 0; UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0)); UPCFG1X = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size)); Pipe_SetInfiniteINRequests(); return Pipe_IsConfigured(); #else for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++) { uint8_t UPCFG0XTemp; uint8_t UPCFG1XTemp; uint8_t UPCFG2XTemp; uint8_t UPIENXTemp; Pipe_SelectPipe(PNum); if (PNum == Number) { UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0)); UPCFG1XTemp = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size)); UPCFG2XTemp = 0; UPIENXTemp = 0; } else { UPCFG0XTemp = UPCFG0X; UPCFG1XTemp = UPCFG1X; UPCFG2XTemp = UPCFG2X; UPIENXTemp = UPIENX; } if (!(UPCFG1XTemp & (1 << ALLOC))) continue; Pipe_DisablePipe(); UPCFG1X &= ~(1 << ALLOC); Pipe_EnablePipe(); UPCFG0X = UPCFG0XTemp; UPCFG1X = UPCFG1XTemp; UPCFG2X = UPCFG2XTemp; UPIENX = UPIENXTemp; Pipe_SetInfiniteINRequests(); if (!(Pipe_IsConfigured())) return false; } Pipe_SelectPipe(Number); return true; #endif }
bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks) { uint8_t Number = (Address & PIPE_EPNUM_MASK); uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT; if (Number >= PIPE_TOTAL_PIPES) return false; if (Type == EP_TYPE_CONTROL) Token = PIPE_TOKEN_SETUP; USB_Pipe_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * PIPE_HSB_ADDRESS_SPACE_SIZE]; #if defined(ORDERED_EP_CONFIG) Pipe_SelectPipe(Number); Pipe_EnablePipe(); (&AVR32_USBB.upcfg0)[Number] = 0; (&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) | Pipe_BytesToEPSizeMask(Size) | ((uint32_t)Number << AVR32_USBB_PEPNUM_OFFSET)); Pipe_SetInfiniteINRequests(); return Pipe_IsConfigured(); #else for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++) { uint32_t UPCFG0Temp; Pipe_SelectPipe(PNum); if (PNum == Number) { UPCFG0Temp = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) | Pipe_BytesToEPSizeMask(Size) | ((EndpointAddress & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); } else { UPCFG0Temp = (&AVR32_USBB.upcfg0)[PNum]; } if (!(UPCFG0Temp & AVR32_USBB_ALLOC_MASK)) continue; Pipe_DisablePipe(); (&AVR32_USBB.upcfg0)[PNum] &= ~AVR32_USBB_ALLOC_MASK; Pipe_EnablePipe(); (&AVR32_USBB.upcfg0)[PNum] = UPCFG0Temp; Pipe_SetInfiniteINRequests(); if (!(Pipe_IsConfigured())) return false; } Pipe_SelectPipe(Number); return true; #endif }
bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber, const uint16_t Size, const uint8_t Banks) { #if defined(ORDERED_EP_CONFIG) Pipe_SelectPipe(Number); Pipe_EnablePipe(); UPCFG1X = 0; UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0)); UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size)); Pipe_SetInfiniteINRequests(); return Pipe_IsConfigured(); #else for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++) { uint8_t UPCFG0XTemp; uint8_t UPCFG1XTemp; uint8_t UPCFG2XTemp; uint8_t UPCONXTemp; uint8_t UPINRQXTemp; uint8_t UPIENXTemp; Pipe_SelectPipe(PNum); if (PNum == Number) { UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0)); UPCFG1XTemp = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size)); UPCFG2XTemp = 0; UPCONXTemp = ((1 << PEN) | (1 << INMODE)); UPINRQXTemp = 0; UPIENXTemp = 0; } else { UPCFG0XTemp = UPCFG0X; UPCFG1XTemp = UPCFG1X; UPCFG2XTemp = UPCFG2X; UPCONXTemp = UPCONX; UPINRQXTemp = UPINRQX; UPIENXTemp = UPIENX; } Pipe_SetInfiniteINRequests(); if (!(UPCFG1XTemp & (1 << ALLOC))) continue; Pipe_DisablePipe(); UPCFG1X &= (1 << ALLOC); Pipe_EnablePipe(); UPCFG0X = UPCFG0XTemp; UPCFG1X = UPCFG1XTemp; UPCFG2X = UPCFG2XTemp; UPCONX = UPCONXTemp; UPINRQX = UPINRQXTemp; UPIENX = UPIENXTemp; if (!(Pipe_IsConfigured())) return false; } Pipe_SelectPipe(Number); return true; #endif }
bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber, const uint16_t Size, const uint8_t Banks) { #if defined(ORDERED_EP_CONFIG) Pipe_SelectPipe(Number); Pipe_EnablePipe(); (&AVR32_USBB.upcfg0)[Number] = 0; (&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | ((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) | ((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); USB_PipeFIFOPos[Number] = &AVR32_USBB_SLAVE[Number * 0x10000]; Pipe_SetInfiniteINRequests(); return Pipe_IsConfigured(); #else for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++) { uint8_t UPCFG0Temp; Pipe_SelectPipe(PNum); if (PNum == Number) { UPCFG0Temp = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | ((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) | ((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); } else { UPCFG0Temp = (&AVR32_USBB.upcfg0)[PNum] } if (!(UPCFG0Temp & AVR32_USBB_ALLOC_MASK)) continue; Pipe_DisablePipe(); (&AVR32_USBB.upcfg0)[PNum] &= ~AVR32_USBB_ALLOC_MASK; Pipe_EnablePipe(); (&AVR32_USBB.upcfg0)[PNum] = UPCFG0Temp; Pipe_SetInfiniteINRequests(); if (!(Pipe_IsConfigured())) return false; } Pipe_SelectPipe(Number); return true; #endif }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a CDC interface descriptor containing bulk data IN and OUT endpoints, and an interrupt event endpoint. * * \return An error code from the CDCHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; uint8_t FoundEndpoints = 0; /* Get Configuration Descriptor size from the device */ if (USB_GetDeviceConfigDescriptor(&ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) return ControlError; /* Ensure that the Configuration Descriptor isn't too large */ if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE) return DescriptorTooLarge; /* Allocate enough memory for the entire config descriptor */ ConfigDescriptorData = alloca(ConfigDescriptorSize); /* Retrieve the entire configuration descriptor into the allocated buffer */ USB_GetDeviceConfigDescriptor(&ConfigDescriptorSize, ConfigDescriptorData); /* Validate returned data - ensure first entry is a configuration header descriptor */ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return InvalidConfigDataReturned; /* Get the CDC control interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } /* Get the IN and OUT data endpoints for the CDC interface */ while (FoundEndpoints != ((1 << CDC_NOTIFICATIONPIPE) | (1 << CDC_DATAPIPE_IN) | (1 << CDC_DATAPIPE_OUT))) { /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextInterfaceCDCDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check to see if the control interface's notification pipe has been found, if so search for the data interface */ if (FoundEndpoints & (1 << CDC_NOTIFICATIONPIPE)) { /* Get the next CDC data interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } else { /* Clear the found endpoints mask, since any already processed endpoints aren't in the CDC interface we need */ FoundEndpoints = 0; /* Disable any already configured pipes from the invalid CDC interfaces */ Pipe_SelectPipe(CDC_NOTIFICATIONPIPE); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_IN); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_OUT); Pipe_DisablePipe(); /* Get the next CDC control interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextInterfaceCDCDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoEndpointFound; } } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); /* Check if the found endpoint is a interrupt or bulk type descriptor */ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { /* If the endpoint is a IN type interrupt endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the notification pipe */ Pipe_ConfigurePipe(CDC_NOTIFICATIONPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); /* Set the flag indicating that the notification pipe has been found */ FoundEndpoints |= (1 << CDC_NOTIFICATIONPIPE); } } else { /* Check if the endpoint is a bulk IN or bulk OUT endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the data IN pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); Pipe_Unfreeze(); /* Set the flag indicating that the data IN pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_IN); } else { /* Configure the data OUT pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_Unfreeze(); /* Set the flag indicating that the data OUT pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_OUT); } } } /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { uint8_t FoundEndpoints = 0; memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return RNDIS_ENUMERROR_InvalidConfigDescriptor; if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } } else { FoundEndpoints = 0; Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber); Pipe_DisablePipe(); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } } if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_EndpointsNotFound; } } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN; } } else { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN; } else { Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT; } } } RNDISInterfaceInfo->State.IsActive = true; return RNDIS_ENUMERROR_NoError; }
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { uint8_t FoundEndpoints = 0; memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return CDC_ENUMERROR_InvalidConfigDescriptor; if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; while (FoundEndpoints != (CDC_FOUND_NOTIFICATION_IN | CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } } else { FoundEndpoints = 0; Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_DisablePipe(); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } } if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_EndpointsNotFound; } } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); FoundEndpoints |= CDC_FOUND_NOTIFICATION_IN; } } else { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { if (Pipe_IsEndpointBound(EndpointData->EndpointAddress)) { CDCInterfaceInfo->State.BidirectionalDataEndpoints = true; Pipe_DisablePipe(); } Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; FoundEndpoints |= CDC_FOUND_DATAPIPE_IN; } else { if (Pipe_IsEndpointBound(EndpointData->EndpointAddress)) { CDCInterfaceInfo->State.BidirectionalDataEndpoints = true; } else { Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); } CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT; } } } CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR); CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR); CDCInterfaceInfo->State.IsActive = true; return CDC_ENUMERROR_NoError; }
void USB_Host_ProcessNextHostState(void) { uint8_t ErrorCode = HOST_ENUMERROR_NoError; uint8_t SubErrorCode = HOST_ENUMERROR_NoError; static uint16_t WaitMSRemaining; static uint8_t PostWaitState; switch (USB_HostState) { case HOST_STATE_WaitForDevice: if (WaitMSRemaining) { if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) { USB_HostState = PostWaitState; ErrorCode = HOST_ENUMERROR_WaitStage; break; } if (!(--WaitMSRemaining)) USB_HostState = PostWaitState; } break; case HOST_STATE_Powered: WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS; USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle; break; case HOST_STATE_Powered_WaitForDeviceSettle: if (WaitMSRemaining--) { _delay_ms(1); break; } else { USB_Host_VBUS_Manual_Off(); USB_OTGPAD_On(); USB_Host_VBUS_Auto_Enable(); USB_Host_VBUS_Auto_On(); USB_HostState = HOST_STATE_Powered_WaitForConnect; } break; case HOST_STATE_Powered_WaitForConnect: if (USB_INT_HasOccurred(USB_INT_DCONNI)) { USB_INT_Clear(USB_INT_DCONNI); USB_INT_Clear(USB_INT_DDISCI); USB_INT_Clear(USB_INT_VBERRI); USB_INT_Enable(USB_INT_VBERRI); USB_Host_ResumeBus(); Pipe_ClearPipes(); HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset); } break; case HOST_STATE_Powered_DoReset: USB_Host_ResetDevice(); HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe); break; case HOST_STATE_Powered_ConfigPipe: Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE); if (!(Pipe_IsConfigured())) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; break; } USB_HostState = HOST_STATE_Default; break; case HOST_STATE_Default: USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), .bRequest = REQ_GetDescriptor, .wValue = (DTYPE_Device << 8), .wIndex = 0, .wLength = 8, }; uint8_t DataBuffer[8]; if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful) { ErrorCode = HOST_ENUMERROR_ControlError; break; } USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)]; USB_Host_ResetDevice(); HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset); break; case HOST_STATE_Default_PostReset: Pipe_DisablePipe(); Pipe_DeallocateMemory(); Pipe_ResetPipe(PIPE_CONTROLPIPE); Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, USB_ControlPipeSize, PIPE_BANK_SINGLE); if (!(Pipe_IsConfigured())) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; break; } USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE), .bRequest = REQ_SetAddress, .wValue = USB_HOST_DEVICEADDRESS, .wIndex = 0, .wLength = 0, }; if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) { ErrorCode = HOST_ENUMERROR_ControlError; break; } HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet); break; case HOST_STATE_Default_PostAddressSet: USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS); EVENT_USB_Host_DeviceEnumerationComplete(); USB_HostState = HOST_STATE_Addressed; break; } if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached)) { EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode); USB_Host_VBUS_Auto_Off(); EVENT_USB_Host_DeviceUnattached(); USB_ResetInterface(); } } uint8_t USB_Host_WaitMS(uint8_t MS) { bool BusSuspended = USB_Host_IsBusSuspended(); uint8_t ErrorCode = HOST_WAITERROR_Successful; USB_Host_ResumeBus(); while (MS) { if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); MS--; } if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode == USB_MODE_DEVICE)) { ErrorCode = HOST_WAITERROR_DeviceDisconnect; break; } if (Pipe_IsError() == true) { Pipe_ClearError(); ErrorCode = HOST_WAITERROR_PipeError; break; } if (Pipe_IsStalled() == true) { Pipe_ClearStall(); ErrorCode = HOST_WAITERROR_SetupStalled; break; } } if (BusSuspended) USB_Host_SuspendBus(); return ErrorCode; } static void USB_Host_ResetDevice(void) { bool BusSuspended = USB_Host_IsBusSuspended(); USB_INT_Disable(USB_INT_DDISCI); USB_Host_ResetBus(); while (!(USB_Host_IsBusResetComplete())); USB_Host_ResumeBus(); USB_INT_Clear(USB_INT_HSOFI); for (uint8_t MSRem = 10; MSRem != 0; MSRem--) { /* Workaround for powerless-pull-up devices. After a USB bus reset, all disconnection interrupts are suppressed while a USB frame is looked for - if it is found within 10ms, the device is still present. */ if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); USB_INT_Clear(USB_INT_DDISCI); break; } _delay_ms(1); } if (BusSuspended) USB_Host_SuspendBus(); USB_INT_Enable(USB_INT_DDISCI); }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a CDC interface descriptor containing bulk data IN and OUT endpoints, and an interrupt event endpoint. * * \return An error code from the \ref CDCHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; uint8_t FoundEndpoints = 0; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } /* Get the CDC control interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } /* Get the IN and OUT data and IN notification endpoints for the CDC interface */ while (FoundEndpoints != ((1 << CDC_NOTIFICATIONPIPE) | (1 << CDC_DATAPIPE_IN) | (1 << CDC_DATAPIPE_OUT))) { /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check to see if the control interface's notification pipe has been found, if so search for the data interface */ if (FoundEndpoints & (1 << CDC_NOTIFICATIONPIPE)) { /* Get the next CDC data interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } else { /* Clear the found endpoints mask, since any already processed endpoints aren't in the CDC interface we need */ FoundEndpoints = 0; /* Disable any already configured pipes from the invalid CDC interfaces */ Pipe_SelectPipe(CDC_NOTIFICATIONPIPE); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_IN); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_OUT); Pipe_DisablePipe(); /* Get the next CDC control interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoEndpointFound; } } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* Check if the found endpoint is a interrupt or bulk type descriptor */ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { /* If the endpoint is a IN type interrupt endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the notification pipe */ Pipe_ConfigurePipe(CDC_NOTIFICATIONPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); /* Set the flag indicating that the notification pipe has been found */ FoundEndpoints |= (1 << CDC_NOTIFICATIONPIPE); } } else { /* Check if the endpoint is a bulk IN or bulk OUT endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the data IN pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); /* Set the flag indicating that the data IN pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_IN); } else { /* Configure the data OUT pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); /* Set the flag indicating that the data OUT pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_OUT); } } } /* Valid data found, return success */ return SuccessfulConfigRead; }