/** 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 HID interface descriptor containing at least one Interrupt type IN endpoint. * * \return An error code from the MouseHostViaInt_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; /* Get Configuration Descriptor size from the device */ if (USB_Host_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_Host_GetDeviceConfigDescriptor(&ConfigDescriptorSize, ConfigDescriptorData); /* Validate returned data - ensure first entry is a configuration header descriptor */ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return InvalidConfigDataReturned; /* Get the mouse interface from the configuration descriptor */ if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, NextMouseInterface)) { /* Descriptor not found, error out */ return NoHIDInterfaceFound; } /* Get the mouse interface's data endpoint descriptor */ if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, NextInterfaceMouseDataEndpoint)) { /* Descriptor not found, error out */ return NoEndpointFound; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); /* Configure the mouse data pipe */ Pipe_ConfigurePipe(MOUSE_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); Pipe_Unfreeze(); /* Enable the pipe IN interrupt for the data pipe */ USB_INT_Enable(PIPE_INT_IN); /* Valid data found, return success */ return SuccessfulConfigRead; }
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) { 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(); }
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) { 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(); }
/** 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 HID interface descriptor containing at least one Interrupt type IN endpoint and HID descriptor. * * \return An error code from the KeyboardHostWithParser_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; /* 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 keyboard interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextKeyboardInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDInterfaceFound; } /* Get the keyboard interface's HID descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDDescriptorFound; } /* Save the HID report size for later use */ HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_HID_t).HIDReportLength; /* Get the keyboard interface's data endpoint descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextInterfaceKeyboardDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoEndpointFound; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); /* Configure the keyboard data pipe */ Pipe_ConfigurePipe(KEYBOARD_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); /* Valid data found, return success */ return SuccessfulConfigRead; }
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(); (&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 }
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 }
/** 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; }
void Bluetooth_ProcessHCICommands(void) { uint8_t ErrorCode; switch (Bluetooth_HCIProcessingState) { case Bluetooth_Init: Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE); Pipe_SetInfiniteINRequests(); memset(&Bluetooth_Connection, 0x00, sizeof(Bluetooth_Connection)); Bluetooth_HCIProcessingState = Bluetooth_Init_Reset; break; case Bluetooth_Init_Reset: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_RESET}, ParameterLength: 0, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_Reset", NULL); ErrorCode = Bluetooth_SendHCICommand(NULL, 0); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_Init_ReadBufferSize; break; case Bluetooth_Init_ReadBufferSize: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_INFORMATIONAL, OCF: OGF_CTRLR_INFORMATIONAL_READBUFFERSIZE}, ParameterLength: 0, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_ReadBufferSize", NULL); ErrorCode = Bluetooth_SendHCICommand(NULL, 0); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_Init_SetEventMask; break; case Bluetooth_Init_SetEventMask: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_SET_EVENT_MASK}, ParameterLength: 8, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetEventMask", NULL); uint8_t EventMask[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; ErrorCode = Bluetooth_SendHCICommand(&EventMask, 8); BT_DEBUG("(HCI) -- Event mask: 0x%02X%02X%02X%02X%02X%02X%02X%02X", EventMask[7], EventMask[6], EventMask[5], EventMask[4], EventMask[3], EventMask[2], EventMask[1], EventMask[0]); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_Init_SetLocalName; break; case Bluetooth_Init_SetLocalName: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME}, ParameterLength: 248, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetLocalName", NULL); BT_DEBUG("(HCI) -- Name: %s", Bluetooth_DeviceConfiguration.Name); ErrorCode = Bluetooth_SendHCICommand(Bluetooth_DeviceConfiguration.Name, strlen(Bluetooth_DeviceConfiguration.Name)); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_Init_SetDeviceClass; break; case Bluetooth_Init_SetDeviceClass: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE}, ParameterLength: 3, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetDeviceClass", NULL); ErrorCode = Bluetooth_SendHCICommand(&Bluetooth_DeviceConfiguration.Class, 3); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_Init_WriteScanEnable; break; case Bluetooth_Init_WriteScanEnable: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE}, ParameterLength: 1, }; BT_DEBUG("(HCI) Enter State: Bluetooth_Init_WriteScanEnable", NULL); uint8_t Interval = InquiryAndPageScans; ErrorCode = Bluetooth_SendHCICommand(&Interval, 1); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents; break; case Bluetooth_PrepareToProcessEvents: BT_DEBUG("(HCI) Enter State: Bluetooth_ProcessEvents", NULL); Bluetooth_HCIProcessingState = Bluetooth_ProcessEvents; break; case Bluetooth_ProcessEvents: if (Bluetooth_GetNextHCIEventHeader()) { BT_DEBUG("(HCI) Event Code: 0x%02X", HCIEventHeader.EventCode); if (HCIEventHeader.EventCode == EVENT_COMMAND_STATUS) { Bluetooth_HCIEvent_CommandStatus_Header_t CommandStatusHeader; Pipe_Read_Stream_LE(&CommandStatusHeader, sizeof(CommandStatusHeader)); HCIEventHeader.ParameterLength -= sizeof(CommandStatusHeader); BT_DEBUG("(HCI) >> Command status: 0x%02X", CommandStatusHeader.CommandStatus); if (CommandStatusHeader.CommandStatus) Bluetooth_HCIProcessingState = Bluetooth_Init; } else if (HCIEventHeader.EventCode == EVENT_CONNECTION_REQUEST) { Bluetooth_HCIEvent_ConnectionRequest_Header_t ConnectionRequestParams; Pipe_Read_Stream_LE(&ConnectionRequestParams, sizeof(ConnectionRequestParams)); HCIEventHeader.ParameterLength -= sizeof(ConnectionRequestParams); BT_DEBUG("(HCI) >> Connection Request from device %02X:%02X:%02X:%02X:%02X:%02X", ConnectionRequestParams.RemoteAddress[5], ConnectionRequestParams.RemoteAddress[4], ConnectionRequestParams.RemoteAddress[3], ConnectionRequestParams.RemoteAddress[2], ConnectionRequestParams.RemoteAddress[1], ConnectionRequestParams.RemoteAddress[0]); BT_DEBUG("(HCI) -- Device Class: 0x%02X%04X", ConnectionRequestParams.ClassOfDevice_Service, ConnectionRequestParams.ClassOfDevice_MajorMinor); BT_DEBUG("(HCI) -- Link Type: 0x%02x", ConnectionRequestParams.LinkType); memcpy(Bluetooth_TempDeviceAddress, ConnectionRequestParams.RemoteAddress, sizeof(Bluetooth_TempDeviceAddress)); Bluetooth_HCIProcessingState = (Bluetooth_Connection.IsConnected) ? Bluetooth_Conn_RejectConnection : Bluetooth_Conn_AcceptConnection; } else if (HCIEventHeader.EventCode == EVENT_DISCONNECTION_COMPLETE) { BT_DEBUG("(HCI) >> Disconnection from device complete.", NULL); Bluetooth_HCIProcessingState = Bluetooth_Init; } else if (HCIEventHeader.EventCode == EVENT_CONNECTION_COMPLETE) { Bluetooth_HCIEvent_ConnectionComplete_Header_t ConnectionCompleteParams; Pipe_Read_Stream_LE(&ConnectionCompleteParams, sizeof(ConnectionCompleteParams)); HCIEventHeader.ParameterLength -= sizeof(ConnectionCompleteParams); BT_DEBUG("(HCI) >> Connection to device complete.", NULL); BT_DEBUG("(HCI) -- Status: %d", ConnectionCompleteParams.Status); BT_DEBUG("(HCI) -- Handle: %d", ConnectionCompleteParams.ConnectionHandle); if (ConnectionCompleteParams.Status == 0x00) { memcpy(Bluetooth_Connection.DeviceAddress, ConnectionCompleteParams.RemoteAddress, sizeof(Bluetooth_Connection.DeviceAddress)); Bluetooth_Connection.ConnectionHandle = ConnectionCompleteParams.ConnectionHandle; Bluetooth_Connection.IsConnected = true; } } else if (HCIEventHeader.EventCode == EVENT_PIN_CODE_REQUEST) { Pipe_Read_Stream_LE(&Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress)); HCIEventHeader.ParameterLength -= sizeof(Bluetooth_TempDeviceAddress); BT_DEBUG("(HCI) >> Pin code request", NULL); BT_DEBUG("(HCI) >> PIN Code Request from device %02X:%02X:%02X:%02X:%02X:%02X", Bluetooth_TempDeviceAddress[5], Bluetooth_TempDeviceAddress[4], Bluetooth_TempDeviceAddress[3], Bluetooth_TempDeviceAddress[2], Bluetooth_TempDeviceAddress[1], Bluetooth_TempDeviceAddress[0]); Bluetooth_HCIProcessingState = Bluetooth_Conn_SendPINCode; } BT_DEBUG("(HCI) -- Unread Event Param Length: %d", HCIEventHeader.ParameterLength); Bluetooth_DiscardRemainingHCIEventParameters(); } break; case Bluetooth_Conn_AcceptConnection: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST}, ParameterLength: sizeof(Bluetooth_HCICommand_AcceptConnectionRequest_Params_t), }; BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_AcceptConnection", NULL); Bluetooth_HCICommand_AcceptConnectionRequest_Params_t AcceptConnectionParams; memcpy(AcceptConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress)); AcceptConnectionParams.SlaveRole = true; Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams)); Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents; break; case Bluetooth_Conn_RejectConnection: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST}, ParameterLength: sizeof(Bluetooth_HCICommand_RejectConnectionRequest_Params_t), }; BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_RejectConnection", NULL); Bluetooth_HCICommand_RejectConnectionRequest_Params_t RejectConnectionParams; memcpy(RejectConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress)); RejectConnectionParams.Reason = ERROR_LIMITED_RESOURCES; Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams)); Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents; break; case Bluetooth_Conn_SendPINCode: HCICommandHeader = (Bluetooth_HCICommand_Header_t) { OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY}, ParameterLength: sizeof(Bluetooth_HCICommand_PinCodeResponse_Params_t), }; BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_SendPINCode", NULL); BT_DEBUG("(HCI) -- PIN: %s", Bluetooth_DeviceConfiguration.PINCode); Bluetooth_HCICommand_PinCodeResponse_Params_t PINCodeRequestParams; memcpy(PINCodeRequestParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress)); PINCodeRequestParams.PINCodeLength = strlen(Bluetooth_DeviceConfiguration.PINCode); memcpy(PINCodeRequestParams.PINCode, Bluetooth_DeviceConfiguration.PINCode, sizeof(Bluetooth_DeviceConfiguration.PINCode)); Bluetooth_SendHCICommand(&PINCodeRequestParams, sizeof(PINCodeRequestParams)); do { while (!(Bluetooth_GetNextHCIEventHeader())); Bluetooth_DiscardRemainingHCIEventParameters(); } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE); Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents; break; } }
/** 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 MSD interface descriptor containing bulk IN and OUT data endpoints. * * \return An error code from the MassStorageHost_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 mass storage interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextMassStorageInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoInterfaceFound; } /* Get the IN and OUT data endpoints for the mass storage interface */ while (FoundEndpoints != ((1 << MASS_STORE_DATA_IN_PIPE) | (1 << MASS_STORE_DATA_OUT_PIPE))) { /* Fetch the next bulk endpoint from the current mass storage interface */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextInterfaceBulkDataEndpoint) != 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 endpoint is a bulk IN or bulk OUT endpoint, set appropriate globals */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the data IN pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_IN_PIPE, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_DOUBLE); Pipe_SetInfiniteINRequests(); /* Set the flag indicating that the data IN pipe has been found */ FoundEndpoints |= (1 << MASS_STORE_DATA_IN_PIPE); } else { /* Configure the data OUT pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_OUT_PIPE, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_DOUBLE); /* Set the flag indicating that the data OUT pipe has been found */ FoundEndpoints |= (1 << MASS_STORE_DATA_OUT_PIPE); } } /* Valid data found, return success */ return SuccessfulConfigRead; }