Exemple #1
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int eprx_recv_op(void)
{
	uint old_ep_index;
	uint this_len;
	uint fifo;

	old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);

	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);

    if (USBC_Dev_IsEpStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX))
    {
        USBC_Dev_EpClearStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);

		printf("sunxi ubs read error: usb rx ep is busy already\n");
	}
	else
    {
    	if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX))
		{
			this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
			if(fastboot_data_flag == 1)
			{
				fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);

				sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer);
				sunxi_ubuf.rx_req_buffer += this_len;

				sunxi_usb_dbg("special read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length);
				__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);		//返回状态
			}
			else if(!sunxi_ubuf.rx_ready_for_data)
			{
				fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);

				memset(sunxi_ubuf.rx_req_buffer, 0, 64);
				sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer);
				sunxi_ubuf.rx_ready_for_data = 1;

				sunxi_usb_dbg("read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length);
				__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);		//返回状态
			}
			else
			{
				sunxi_usb_dbg("eprx do nothing and left it to dma\n");
			}
		}
		else
		{
			sunxi_usb_dbg("sunxi usb rxdata not ready\n");
		}
    }

	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index);

	return 0;
}
/*
*******************************************************************************
*                     fastboot_tx_status
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_write_fifo(uchar *buffer, unsigned int buffer_size)
{
    u32 old_ep_idx = 0;
    u32 fifo = 0;
	u32 transfered = 0;
    u32 left = 0;
    u32 this_len;

    /* Save index */
	old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_IN_EP_INDEX);

    left = buffer_size;
	fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_IN_EP_INDEX);

    while(left)
   	{
    	this_len = MIN(sunxi_udc_source.fifo_size, left);
        this_len = USBC_WritePacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer + transfered);

		transfered += this_len;
        left -= this_len;

        __usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, 1);
    }

    USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);

    return 0;
}
/*
*******************************************************************************
*                     __usb_read_ep0_data
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_read_ep0_data(void *buffer, uint data_type)
{
	u32 fifo_count  = 0;
	u32 fifo        = 0;
	int ret = 0;
   	u32 old_ep_index  = 0;

	old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
 	fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX);
    fifo_count = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
    if(!data_type)
    {
    	if(fifo_count != 8 )
    	{
    		printf("err: ep0 fifo_count %d is not 8\n", fifo_count);

    		return -1;
    	}
    }
	USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, fifo_count, (void *)buffer);
	__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index);

	return ret;
}
Exemple #4
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static void __usb_recv_by_dma_isr(void *p_arg)
{
	u32 old_ep_idx;

	old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);			//选择RXEP

	//选择使用IO方式搬运数据
	sunxi_usb_dbg("select io mode to transfer data\n");
	USBC_Dev_ClearEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);

	if(usb_dma_trans_unaliged_bytes)
	{
		uint fifo, this_len;

		this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
		fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);
		USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, usb_dma_trans_unaligned_buf);
		__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);		//返回状态
		usb_dma_trans_unaliged_bytes = 0;
	}
	//如果当前dma传输的不是完整包,则需要手动清除中断
	if(sunxi_ubuf.request_size % sunxi_udc_source.bulk_ep_max)
	{
		USBC_Dev_ReadDataStatus(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);
		//printf("clear rx pending manually\n");
	}

	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);

	sunxi_udev_active->dma_rx_isr(p_arg);
}
static int __usb_read_fifo(void *buffer, unsigned int buffer_size)
{
    u32 old_ep_idx = 0;
    u32 fifo = 0;
	u32 transfered = 0;
    u32 left = 0;
    u32 this_len;

	old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);			//选择当前EP

	fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);		//选择fifo

	left = buffer_size;

	if(left)
	{
		while(left)
		{
			if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX))
			{
				this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
				this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer + transfered);

				transfered += this_len;
	        	left -= this_len;

	        	__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);		//返回状态
			}
		}
		USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, SUNXI_USB_BULK_OUT_EP_INDEX);
	}
	else
	{
		if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX))
		{
			this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
			this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer);

			transfered = this_len;
			__usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1);		//返回状态
		}
		else
		{
			sunxi_usb_dbg("sunxi usb rxdata not ready\n");
		}
	}

	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);

	sunxi_usb_dbg("read bytes 0x%x\n", transfered);

	return transfered;
}
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
void sunxi_udc_send_setup(uint bLength, void *buffer)
{
	u32 fifo = 0;

	if(!bLength)
	{
		/* sent zero packet */
		__usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1);
	}
	else
	{
		fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX);
		USBC_WritePacket(sunxi_udc_source.usbc_hd, fifo, bLength, (void *)buffer);
		__usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1);
	}
}
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_udc_start_recv_by_dma(uint mem_buf, uint length)
{
	uint old_ep_idx;
	uint fifo;

	old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);			//选择当前EP
	//usb控制器选择dma传输方式
	USBC_Dev_ConfigEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
	//选择buffer
	fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX);
	//刷掉cache
	flush_cache(mem_buf, length);
	//使能dma传输
	sunxi_ubuf.request_size = length;
	sunxi_usb_dbg("dma start\n");
	sunxi_dma_start(sunxi_udc_source.dma_recv_channal, fifo, mem_buf, length);
	//恢复EP
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);			//恢复原有EP

	return 0;
}
/*
*******************************************************************************
*                     read_request
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int read_request(struct usb_device_request *req)
{
	u32 fifo_count  = 0;
	u32 fifo        = 0;
	int ret = FASTBOOT_OK;
	u8 old_ep_index = 0;

	old_ep_index = USBC_GetActiveEp(udc.bsp);
	USBC_SelectActiveEp(udc.bsp, CTRL_EP_INDEX);

 	fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX);
    fifo_count = USBC_ReadLenFromFifo(udc.bsp, USBC_EP_TYPE_EP0);
    if(fifo_count != 8 ){
    	DMSG_PANIC("err: ep0 fifo_count is not 8\n", fifo_count);
    	return FASTBOOT_ERROR;
    }

	USBC_ReadPacket(udc.bsp, fifo, fifo_count, (void *)req);
	ReadDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 0);

	USBC_SelectActiveEp(udc.bsp, old_ep_index);

	return ret;
}
/*
*******************************************************************************
*                     do_usb_req_get_descriptor
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int do_usb_req_get_descriptor(void)
{
	int ret  = FASTBOOT_OK;
	u32 fifo = 0;

	if(0 == udc.req.wLength){
		DMSG_PANIC("wrn: req.wLength is zero\n");
		return FASTBOOT_OK;
	}

	if(udc.req.bmRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)){
		DMSG_PANIC("err: invalid bmRequestType, (0, %d), (0, %d)\n", udc.req.bmRequestType);
		return FASTBOOT_ERROR;
	}

	switch(udc.req.wValue >> 8){
		case USB_DT_DEVICE:
		{
			struct usb_device_descriptor d;

			memset(&d, 0, sizeof(struct usb_device_descriptor));

			d.bLength = MIN(udc.req.wLength, sizeof (d));
			d.bDescriptorType    = USB_DT_DEVICE;
#ifdef CONFIG_USB_1_1_DEVICE
			d.bcdUSB             = 0x110;
#else
			d.bcdUSB             = 0x200;
#endif
			d.bDeviceClass       = 0xff;
			d.bDeviceSubClass    = 0xff;
			d.bDeviceProtocol    = 0xff;
			d.bMaxPacketSize0    = 0x40;
			d.idVendor           = DEVICE_VENDOR_ID;
			d.idProduct          = DEVICE_PRODUCT_ID;
			d.bcdDevice          = DEVICE_BCD;
			d.iManufacturer      = DEVICE_STRING_MANUFACTURER_INDEX;
			d.iProduct           = DEVICE_STRING_PRODUCT_INDEX;
			d.iSerialNumber      = DEVICE_STRING_SERIAL_NUMBER_INDEX;
			d.bNumConfigurations = 1;

			fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX);

            memcpy(fastboot_fifo_ep0, &d, d.bLength);
			USBC_WritePacket(udc.bsp, fifo, d.bLength, (void *)fastboot_fifo_ep0);

			WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1);
		}
		break;

		case USB_DT_CONFIG:
		{
			struct usb_configuration_descriptor c;
			struct usb_interface_descriptor i;
			struct usb_endpoint_descriptor ep_in, ep_out;
			unsigned char bytes_remaining = udc.req.wLength;
			unsigned char bytes_total = 0;

			memset(&c, 0, sizeof(struct usb_configuration_descriptor));
			memset(&i, 0, sizeof(struct usb_interface_descriptor));
			memset(&ep_in, 0, sizeof(struct usb_endpoint_descriptor));
			memset(&ep_out, 0, sizeof(struct usb_endpoint_descriptor));
			memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE));

			/* configuration */
			c.bLength            	= MIN(bytes_remaining, sizeof (c));
			c.bDescriptorType    	= USB_DT_CONFIG;
			c.wTotalLength 			= sizeof (c) + sizeof (i) + sizeof (ep_in) + sizeof (ep_out);
			c.bNumInterfaces     	= 1;
			c.bConfigurationValue	= CONFIGURATION_NORMAL;
			c.iConfiguration     	= DEVICE_STRING_CONFIG_INDEX;
			c.bmAttributes       	= 0xc0;
			c.bMaxPower          	= 0x32;

			bytes_remaining -= c.bLength;
			memcpy (&fastboot_fifo_ep0[0], &c, c.bLength);
			bytes_total += c.bLength;

			/* interface */
			i.bLength             = MIN (bytes_remaining, sizeof(i));
			i.bDescriptorType     = USB_DT_INTERFACE;
			i.bInterfaceNumber    = 0x00;
			i.bAlternateSetting   = 0x00;
			i.bNumEndpoints       = 0x02;
			i.bInterfaceClass     = FASTBOOT_INTERFACE_CLASS;
			i.bInterfaceSubClass  = FASTBOOT_INTERFACE_SUB_CLASS;
			i.bInterfaceProtocol  = FASTBOOT_INTERFACE_PROTOCOL;
			i.iInterface          = DEVICE_STRING_INTERFACE_INDEX;

			bytes_remaining -= i.bLength;
			memcpy (&fastboot_fifo_ep0[bytes_total], &i, i.bLength);
			bytes_total += i.bLength;

			/* ep_in */
			ep_in.bLength            = MIN (bytes_remaining, sizeof (ep_in));
			ep_in.bDescriptorType    = USB_DT_ENDPOINT;
			ep_in.bEndpointAddress   = 0x80 | BULK_IN_EP_INDEX; /* IN */
			ep_in.bmAttributes       = USB_ENDPOINT_XFER_BULK;
			if(fastboot_is_highspeed()){
				ep_in.wMaxPacketSize = HIGH_SPEED_EP_MAX_PACKET_SIZE;
			}else{
				ep_in.wMaxPacketSize = FULL_SPEED_EP_MAX_PACKET_SIZE;
			}
			ep_in.bInterval          = 0x00;

			bytes_remaining -= ep_in.bLength;
			memcpy (&fastboot_fifo_ep0[bytes_total], &ep_in, ep_in.bLength);
			bytes_total += ep_in.bLength;

			/* ep_out */
			ep_out.bLength            = MIN (bytes_remaining, sizeof (ep_out));
			ep_out.bDescriptorType    = USB_DT_ENDPOINT;
			ep_out.bEndpointAddress   = BULK_OUT_EP_INDEX; /* OUT */
			ep_out.bmAttributes       = USB_ENDPOINT_XFER_BULK;
			if(fastboot_is_highspeed()){
				ep_out.wMaxPacketSize = HIGH_SPEED_EP_MAX_PACKET_SIZE;
			}else{
				ep_out.wMaxPacketSize = FULL_SPEED_EP_MAX_PACKET_SIZE;
			}
			ep_out.bInterval          = 0x00;

			bytes_remaining -= ep_out.bLength;
			memcpy (&fastboot_fifo_ep0[bytes_total], &ep_out, ep_out.bLength);
			bytes_total += ep_out.bLength;

			fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX);
			USBC_WritePacket(udc.bsp, fifo, bytes_total, (void *)fastboot_fifo_ep0);
			WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1);
		}
		break;

		case USB_DT_STRING:
		{
			unsigned char bLength = 0;
			unsigned char string_index = udc.req.wValue & 0xff;

			if(string_index > DEVICE_STRING_MAX_INDEX){
				/* Windows XP asks for an invalid string index.
				   Fail silently instead of doing

				   NAK_REQ();
				*/
			}else if(0 == string_index){
				/* Language ID */
				bLength = MIN(4, udc.req.wLength);

				memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE));
				fastboot_fifo_ep0[0] = bLength;        /* length */
				fastboot_fifo_ep0[1] = USB_DT_STRING;  /* descriptor = string */
				fastboot_fifo_ep0[2] = DEVICE_STRING_LANGUAGE_ID & 0xff;
				fastboot_fifo_ep0[3] = DEVICE_STRING_LANGUAGE_ID >> 8;

				fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX);
				USBC_WritePacket(udc.bsp, fifo, bLength, (void *)fastboot_fifo_ep0);
				WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1);
			}else{
				/* Size of string in chars */
				unsigned char s = 0;
				unsigned char sl = strlen (&device_strings[string_index][0]);
				unsigned char bLength = 2 + (2 * sl);

				bLength = MIN(bLength, udc.req.wLength);

				memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE));

				fastboot_fifo_ep0[0] = bLength;        /* length */
				fastboot_fifo_ep0[1] = USB_DT_STRING;  /* descriptor = string */

				/* Copy device string to fifo, expand to simple unicode */
				for(s = 0; s < sl; s++){
					fastboot_fifo_ep0[2+ 2*s + 0] = device_strings[string_index][s];
					fastboot_fifo_ep0[2+ 2*s + 1] = 0;
				}

				fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX);
				USBC_WritePacket(udc.bsp, fifo, bLength, (void *)fastboot_fifo_ep0);
				WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1);
			}
		}