/** 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;
}
Beispiel #2
0
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();
}
Beispiel #3
0
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();
}
Beispiel #4
0
/** 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;
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
/** 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;
	}
}
Beispiel #11
0
/** 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;
}