⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 该程序为UClinux下面的USB接口通讯程序,采用C语言编写,包含了makefile文件,使用的开发环境为华恒公司的嵌入式开发套件
💻 C
📖 第 1 页 / 共 2 页
字号:
		}
		ep[epnum].buffer.position += fifo_data;
	}
	if (event & (MCF5272_USB_EP0ISR_OUT_LVL | MCF5272_USB_EPNISR_FIFO_LVL))
	{
		/* Clear the FIFO Level Interrupt bits */
		MCF5272_WR_USB_EPISR(imm, epnum, 0
			| MCF5272_USB_EP0ISR_OUT_LVL
			| MCF5272_USB_EPNISR_FIFO_LVL);
	}
	if (event & (MCF5272_USB_EP0ISR_OUT_EOT | MCF5272_USB_EPNISR_EOT))
	{
		/* The current transfer is complete */
		/* Clear the EOT Interrupt bits */
		MCF5272_WR_USB_EPISR(imm, epnum, 0
			| MCF5272_USB_EP0ISR_OUT_EOT
			| MCF5272_USB_EPNISR_EOT);

		/* Call the Rx Handler */
		usb_ep_rx_done(epnum,SUCCESS);

		/* Free the buffer if it was malloc()ed */
		if (ep[epnum].buffer.free)
		{
			ep[epnum].buffer.free = FALSE;
			free(ep[epnum].buffer.start);
		}
		ep[epnum].buffer.length = 0;
		ep[epnum].buffer.position = 0;
		ep[epnum].buffer.start = 0;
	}
}

/********************************************************************/
void 
usb_bus_state_chg_service(uint32 event)
{
    if (event & SUSPEND)
    {
    	#if (DEBUG)
			printf("The bus is suspended (J state)\n");
		#endif
        if (event & ENABLE_WAKEUP)
        {
            #if (DEBUG)
                printf("Remote wakeup enabled.\n");
            #endif
            /* Set the Remote Wakeup flag */
            fRemoteWakeup = 1;
        }
    }
    if (event & RESUME)
    {
		#if (DEBUG)
			printf("The bus has been resumed (K state)\n");
		#endif
    }
    if (event & RESET)
    {
		#if (DEBUG)
			printf("USB reset signal detected\n");
		#endif
    }
}

/********************************************************************/
void 
usb_devcfg_service(void)
{
	static uint8 last_addr = 0;
	static uint8 last_config = 0;
	static uint32 last_altsetting = 0;
	uint8 flags, i, j, epnum;
	USB_CONFIG_DESC *pCfgDesc;
	USB_INTERFACE_DESC *pIfcDesc;
	USB_ENDPOINT_DESC *pEpDesc;
	MCF5272_IMM *imm = mcf5272_get_immp();

	flags = 0;
	if (last_addr != MCF5272_RD_USB_FAR(imm))
	{
		#if (DEBUG)
			printf("Address change:  old addr = %d, new addr = %d\n",
					last_addr, MCF5272_RD_USB_FAR(imm));
		#endif
		last_addr = MCF5272_RD_USB_FAR(imm);
		flags |= ADDRESS_CHG;
	}
	if (last_config != (MCF5272_RD_USB_EP0SR(imm) >> 12))
	{
		#if (DEBUG)
			printf("Configuration change:  old cfg = %d, new cfg = %d\n",
					last_config, MCF5272_RD_USB_EP0SR(imm) >> 12);
		#endif

		last_config = (uint8)(MCF5272_RD_USB_EP0SR(imm) >> 12);
		flags |= CONFIGURATION_CHG;
	}
	if (last_altsetting != (MCF5272_RD_USB_ASR(imm)))
	{
		#if (DEBUG)
			printf("Interface change:  old setting = %d, new setting = %d\n",
					last_altsetting, MCF5272_RD_USB_ASR(imm));
		#endif
		last_altsetting = (MCF5272_RD_USB_ASR(imm));
		flags |= INTERFACE_CHG;
	}
	if (flags & (INTERFACE_CHG | CONFIGURATION_CHG))
	{
		/* Initialize Endpoint settings for this configuration */

		/* Start by marking all Endpoints as disabled (except EP0) */
		for (i = 1; i < NUM_ENDPOINTS; i++)
			ep[i].ttype = DISABLED;

		/* Get pointer to active Configuration descriptor */
		pCfgDesc = (USB_CONFIG_DESC *)usb_get_desc(last_config, -1, -1, -1);

		/* Iterate through all the valid Interfaces in this Configuration */
		for (i = 0; i < pCfgDesc->bNumInterfaces; i++)
		{
			pIfcDesc = (USB_INTERFACE_DESC *)usb_get_desc(last_config, i, 
														AltSetting(imm, i),
														-1);
			/* Iterate through all the valid Endpoints in this interface */
			for (j = 0; j < pIfcDesc->bNumEndpoints; j++)
			{
				pEpDesc = (USB_ENDPOINT_DESC *)usb_get_desc(last_config, i, 
														  AltSetting(imm, i),
														  j);
				if (pEpDesc)
				{
					epnum = pEpDesc->bEndpointAddress & 0x0F;

					/* See if this Endpoint is actually active */
					if (!(MCF5272_RD_USB_EPISR(imm, epnum) & 
						  MCF5272_USB_EPNISR_PRES))
						return;

					/* Set the new transfer type */
					ep[epnum].ttype = pEpDesc->bmAttributes;

					/* Set the current direction */
					if (MCF5272_RD_USB_EPISR(imm, epnum) & 
						MCF5272_USB_EPNISR_DIR)
						ep[epnum].dir = IN;
					else
						ep[epnum].dir = OUT;

					/* Get the current packet size */
					ep[epnum].packet_size = (uint16)(pEpDesc->wMaxPacketSizeL +
						(pEpDesc->wMaxPacketSizeH << 8));

					/* No buffer allocated yet */
					ep[epnum].buffer.start = 0;
					ep[epnum].buffer.position = 0;
					ep[epnum].buffer.length = 0;
					ep[epnum].buffer.free = 0;

					if (ep[epnum].ttype == ISOCHRONOUS)
					{
						/* Set the FIFO length */
						ep[epnum].fifo_length = ep[epnum].packet_size;

						/* Enable ISO mode and set FIFO Level for interrupts */
						MCF5272_WR_USB_EPCTL(imm, epnum, 0
							| MCF5272_USB_EPNCTL_ISO_MODE
							| MCF5272_USB_EPNCTL_FIFO_LVL(2));

						/* Disable EOP and EOT interrupts, enable FIFO_LVL */
						MCF5272_WR_USB_EPIMR(imm, epnum, 
							(MCF5272_RD_USB_EPIMR(imm, epnum)
								& ~(MCF5272_USB_EPNISR_EOP
								| MCF5272_USB_EPNISR_EOT))
							| MCF5272_USB_EPNISR_FIFO_LVL);
					}
					else
					{
						/* Set the FIFO length */
						ep[epnum].fifo_length = \
							(uint16)(ep[epnum].packet_size * FIFO_DEPTH);

						/* Disable ISO mode and set IN-BUSY (if IN EP)*/
						if (ep[epnum].dir == IN)
						{
							/* Set the IN-BUSY bit - This is only required
							   on pre-2K75N masks. This bit is set by HW 
							   beginning with the 2K75N silicon. */
							MCF5272_WR_USB_EPCTL(imm, epnum, \
								MCF5272_USB_EPNCTL_IN_BUSY);
						}
						else
						{
							MCF5272_WR_USB_EPCTL(imm, epnum, 0);
						}

						/* Enable EOP and EOT interrupts, disable FIFO_LVL */
						MCF5272_WR_USB_EPIMR(imm, epnum,
							(MCF5272_RD_USB_EPIMR(imm, epnum)
								& ~MCF5272_USB_EPNISR_FIFO_LVL)
							| MCF5272_USB_EPNISR_EOP
							| MCF5272_USB_EPNISR_EOT);
					}
				}
			}
		}	
		usb_fifo_init();
	}
	
	/* Call application specific routine to notify of config/iface change */
	usb_devcfg_notice(flags, last_config, last_altsetting);
}

/********************************************************************/
void
usb_vendreq_done(uint32 error)
{
	MCF5272_IMM *imm = mcf5272_get_immp();

	if (error)
		/* This sends a single STALL as the handshake */
		MCF5272_WR_USB_EP0CTL(imm,
			MCF5272_RD_USB_EP0CTL(imm)
			| MCF5272_USB_EP0CTL_CMD_OVER
			| MCF5272_USB_EP0CTL_CMD_ERR);
	else
		MCF5272_WR_USB_EP0CTL(imm,
			MCF5272_RD_USB_EP0CTL(imm)
			| MCF5272_USB_EP0CTL_CMD_OVER);
	return;
}

/********************************************************************/
void
usb_sort_ep_array(USB_EP_STATE *list[], int n)
{
	/* Simple bubble sort function called by usb_fifo_init() */
	int i, pass, sorted;
	USB_EP_STATE *temp;
	pass = 1;

	do {
		sorted = 1;
		for (i = 0; i < n - pass; ++i)
		{
			if (list[i]->fifo_length < list[i+1]->fifo_length )
			{
				/* Exchange out-of-order pair */
				temp = list[i];
				list[i] = list[i + 1];
				list[i+1] = temp;
				sorted = 0;
			}
		}
		++pass;
	} while(!sorted);
}

/********************************************************************/
void
usb_make_power_of_two(uint32 *size)
{
	/* Called by usb_fifo_init() */
	int i, not_power_of_two = 0;
	uint32 new_size = *size;

	for (i = 0; new_size != 1; i++)
	{
		if (new_size & 0x0001)
			not_power_of_two = 1;
		new_size >>= 1;
	}
	new_size = 1 << (i + not_power_of_two);
	if (new_size > 256)
		new_size = 256;
	*size = new_size;
}

/********************************************************************/
void
usb_fifo_init(void)
{
	MCF5272_IMM *imm = mcf5272_get_immp();
	USB_EP_STATE *pIN[NUM_ENDPOINTS];
	USB_EP_STATE *pOUT[NUM_ENDPOINTS];
	uint8 nIN, nOUT, i;
	uint16 INpos, OUTpos;

	/* Endpoint 0 is always present and bi-directional */
	pIN[0] = &ep[0];
	pOUT[0] = &ep[0];
	nIN = nOUT = 1;

	/* Sort the active endpoints by direction */
	for (i = 1; i < NUM_ENDPOINTS; i++)
	{
		if (ep[i].ttype != DISABLED)
		{
			if (ep[i].dir == IN)
				pIN[nIN++] = &ep[i];
			else
				pOUT[nOUT++] = &ep[i];
		}
	}

	/* Make sure FIFO size is a power of 2; if not, make it so */
	for (i = 0; i < nIN; i++)
		usb_make_power_of_two( &(pIN[i]->fifo_length) );
	for (i = 0; i < nOUT; i++)
		usb_make_power_of_two( &(pOUT[i]->fifo_length) );

	/* Sort the endpoints by FIFO length (decending) */
	usb_sort_ep_array(pIN, nIN);
	usb_sort_ep_array(pOUT, nOUT);

	/* Calculate the FIFO address for each endpoint */
	INpos = 0;
	OUTpos = 0;
	for (i = 0; i < nIN; i++)
	{
		pIN[i]->in_fifo_start = INpos;
		INpos += pIN[i]->fifo_length;
	}
	for (i = 0; i < nOUT; i++)
	{
		pOUT[i]->out_fifo_start = OUTpos;
		OUTpos += pOUT[i]->fifo_length;
	}

	/* Save the FIFO settings into the Configuration Registers */
	
	/* Initialize Endpoint 0 IN FIFO */
	MCF5272_WR_USB_IEP0CFG(imm, 0
		| (ep[0].packet_size << 22)
		| (ep[0].fifo_length << 11)
		|  ep[0].in_fifo_start);

	/* Initialize Endpoint 0 OUT FIFO */
	MCF5272_WR_USB_OEP0CFG(imm, 0
		| (ep[0].packet_size << 22)
		| (ep[0].fifo_length << 11)
		|  ep[0].out_fifo_start);

	for (i = 1; i < NUM_ENDPOINTS; i++)
	{
		if (ep[i].ttype != DISABLED)
		{
			if (ep[i].dir == IN)
				/* Initialize Endpoint i FIFO */
				MCF5272_WR_USB_EPCFG(imm, i, 0
				| (ep[i].packet_size << 22)
				| (ep[i].fifo_length << 11)
				|  ep[i].in_fifo_start);
			else
				/* Initialize Endpoint i FIFO */
				MCF5272_WR_USB_EPCFG(imm, i, 0
				| (ep[i].packet_size << 22)
				| (ep[i].fifo_length << 11)
				|  ep[i].out_fifo_start);
		}
	}
}

/********************************************************************/
uint32
usb_tx_data(uint32 epnum, uint8 *start, uint16 length)
{
	MCF5272_IMM *imm = mcf5272_get_immp();
	uint32 imr_mask, i;

	/* Make sure there is data to send */
	if (!start)
		return 0;
	/* Check the bounds on epnum */
	if (epnum > NUM_ENDPOINTS)
		return 0;
	/* See if the EP is currently busy */
	if (ep[epnum].buffer.start || (epnum && MCF5272_RD_USB_EPDPR(imm, epnum)))
		return 0;
	/* Make sure this is an IN endpoint */
	if (epnum && !(MCF5272_RD_USB_EPISR(imm, epnum) & MCF5272_USB_EPNISR_DIR))
		return 0;
	/* Make sure this EP is not HALTed */
	if (MCF5272_RD_USB_EPISR(imm, epnum) & MCF5272_USB_EPNISR_HALT)
		return 0;

	/* Setup the EP Buffer structure */
	ep[epnum].buffer.start = start;
	ep[epnum].buffer.length = length;
	ep[epnum].buffer.position = 0;
	
	/* Save off the current IMR */
	imr_mask = MCF5272_RD_USB_EPIMR(imm, epnum);

	/* Clear the EOT, EOP and FIFO_LVL mask bits */
	MCF5272_WR_USB_EPIMR(imm, epnum, imr_mask & 
		~(MCF5272_USB_EPNISR_EOT
		| MCF5272_USB_EPNISR_EOP
		| MCF5272_USB_EPNISR_FIFO_LVL));

	for (i = 0; i < ep[epnum].fifo_length; )
	{
		if ( (ep[epnum].buffer.length - i) <= 3 )
		{
			MCF5272_WR_USB_EPDR(imm, epnum, 8, ep[epnum].buffer.start[i]);
			i++;
		}
		else
		{
			MCF5272_WR_USB_EPDR(imm, epnum, 32,
				*(uint32 *)(&ep[epnum].buffer.start[i]));
			i += 4;
		}
		if ( i == ep[epnum].buffer.length )
		{
			/* This is all of the data to be sent -> Clear the IN-BUSY bit */
			MCF5272_WR_USB_EPCTL(imm, epnum, MCF5272_RD_USB_EPCTL(imm, epnum)
				& ~MCF5272_USB_EPNCTL_IN_BUSY);
			break;
		}
	}
	ep[epnum].buffer.position = (uint16)i;
	MCF5272_WR_USB_EPIMR(imm, epnum, imr_mask);
	return 1;
}
/********************************************************************/
uint8*
usb_get_desc(int8 config, int8 iface, int8 setting, int8 ep)
{
	/* Note:
	 * ep is the offset and not the physical endpoint number
	 * In order to get the config desc pointer, specify -1 for 
	 * all other inputs except config
	 * In order to get the interface/alternate setting desc pointer,
	 * specify -1 for epNum
	 */
	int i;
	uint8 *pDesc = (uint8 *)&Descriptors;

	if (config != -1)
	{
		if (config > ((USB_DEVICE_DESC *)pDesc)->bNumConfigurations)
			return 0;
		
		/* Allow for non-standard desc between device and config desc */
		while (pDesc[1] != CONFIGURATION)
			pDesc += pDesc[0];	

		/* pDesc now points to Config 1 descriptor */
		for (i = 1; i < config;)
		{
			pDesc += pDesc[0];
			if (pDesc[1] == CONFIGURATION)
				i++;
		}

		/* pDesc now points to the correct Configuration descriptor */
		if ((iface != -1) && (setting != -1))
		{
			if (iface >= ((USB_CONFIG_DESC *)pDesc)->bNumInterfaces)
				return 0;

			/* Allow for non-standard desc between config and iface desc */
			while (pDesc[1] != INTERFACE)
				pDesc += pDesc[0];

			/* pDesc now points to first Interface descriptor */
			for (i = 0; i < iface;)
			{
				pDesc += pDesc[0];
				if (pDesc[1] == INTERFACE && pDesc[3] == 0)
					i++;
			}
			/* pDesc now points to correct Interface descriptor */
			for (i = 0; i < setting;)
			{
				pDesc += pDesc[0];
				if (pDesc[1] == INTERFACE)
				{
					if (pDesc[2] != iface)
						return 0;
					else
						i++;
				}
			}

			/* pDesc now points to correct Alternate Setting descriptor */
			if (ep != -1)
			{
				if (ep >= pDesc[4])
					return 0;

				/* Allow for non-standard desc between iface and ep desc */
				while (pDesc[1] != ENDPOINT)
					pDesc += pDesc[0];

				/* pDesc now points to first Endpoint descriptor */
				for (i = 0; i < ep;)
				{
					pDesc += pDesc[0];
					if (pDesc[1] == ENDPOINT)
						i++;
				}
				/* pDesc now points to the correct Endpoint descriptor */
			}
		}
	}
	return (pDesc);
}

/********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -