Esempio n. 1
0
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();
	}
}
Esempio n. 2
0
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();
	}
}
Esempio n. 3
0
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();
	}
}
Esempio n. 4
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
}
Esempio n. 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;

	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
}
Esempio n. 6
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
}
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
}
Esempio n. 8
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
}
Esempio n. 12
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 \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;
}