Ejemplo n.º 1
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int sunxi_pburn_init(void)
{
	sunxi_usb_dbg("sunxi_pburn_init\n");
	memset(&trans_data, 0, sizeof(pburn_trans_set_t));
	sunxi_usb_pburn_write_enable = 0;
    sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE;

    trans_data.base_recv_buffer = (u8 *)malloc(SUNXI_PBURN_RECV_MEM_SIZE);
    if(!trans_data.base_recv_buffer)
    {
    	printf("sunxi usb pburn err: unable to malloc memory for pburn receive\n");

    	return -1;
    }

	trans_data.base_send_buffer = (u8 *)malloc(SUNXI_PBURN_SEND_MEM_SIZE);
    if(!trans_data.base_send_buffer)
    {
    	printf("sunxi usb pburn err: unable to malloc memory for pburn send\n");
    	free(trans_data.base_recv_buffer);

    	return -1;
    }
	sunxi_usb_dbg("recv addr 0x%x\n", (uint)trans_data.base_recv_buffer);
    sunxi_usb_dbg("send addr 0x%x\n", (uint)trans_data.base_send_buffer);

    return 0;
}
Ejemplo n.º 2
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_udc_set_address(uchar address)
{
	__u32 speed_mode;

	/*Config New Address*/
	SUSB_Dev_SetAddress(address);

    speed_mode = SUSB_Get_Speed_Mode();
    if(speed_mode== 0x4)
    {
  	    sunxi_udc_source.speed = USB_SPEED_SUPER;
		sunxi_usb_dbg("usb speed: SS\n");
    }
    else if(speed_mode == 0x0)
    {
  	    sunxi_udc_source.speed = USB_SPEED_HIGH;
		sunxi_usb_dbg("usb speed: HIGH\n");
    }
	else
	{
	    sunxi_udc_source.speed = USB_SPEED_FULL;
		sunxi_usb_dbg("usb speed: FULL\n");
	}

	//__ep0_send_zero_package();
    ep0_zero_package_flag = 1;

	return SUNXI_USB_REQ_SUCCESSED;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static void __endpoint_interrupt(__u32 event_context)
{
	switch(((event_context>>6)&0x0f))
	{
		case SUSB_DEPEVT_XFERCOMPLETE:
			if(((event_context>>1)&0x1f)==0)//ep0 out
			{
				sunxi_usb_dbg("ep0 out complete\n");
			 	__ep0_complete_out();
			}
			else if(((event_context>>1)&0x1f)==1)//ep0 in
			{
				sunxi_usb_dbg("ep0 in complete\n");
			 	__ep0_complete_in();
			}
			else if(((event_context>>1)&0x1f) == (usb_mem_cfg.phy_out_ep&0x1f))//epx out
Ejemplo n.º 6
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int sunxi_pburn_nonstandard_req_op(uint cmd, struct usb_device_request *req, uchar *buffer, uint data_status)
{
	int ret = SUNXI_USB_REQ_SUCCESSED;

	switch(req->bmRequestType)		//PBURN 特有请求
	{
		case 161:
			if(req->bRequest == 0xFE)
			{
				sunxi_usb_dbg("pburn ask for max lun\n");

				buffer[0] = 0;

				sunxi_udc_send_setup(1, buffer);
			}
			else
			{
				printf("sunxi usb err: unknown ep0 req in pburn\n");

				ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED;
			}
			break;

		default:
			printf("sunxi usb err: unknown non standard ep0 req\n");

			ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED;

			break;
	}

	return ret;
}
Ejemplo n.º 7
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static void  sunxi_pburn_usb_tx_dma_isr(void *p_arg)
{
	sunxi_usb_dbg("dma int for usb tx occur\n");
#if defined(SUNXI_USB_30)
	sunxi_usb_pburn_status_enable = 1;
#endif
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int __eps_complete_out(void)
{
	pSUSBTRB cbw_trb;

	cbw_trb = (pSUSBTRB)&usb_mem_cfg.pSDEVTRBx[0];

	if(sunxi_udc_source.eps_bulk_step == SUNXI_USB_BULK_CBW_BEGIN)
	{
		sunxi_udc_source.eps_bulk_step = SUNXI_USB_BULK_CBW_OK;
		sunxi_ubuf.rx_ready_for_data = 1;
		sunxi_ubuf.rx_req_length = 0x200 - (cbw_trb->size & 0x00ffffff);
		sunxi_usb_dbg("sunxi_ubuf.rx_req_length=0x%x\n", sunxi_ubuf.rx_req_length);
		if(fastboot_data_flag)
		{
			sunxi_ubuf.rx_req_buffer += sunxi_ubuf.rx_req_length;
			sunxi_udc_source.eps_bulk_step = SUNXI_USB_BULK_PREPARE;
		}
	}
	else if(sunxi_udc_source.eps_bulk_step == SUNXI_USB_BULK_CBW_OK)
	{
		sunxi_udev_active->dma_rx_isr(NULL);
	}

	return 0;
}
Ejemplo n.º 10
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_udc_set_address(uchar address)
{
	USBC_Dev_SetAddress(sunxi_udc_source.usbc_hd, address);
	if(USBC_Dev_QueryTransferMode(sunxi_udc_source.usbc_hd) == USBC_TS_MODE_HS)
	{
		sunxi_udc_source.speed = USB_SPEED_HIGH;
		sunxi_udc_source.fifo_size = HIGH_SPEED_EP_MAX_PACKET_SIZE;
		sunxi_usb_dbg("usb speed: HIGH\n");
	}
	else
	{
		sunxi_udc_source.speed = USB_SPEED_FULL;
		sunxi_udc_source.fifo_size = FULL_SPEED_EP_MAX_PACKET_SIZE;
		sunxi_usb_dbg("usb speed: FULL\n");
	}

	return SUNXI_USB_REQ_SUCCESSED;
}
Ejemplo n.º 11
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int sunxi_pburn_exit(void)
{
	sunxi_usb_dbg("sunxi_pburn_exit\n");
    if(trans_data.base_recv_buffer)
    {
    	free(trans_data.base_recv_buffer);
    }
    if(trans_data.base_send_buffer)
    {
    	free(trans_data.base_send_buffer);
    }

    return 0;
}
Ejemplo n.º 12
0
/*
*******************************************************************************
*                     do_usb_req_set_interface
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_set_interface(struct usb_device_request *req)
{
	sunxi_usb_dbg("set interface\n");
	/* Only support interface 0, alternate 0 */
	if((0 == req->wIndex) && (0 == req->wValue))
	{
		sunxi_udc_ep_reset();
	}
	else
	{
		printf("err: invalid wIndex and wValue, (0, %d), (0, %d)\n", req->wIndex, req->wValue);
		return SUNXI_USB_REQ_OP_ERR;
	}

	return SUNXI_USB_REQ_SUCCESSED;
}
Ejemplo n.º 13
0
/*
*******************************************************************************
*                     do_usb_req_set_configuration
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_set_configuration(struct usb_device_request *req)
{
	sunxi_usb_dbg("set configuration\n");
	/* Only support 1 configuration so nak anything else */
	if (1 == req->wValue)
	{
		sunxi_udc_ep_reset();
	}
	else
	{
		printf("err: invalid wValue, (0, %d)\n", req->wValue);

		return SUNXI_USB_REQ_OP_ERR;
	}

	sunxi_udc_set_configuration(req->wValue);

	return SUNXI_USB_REQ_SUCCESSED;
}
Ejemplo n.º 14
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
	//如果当前dma传输的不是完整包,则需要手动清除中断
	//printf("sunxi_ubuf.request_size=0x%x\n",sunxi_ubuf.request_size);
	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");
	}
	//选择使用IO方式搬运数据
	sunxi_usb_dbg("select io mode to transfer data\n");
	USBC_Dev_ClearEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);

	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);

	sunxi_udev_active->dma_rx_isr(p_arg);
}
Ejemplo n.º 15
0
/*
************************************************************************************************************
*
*                                             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;
}
Ejemplo n.º 16
0
/*
*******************************************************************************
*                     __usb_get_status
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_get_status(struct usb_device_request *req, uchar *buffer)
{
	unsigned char bLength = 0;

	sunxi_usb_dbg("get status\n");
	if(0 == req->wLength)
	{
		/* sent zero packet */
		sunxi_udc_send_setup(0, NULL);

		return SUNXI_USB_REQ_OP_ERR;
	}

	bLength = MIN(req->wValue, 2);

	buffer[0] = 1;
	buffer[1] = 0;

	sunxi_udc_send_setup(bLength, buffer);

	return SUNXI_USB_REQ_SUCCESSED;
}
Ejemplo n.º 17
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_udc_start_recv_by_dma(uint mem_buf, uint length)
{
	uint old_ep_idx;

	usb_dma_trans_unaliged_bytes = length & (sizeof(int) - 1);
	length &= ~(sizeof(int) - 1);
	usb_dma_trans_unaligned_buf = (uchar *)mem_buf + length;

	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);

	//刷掉cache
	flush_cache(mem_buf, length);
	//使能dma传输
	sunxi_ubuf.request_size = length;
	sunxi_usb_dbg("dma start 0x%x, length 0x%x\n", mem_buf, length);
	usb_dma_start(sunxi_udc_source.dma_recv_channal, mem_buf, length);
	//恢复EP
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);			//恢复原有EP

	return 0;
}
Ejemplo n.º 18
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
void sunxi_usb_irq(void *data)
{
	u8 misc_irq = 0;
	u16 tx_irq = 0;
	u16 rx_irq = 0;
    u32 old_ep_idx  = 0;

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

    /* Read status registers */
	misc_irq = USBC_INT_MiscPending(sunxi_udc_source.usbc_hd);
	tx_irq  = USBC_INT_EpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX);
	rx_irq  = USBC_INT_EpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);

	/* RESET */
	if(misc_irq & USBC_INTUSB_RESET)
	{
	    sunxi_usb_dbg("IRQ: reset\n");

	    USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_RESET);
        __usb_clear_all_irq();

        USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, 0);
		USBC_Dev_SetAddress_default(sunxi_udc_source.usbc_hd);

		sunxi_udc_source.address = 0;					//default value
		sunxi_udc_source.speed = USB_SPEED_HIGH;		//default value

		sunxi_dma_stop(sunxi_udc_source.dma_recv_channal);
		sunxi_dma_stop(sunxi_udc_source.dma_send_channal);

		sunxi_ubuf.rx_ready_for_data = 0;
		sunxi_udev_active->state_reset();

		return ;
    }

	/* RESUME 暂时不处理,仅仅清理中断*/
	if (misc_irq & USBC_INTUSB_RESUME)
	{
		sunxi_usb_dbg("IRQ: resume\n");
		/* clear interrupt */
		USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_RESUME);
	}

	/* SUSPEND */
	if (misc_irq & USBC_INTUSB_SUSPEND)
	{
		sunxi_usb_dbg("IRQ: suspend\n");
		/* clear interrupt */
		USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND);
	}

    /* DISCONNECT */
    if(misc_irq & USBC_INTUSB_DISCONNECT)
    {
        sunxi_usb_dbg("IRQ: disconnect\n");

		USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_DISCONNECT);

        return ;
	}
#if 0
	/* SOF */
	if(misc_irq & USBC_INTUSB_SOF)
	{
	    sunxi_usb_dbg("IRQ: SOF\n");

		USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_SOF);
	}
#endif
	/* ep0 */
	if (tx_irq & (1 << SUNXI_USB_CTRL_EP_INDEX) )
	{
		sunxi_usb_dbg("IRQ: EP0\n");

		USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX);
		//中断内完成ep0处理
		ep0_recv_op();
    }

	/* tx endpoint data transfers */
	if (tx_irq & (1 << SUNXI_USB_BULK_IN_EP_INDEX))
	{
		sunxi_usb_dbg("tx irq occur\n");
		/* Clear the interrupt bit by setting it to 1 */
		USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_BULK_IN_EP_INDEX);

		eptx_send_op();
	}
	/* rx endpoint data transfers */
	if (rx_irq & (1 << SUNXI_USB_BULK_OUT_EP_INDEX))
	{
		sunxi_usb_dbg("rx irq occur\n");
		/* Clear the interrupt bit by setting it to 1 */
		USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, SUNXI_USB_BULK_OUT_EP_INDEX);

		eprx_recv_op();
	}

    USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx);

    return ;
}
Ejemplo n.º 19
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static void  sunxi_pburn_usb_rx_dma_isr(void *p_arg)
{
	sunxi_usb_dbg("dma int for usb rx occur\n");
	//通知主循环,可以写入数据
	sunxi_usb_pburn_write_enable = 1;
}
Ejemplo n.º 20
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :   usb初始化动作,完成后,即可开启中断后,使用中断处理程序
*
*
************************************************************************************************************
*/
int sunxi_usb_init(int delaytime)
{
	sunxi_dma_setting_t  usb_send_by_dma;
	sunxi_dma_setting_t  usb_recv_by_dma;

	if(sunxi_udev_active->state_init())
	{
		printf("sunxi usb err: fail to init usb device\n");

		return -1;
	}
	//预先关闭usb中断
	irq_disable(AW_IRQ_USB_OTG);
	//初始化 sunxi_udc用到的资源
    memset(&sunxi_udc_source, 0, sizeof(sunxi_udc_t));
	//获取控制器地址资源
    sunxi_udc_source.usbc_hd = USBC_open_otg(0);
	if(sunxi_udc_source.usbc_hd == 0)
	{
		printf("sunxi usb err : USBC_open_otg failed\n");

		return -1;
	}
	//断开usb
	USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF);
	//预先关闭usb时钟
	usb_close_clock();
	//延时 delaytime  ms
	printf("delay time %d\n", delaytime);
	__msdelay(delaytime);
	//申请DMA资源
	sunxi_udc_source.dma_send_channal = sunxi_dma_request(0);
	if(!sunxi_udc_source.dma_send_channal)
	{
		printf("sunxi usb err : unable to request dma for usb send data\n");

		goto __sunxi_usb_init_fail;
	}
	sunxi_udc_source.dma_recv_channal = sunxi_dma_request(0);
	if(!sunxi_udc_source.dma_recv_channal)
	{
		printf("sunxi usb err : unable to request dma for usb receive data\n");

		goto __sunxi_usb_init_fail;
	}
	//配置dma资源
	usb_recv_by_dma.loop_mode = 0;
	usb_recv_by_dma.wait_cyc  = 8;
	usb_recv_by_dma.data_block_size = 1 * 32/8;
	//config recv(from usb fifo to dram)
	usb_recv_by_dma.cfg.src_drq_type     = DMAC_CFG_SRC_TYPE_OTG_EP2;  //OTG EP2
	usb_recv_by_dma.cfg.src_addr_mode    = DMAC_CFG_SRC_ADDR_TYPE_IO_MODE;
	usb_recv_by_dma.cfg.src_burst_length = DMAC_CFG_SRC_1_BURST;
	usb_recv_by_dma.cfg.src_data_width   = DMAC_CFG_SRC_DATA_WIDTH_32BIT;
	usb_recv_by_dma.cfg.reserved0        = 0;

	usb_recv_by_dma.cfg.dst_drq_type     = DMAC_CFG_DEST_TYPE_DRAM;  //DRAM
	usb_recv_by_dma.cfg.dst_addr_mode    = DMAC_CFG_DEST_ADDR_TYPE_LINEAR_MODE;
	usb_recv_by_dma.cfg.dst_burst_length = DMAC_CFG_DEST_1_BURST;
	usb_recv_by_dma.cfg.dst_data_width   = DMAC_CFG_DEST_DATA_WIDTH_32BIT;
	usb_recv_by_dma.cfg.reserved1        = 0;

	//注册dma中断函数
	sunxi_usb_dbg("install dma isr\n");
	sunxi_dma_install_int(sunxi_udc_source.dma_recv_channal, __usb_recv_by_dma_isr, 0);
	//sunxi_dma_install_int(sunxi_udc_source.dma_recv_channal, __usb_recv_by_dma_isr, 0);
	//使能dma中断
	sunxi_usb_dbg("enable dma isr\n");
	sunxi_dma_enable_int(sunxi_udc_source.dma_recv_channal);

	//配置dma资源
	usb_send_by_dma.loop_mode = 0;
	usb_send_by_dma.wait_cyc  = 8;
	usb_send_by_dma.data_block_size = 1 * 32/8;
	//usb_send_by_dma.
	//config send(from dram to usb fifo)
	usb_send_by_dma.cfg.src_drq_type     = DMAC_CFG_SRC_TYPE_DRAM;  //OTG, EP2
	usb_send_by_dma.cfg.src_addr_mode    = DMAC_CFG_SRC_ADDR_TYPE_LINEAR_MODE;
	usb_send_by_dma.cfg.src_burst_length = DMAC_CFG_SRC_1_BURST;
	usb_send_by_dma.cfg.src_data_width   = DMAC_CFG_SRC_DATA_WIDTH_32BIT;
	usb_send_by_dma.cfg.reserved0        = 0;

	usb_send_by_dma.cfg.dst_drq_type     = DMAC_CFG_DEST_TYPE_OTG_EP1;  //OTG EP1
	usb_send_by_dma.cfg.dst_addr_mode    = DMAC_CFG_DEST_ADDR_TYPE_IO_MODE;
	usb_send_by_dma.cfg.dst_burst_length = DMAC_CFG_DEST_1_BURST;
	usb_send_by_dma.cfg.dst_data_width   = DMAC_CFG_DEST_DATA_WIDTH_32BIT;
	usb_send_by_dma.cfg.reserved1        = 0;

	sunxi_dma_setting(sunxi_udc_source.dma_recv_channal, &usb_recv_by_dma);
	sunxi_dma_setting(sunxi_udc_source.dma_send_channal, &usb_send_by_dma);
	//假定usb运行在高速模式下
	sunxi_udc_source.address = 0;
	sunxi_udc_source.speed = USB_SPEED_HIGH;
	sunxi_udc_source.bulk_ep_max = HIGH_SPEED_EP_MAX_PACKET_SIZE;
	sunxi_udc_source.fifo_size    = BULK_FIFOSIZE;
	sunxi_udc_source.bulk_in_addr = 100;
	sunxi_udc_source.bulk_out_addr = sunxi_udc_source.bulk_in_addr + sunxi_udc_source.fifo_size * 2;

	memset(&sunxi_ubuf, 0, sizeof(sunxi_ubuf_t));

	sunxi_ubuf.rx_base_buffer = (uchar *)malloc(1024);
	if(!sunxi_ubuf.rx_base_buffer)
	{
		printf("sunxi usb err: fail to malloc memory for rx command buffer\n");

		goto __sunxi_usb_init_fail;
	}
	sunxi_ubuf.rx_req_buffer = sunxi_ubuf.rx_base_buffer;

	usb_open_clock();
	//设置为device模式
    USBC_ForceId(sunxi_udc_source.usbc_hd, USBC_ID_TYPE_DEVICE);
	//设置VBUS为高
	USBC_ForceVbusValid(sunxi_udc_source.usbc_hd, USBC_VBUS_TYPE_HIGH);

    USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF);
	//soft connect
    USBC_EnableDpDmPullUp(sunxi_udc_source.usbc_hd);
    USBC_EnableIdPullUp(sunxi_udc_source.usbc_hd);
    //选择使用PIO模式搬移数据
    USBC_SelectBus(sunxi_udc_source.usbc_hd, USBC_IO_TYPE_PIO, 0, 0);
    //映射SRAM buffer
    USBC_ConfigFIFO_Base(sunxi_udc_source.usbc_hd, 0, 0);
	//
    USBC_EnhanceSignal(sunxi_udc_source.usbc_hd);
	//默认采用高速模式传输
#ifdef	CONFIG_USB_1_1_DEVICE
	USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_FS);
#else
	USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_HS);
#endif
    /* disable all interrupt */
    USBC_INT_DisableUsbMiscAll(sunxi_udc_source.usbc_hd);
    USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
    USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX);

    /* 开启 reset、resume、suspend中断 */
	USBC_INT_EnableUsbMiscUint(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND | USBC_INTUSB_RESUME	\
													   | USBC_INTUSB_RESET);

    /* enbale ep0_tx_irq */
	USBC_INT_EnableEp(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX);

    __usb_bulk_ep_reset();

    USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_ON);

	irq_install_handler(AW_IRQ_USB_OTG, sunxi_usb_irq, NULL);
	irq_enable(AW_IRQ_USB_OTG);

	return 0;

__sunxi_usb_init_fail:
	if(sunxi_udc_source.usbc_hd)
	{
		USBC_close_otg(sunxi_udc_source.usbc_hd);
	}

	if(sunxi_udc_source.dma_send_channal)
	{
		sunxi_dma_release(sunxi_udc_source.dma_send_channal);
	}
	if(sunxi_udc_source.dma_recv_channal)
	{
		sunxi_dma_release(sunxi_udc_source.dma_recv_channal);
	}

	if(sunxi_ubuf.rx_base_buffer)
	{
		free(sunxi_ubuf.rx_base_buffer);
	}

	return -1;
}
Ejemplo n.º 21
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int ep0_recv_op(void)
{
   	u32 old_ep_index  = 0;
   	int ret = 0;
   	static uint ep0_stage = 0;

	if(!ep0_stage)
	{
		memset(&sunxi_udc_source.standard_reg, 0, sizeof(struct usb_device_request));
	}

	old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd);
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX);
    //clear stall status
    if(USBC_Dev_IsEpStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0))
    {
       	printf("ERR: handle_ep0: ep0 stall\n");

		USBC_Dev_EpClearStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
        ret = -1;

        goto __ep0_recv_op_err;
    }

    //clear setup end
	if (USBC_Dev_Ctrl_IsSetupEnd(sunxi_udc_source.usbc_hd))
	{
   	    USBC_Dev_Ctrl_ClearSetupEnd(sunxi_udc_source.usbc_hd);
	}
	//检查读ep0数据是否完成
	if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0))
	{
		uint status;

		if(!ep0_stage)
		{
			status = __usb_read_ep0_data(&sunxi_udc_source.standard_reg, ep0_stage);
		}
		else
		{
			status = __usb_read_ep0_data(sunxi_usb_ep0_buffer, ep0_stage);
		}
		if(status!= 0)
		{
			printf("sunxi usb err: read_request failed\n");
			ret = -1;

			goto __ep0_recv_op_err;
		}
	}
	else		//此情况通常由于ep0发送空包引起,可以不处理
	{
		sunxi_usb_dbg("sunxi usb msg: ep0 rx data is not ready\n");

		goto __ep0_recv_op_err;
	}
	/* Check data */
	if(USB_REQ_TYPE_STANDARD == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_TYPE_MASK))
	{
		ret = SUNXI_USB_REQ_UNMATCHED_COMMAND;

		/* standard */
		switch(sunxi_udc_source.standard_reg.bRequest)
		{
			case USB_REQ_GET_STATUS:		//   0x00
			{
				/* device-to-host */
				if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_STATUS, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer);
				}

				break;
			}
			case USB_REQ_CLEAR_FEATURE:		//   0x01
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					ret = sunxi_udev_active->standard_req_op(USB_REQ_CLEAR_FEATURE, &sunxi_udc_source.standard_reg, NULL);
				}

				break;
			}
			case USB_REQ_SET_FEATURE:		//   0x03
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_FEATURE, &sunxi_udc_source.standard_reg, NULL);
				}

				break;
			}
			case USB_REQ_SET_ADDRESS:		//   0x05
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						/* receiver is device */
						ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_ADDRESS, &sunxi_udc_source.standard_reg, NULL);
					}
				}

				break;
			}
			case USB_REQ_GET_DESCRIPTOR:		//   0x06
			{
				/* device-to-host */
				if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_DESCRIPTOR, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer);
					}
				}

				break;
			}
			case USB_REQ_SET_DESCRIPTOR:		//   0x07
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						//there is some problem
						ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_DESCRIPTOR, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer);
					}
				}

				break;
			}
			case USB_REQ_GET_CONFIGURATION:		//   0x08
			{
				/* device-to-host */
				if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_CONFIGURATION, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer);
					}
				}

				break;
			}
			case USB_REQ_SET_CONFIGURATION:		//   0x09
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_CONFIGURATION, &sunxi_udc_source.standard_reg, NULL);
					}
				}

				break;
			}
			case USB_REQ_GET_INTERFACE:		//   0x0a
			{
				/* device-to-host */
				if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_INTERFACE, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer);
					}
				}

				break;
			}
			case USB_REQ_SET_INTERFACE:		//   0x0b
			{
				/* host-to-device */
				if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_INTERFACE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_INTERFACE, &sunxi_udc_source.standard_reg, NULL);
					}
				}

				break;
			}
			case USB_REQ_SYNCH_FRAME:		//   0x0b
			{
				/* device-to-host */
				if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK))
				{
					if(USB_RECIP_INTERFACE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK))
					{
						//there is some problem
						if(!ep0_stage)
						{
							ep0_stage = 1;
						}
						else
						{
							ret = sunxi_udev_active->standard_req_op(USB_REQ_SYNCH_FRAME, &sunxi_udc_source.standard_reg, NULL);
							ep0_stage = 0;
						}
					}
				}

				break;
			}
			default:
			{
				printf("sunxi usb err: unknown usb out request to device\n");

				USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
				ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED;
				ep0_stage = 0;

				break;
			}
		}
	}
	else
	{
		/* Non-Standard Req */
		printf("non standard req\n");
		ret = sunxi_udev_active->nonstandard_req_op(USB_REQ_GET_STATUS, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer, ep0_stage);
		if(ret == SUNXI_USB_REQ_DATA_HUNGRY)
		{
			ep0_stage = 1;
		}
		else if(ret == SUNXI_USB_REQ_SUCCESSED)
		{
			ep0_stage = 0;
		}
		else if(ret < 0)
		{
			ep0_stage = 0;
			printf("err: unkown bmRequestType(%d)\n", sunxi_udc_source.standard_reg.bmRequestType);
			USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
		}
	}

__ep0_recv_op_err:
	USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index);

	return ret;
}
Ejemplo n.º 22
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
static int sunxi_pburn_state_loop(void  *buffer)
{
	static struct umass_bbb_cbw_t  *cbw;
	static struct umass_bbb_csw_t  csw;
	static uint pburn_flash_start = 0;
	//static uint pburn_flash_sectors = 0;
	int    ret;
	sunxi_ubuf_t *sunxi_ubuf = (sunxi_ubuf_t *)buffer;

	switch(sunxi_usb_pburn_status)
	{
		case SUNXI_USB_PBURN_IDLE:
			if(sunxi_ubuf->rx_ready_for_data == 1)
			{
				sunxi_usb_pburn_status = SUNXI_USB_PBURN_SETUP;
			}

			break;

		case SUNXI_USB_PBURN_SETUP:

			sunxi_usb_dbg("SUNXI_USB_PBURN_SETUP\n");

			if(sunxi_ubuf->rx_req_length != sizeof(struct umass_bbb_cbw_t))
			{
				printf("sunxi usb error: received bytes 0x%x is not equal cbw struct size 0x%zx\n", sunxi_ubuf->rx_req_length, sizeof(struct umass_bbb_cbw_t));

				sunxi_ubuf->rx_ready_for_data = 0;
				sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE;

				break;
			}

			cbw = (struct umass_bbb_cbw_t *)sunxi_ubuf->rx_req_buffer;
			if(CBWSIGNATURE != cbw->dCBWSignature)
			{
				printf("sunxi usb error: the cbw signature 0x%x is bad, need 0x%x\n", cbw->dCBWSignature, CBWSIGNATURE);

				sunxi_ubuf->rx_ready_for_data = 0;
				sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE;

				break;
			}

			csw.dCSWSignature = CSWSIGNATURE;
			csw.dCSWTag 	  = cbw->dCBWTag;

#if defined(SUNXI_USB_30)
			sunxi_usb_pburn_status_enable = 1;
#endif
			sunxi_usb_dbg("usb cbw command = 0x%x\n", cbw->CBWCDB[0]);

			switch(cbw->CBWCDB[0])
	  		{
#ifdef  CONFIG_SUNXI_SECURE_STORAGE
				case 0xf0:			//自定义命令,用于烧录用户数据
	  				sunxi_usb_dbg("usb burn secure storage data\n");
	  				printf("usb command = %d\n", cbw->CBWCDB[1]);
	  				switch(cbw->CBWCDB[1])
	  				{
	  					case 0:				//握手
	  					{
	  						__usb_handshake_sec_t  *handshake = (__usb_handshake_sec_t *)trans_data.base_send_buffer;

                            memset(handshake, 0, sizeof(__usb_handshake_sec_t));
							strcpy(handshake->magic, "usb_burn_handshake");
							sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;

		  					trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_sec_t));

							sunxi_usb_burn_from_boot_setup = 1;

							private_data_ext_buff = (u8 *)malloc(4 * 1024 * 1024);
							if(private_data_ext_buff == NULL)
							{
								printf("there is no memorfy to store all user key data\n");

								csw.bCSWStatus = -1;
							}
							else
		  					{
		  						csw.bCSWStatus = 0;
		  						sunxi_usb_burn_from_boot_handshake = 1;
		  					}
		  					private_data_ext_buff_step = private_data_ext_buff;
						}
						break;

						case 1:				//小机端接收数据
						{
							trans_data.recv_size = cbw->dCBWDataTransferLength;

                            sunxi_usb_pburn_write_enable = 0;
							sunxi_udc_start_recv_by_dma(private_data_ext_buff_step, trans_data.recv_size);	//start dma to receive data

							printf("recv_size=%d\n", trans_data.recv_size);
							sunxi_dump(private_data_ext_buff, trans_data.recv_size);

					        sunxi_usb_pburn_status = SUNXI_USB_PBURN_RECEIVE_NULL;
						}
						break;

						case 2:             //工具端声明数据传输已经完毕,要求获取烧录状态
						{
							__usb_handshake_ext_t  *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer;

							memset(handshake, 0, sizeof(__usb_handshake_ext_t));
							//strcpy(handshake->magic, "usb_burn_receive_data_all");
							sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;

							printf("recv_size=%d\n", trans_data.recv_size);
							sunxi_dump(private_data_ext_buff, trans_data.recv_size);

							int ret = __sunxi_burn_key(private_data_ext_buff, trans_data.recv_size);

		  					trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t));
		  					//开始根据数据类型进行烧录动作

		  					if(!ret)	//数据烧写成功
		  					{
		  						strcpy(handshake->magic, "usb_burn_success");
		  						csw.bCSWStatus = 0;
		  					}
		  					else	//数据烧写失败
		  					{
		  						strcpy(handshake->magic, "usb_burn_error");
		  						csw.bCSWStatus = -1;
		  					}
		  					if(private_data_ext_buff)
		  					{
		  						free(private_data_ext_buff);
		  					}
						}
						break;

//						case 3:             //小机端读取每个key
//						{
//							uint start, sectors;
//							uint offset;
//
//							start   = *(int *)(cbw->CBWCDB + 4);		//读数据的偏移量
//							sectors = *(int *)(cbw->CBWCDB + 8);		//扇区数;
//
//							trans_data.send_size 	   = min(cbw->dCBWDataTransferLength, sectors * 512);
//							trans_data.act_send_buffer = (uint)trans_data.base_send_buffer;
//
//							offset = burn_private_start;
//							ret = sunxi_flash_read(start + offset, sectors, trans_data.base_send_buffer);
//							if(!ret)
//							{
//								printf("sunxi flash read err: start,0x%x sectors 0x%x\n", start, sectors);
//
//								csw.bCSWStatus = 1;
//							}
//							else
//							{
//								csw.bCSWStatus = 0;
//							}
//
//							sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;
//						}
//						break;

						case 4:				//关闭usb
						{
							__usb_handshake_ext_t  *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer;

                            memset(handshake, 0, sizeof(__usb_handshake_ext_t));
							strcpy(handshake->magic, "usb_burn_finish");

							trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t));

							sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size);

		  					csw.bCSWStatus = 0;

		  					sunxi_usb_pburn_status = SUNXI_USB_PBURN_EXIT;

						}
						break;

						case 5:
						{
							__usb_handshake_ext_t  *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer;

							memset(handshake, 0, sizeof(__usb_handshake_ext_t));
							strcpy(handshake->magic, "usb_burn_saved");

							trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t));

		  					csw.bCSWStatus = 0;

		  					sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;
		  					if(sunxi_secure_storage_write("key_burned_flag", "key_burned", strlen("key_burned")))
		  					{
		  						printf("save burned flag err\n");

		  						csw.bCSWStatus = -1;
		  					}
		  					sunxi_secure_storage_exit();
						}
						break;

					default:
						break;
	  			}
	  			break;
#endif

	  			case 0xf3:			//自定义命令,用于烧录用户数据
	  				sunxi_usb_dbg("usb burn private\n");
	  				printf("usb command = %d\n", cbw->CBWCDB[1]);
	  				switch(cbw->CBWCDB[1])
	  				{
	  					case 0:				//握手
	  					{
	  						__usb_handshake_t  *handshake = (__usb_handshake_t *)trans_data.base_send_buffer;

							burn_private_start = sunxi_partition_get_offset_byname("private");
							burn_private_len   = sunxi_partition_get_size_byname("private");

							if(!burn_private_start)
							{
								printf("private partition is not exist\n");

								csw.bCSWStatus = -1;
							}
							else
							{
								csw.bCSWStatus = 0;
							}

                            memset(handshake, 0, sizeof(__usb_handshake_t));
							strcpy(handshake->magic, "usb_burn_handshake");
							handshake->sizelo = burn_private_len;
							handshake->sizehi = 0;
							sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;

							sunxi_usb_burn_from_boot_setup = 1;
							sunxi_usb_burn_from_boot_handshake = 1;

		  					trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_t));
						}
						break;

						case 1:				//小机端接收数据
						{
							//pburn_flash_sectors  = *(int *)(cbw->CBWCDB + 8);
							//pburn_flash_start    = *(int *)(cbw->CBWCDB + 4);
							memcpy(&pburn_flash_start,(cbw->CBWCDB + 4),4);

							trans_data.recv_size = cbw->dCBWDataTransferLength;
							trans_data.act_recv_buffer = trans_data.base_recv_buffer;

                            pburn_flash_start += burn_private_start;
                            sunxi_usb_pburn_write_enable = 0;
							sunxi_udc_start_recv_by_dma(trans_data.act_recv_buffer, trans_data.recv_size);	//start dma to receive data

					        sunxi_usb_pburn_status = SUNXI_USB_PBURN_RECEIVE_DATA;
						}
						break;

						case 3:             //小机端发送数据
						{
							uint start, sectors;

							//start   = *(int *)(cbw->CBWCDB + 4);		//读数据的偏移量
							//sectors = *(int *)(cbw->CBWCDB + 8);		//扇区数;
							memcpy(&start,(cbw->CBWCDB + 4),4);
							memcpy(&sectors,(cbw->CBWCDB + 8),4);

							printf("start=%d, sectors=%d\n", start, sectors);

							trans_data.send_size 	   = min(cbw->dCBWDataTransferLength, sectors * 512);
							trans_data.act_send_buffer = trans_data.base_send_buffer;

							printf("send size=%d\n", trans_data.send_size);

							ret = sunxi_flash_read(start + burn_private_start, sectors, trans_data.base_send_buffer);
							if(!ret)
							{
								printf("sunxi flash read err: start,0x%x sectors 0x%x\n", start, sectors);

								csw.bCSWStatus = 1;
							}
							else
							{
								csw.bCSWStatus = 0;
							}

							sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;
						}
						break;

						case 4:				//关闭usb
						{
							__usb_handshake_ext_t  *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer;

                            memset(handshake, 0, sizeof(__usb_handshake_ext_t));
							strcpy(handshake->magic, "usb_burn_finish");

							trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t));

							sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size);

		  					csw.bCSWStatus = 0;

							sunxi_flash_flush();
		  					sunxi_usb_pburn_status = SUNXI_USB_PBURN_EXIT;

						}
						break;

						case 5:
						{
							__usb_handshake_ext_t  *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer;
							char buffer[512];

							memset(handshake, 0, sizeof(__usb_handshake_ext_t));
							strcpy(handshake->magic, "usb_burn_saved");

							trans_data.act_send_buffer = trans_data.base_send_buffer;
		  					trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t));

		  					csw.bCSWStatus = 0;

		  					sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA;

		  					memset(buffer, 0, 512);
							strcpy(buffer, "key_burned");

		  					if(!sunxi_flash_write(burn_private_start + burn_private_len - (8192+512)/512, 1, buffer))
		  					{
		  						printf("save burned flag err\n");

		  						csw.bCSWStatus = -1;
		  					}
		  					sunxi_flash_flush();
#ifdef CONFIG_SUNXI_SECURE_STORAGE
							if(sunxi_secure_storage_init())
							{
								printf("init secure storage failed\n");

								csw.bCSWStatus = -1;
							}
		  					else
		  					{
		  						if(sunxi_secure_storage_write("key_burned_flag", "key_burned", strlen("key_burned")))
		  						{
		  							printf("save burned flag err\n");

		  							csw.bCSWStatus = -1;
		  						}
		  					}
		  					sunxi_secure_storage_exit();
#endif
						}
						break;

					default:
						break;
	  				}

	  			break;

	  			default:
	  				sunxi_usb_dbg("not supported command 0x%x now\n", cbw->CBWCDB[0]);
	  				sunxi_usb_dbg("asked size 0x%x\n", cbw->dCBWDataTransferLength);

	  				csw.bCSWStatus = 1;

	  				sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS;

	  				break;
	  		}

	  		break;

	  	case SUNXI_USB_PBURN_SEND_DATA:

	  		sunxi_usb_dbg("SUNXI_USB_SEND_DATA\n");

			sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS;
			printf("SUNXI_USB_SEND_DATA=%d\n", trans_data.send_size);
			sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size);
#if defined(SUNXI_USB_30)
			sunxi_usb_pburn_status_enable = 0;
#endif
	  		break;

	  	case SUNXI_USB_PBURN_RECEIVE_DATA:

	  		sunxi_usb_dbg("SUNXI_USB_RECEIVE_DATA\n");

			if(sunxi_usb_pburn_write_enable == 1)
			{
				sunxi_usb_dbg("write flash, start 0x%x, sectors 0x%x\n", pburn_flash_start, trans_data.recv_size/512);
				ret = sunxi_flash_write(pburn_flash_start, (trans_data.recv_size+511)/512, (void *)trans_data.act_recv_buffer);
				if(!ret)
				{
					printf("sunxi flash write err: start,0x%x sectors 0x%x\n", pburn_flash_start, (trans_data.recv_size+511)/512);

					csw.bCSWStatus = 1;
				}
				else
				{
					csw.bCSWStatus = 0;
  				}
				sunxi_usb_pburn_write_enable = 0;

  				sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS;
			}

	  		break;

		case SUNXI_USB_PBURN_STATUS:

			sunxi_usb_dbg("SUNXI_USB_PBURN_STATUS\n");
#if defined(SUNXI_USB_30)
			if(sunxi_usb_pburn_status_enable)
#endif
			{
				sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE;
				sunxi_ubuf->rx_ready_for_data = 0;
				__sunxi_pburn_send_status(&csw, sizeof(struct umass_bbb_csw_t));
			}

			break;

		case SUNXI_USB_PBURN_EXIT:

			printf("SUNXI_USB_PBURN_EXIT\n");

			sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE;
			sunxi_ubuf->rx_ready_for_data = 0;
			__sunxi_pburn_send_status(&csw, sizeof(struct umass_bbb_csw_t));

			printf("Device will shutdown in 3 Secends...\n");
			__msdelay(3000);

			return SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN;

	  	case SUNXI_USB_PBURN_RECEIVE_NULL:

	  		sunxi_usb_dbg("SUNXI_USB_PBURN_RECEIVE_NULL\n");

			if(sunxi_usb_pburn_write_enable == 1)
			{
				csw.bCSWStatus = 0;
				sunxi_usb_pburn_write_enable = 0;
  				sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS;
			}

	  		break;

	  	default:
	  		break;
	}

	return 0;
}
Ejemplo n.º 23
0
/*
*******************************************************************************
*                     do_usb_req_get_descriptor
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer)
{
	int ret = SUNXI_USB_REQ_SUCCESSED;

	//获取描述符
	switch(req->wValue >> 8)
	{
		case USB_DT_DEVICE:		//设备描述符
		{
			struct usb_device_descriptor *dev_dscrptr;

			sunxi_usb_dbg("get device descriptor\n");

			dev_dscrptr = (struct usb_device_descriptor *)buffer;
			memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor));

			dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor));
			dev_dscrptr->bDescriptorType    = USB_DT_DEVICE;
#ifdef CONFIG_USB_1_1_DEVICE
			dev_dscrptr->bcdUSB             = 0x110;
#else
			dev_dscrptr->bcdUSB             = 0x200;
#endif
			dev_dscrptr->bDeviceClass       = 0xff;		//设备类:大容量存储
			dev_dscrptr->bDeviceSubClass    = 0xff;
			dev_dscrptr->bDeviceProtocol    = 0xff;
			dev_dscrptr->bMaxPacketSize0    = 0x40;
			dev_dscrptr->idVendor           = DEVICE_VENDOR_ID;
			dev_dscrptr->idProduct          = DEVICE_PRODUCT_ID;
			dev_dscrptr->bcdDevice          = DEVICE_BCD;
			dev_dscrptr->iManufacturer      = SUNXI_FASTBOOT_DEVICE_STRING_MANUFACTURER_INDEX;
			dev_dscrptr->iProduct           = SUNXI_FASTBOOT_DEVICE_STRING_PRODUCT_INDEX;
			dev_dscrptr->iSerialNumber      = SUNXI_FASTBOOT_DEVICE_STRING_SERIAL_NUMBER_INDEX;
			dev_dscrptr->bNumConfigurations = 1;

			sunxi_udc_send_setup(dev_dscrptr->bLength, buffer);
		}
		break;

		case USB_DT_CONFIG:		//配置描述符
		{
			struct usb_configuration_descriptor *config_dscrptr;
			struct usb_interface_descriptor 	*inter_dscrptr;
			struct usb_endpoint_descriptor 		*ep_in, *ep_out;
			unsigned char bytes_remaining = req->wLength;
			unsigned char bytes_total = 0;

			sunxi_usb_dbg("get config descriptor\n");

			bytes_total = sizeof (struct usb_configuration_descriptor) + \
						  sizeof (struct usb_interface_descriptor) 	   + \
						  sizeof (struct usb_endpoint_descriptor) 	   + \
						  sizeof (struct usb_endpoint_descriptor);

			memset(buffer, 0, bytes_total);

			config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0);
			inter_dscrptr  = (struct usb_interface_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor));
			ep_in 		   = (struct usb_endpoint_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor) + 	\
																	 sizeof(struct usb_interface_descriptor));
			ep_out 		   = (struct usb_endpoint_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor) + 	\
																	 sizeof(struct usb_interface_descriptor)	 +	\
																	 sizeof(struct usb_endpoint_descriptor));

			/* configuration */
			config_dscrptr->bLength            	= MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor));
			config_dscrptr->bDescriptorType    	= USB_DT_CONFIG;
			config_dscrptr->wTotalLength 		= bytes_total;
			config_dscrptr->bNumInterfaces     	= 1;
			config_dscrptr->bConfigurationValue	= 1;
			config_dscrptr->iConfiguration     	= SUNXI_FASTBOOT_DEVICE_STRING_CONFIG_INDEX;
			config_dscrptr->bmAttributes       	= 0xC0;
			config_dscrptr->bMaxPower          	= 0xFA;		//最大电流500ms(0xfa * 2)

			bytes_remaining 				   -= config_dscrptr->bLength;
			/* interface */
			inter_dscrptr->bLength             = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor));
			inter_dscrptr->bDescriptorType     = USB_DT_INTERFACE;
			inter_dscrptr->bInterfaceNumber    = 0x00;
			inter_dscrptr->bAlternateSetting   = 0x00;
			inter_dscrptr->bNumEndpoints       = 0x02;
			inter_dscrptr->bInterfaceClass     = 0xff;		//fastboot storage
			inter_dscrptr->bInterfaceSubClass  = FASTBOOT_INTERFACE_SUB_CLASS;
			inter_dscrptr->bInterfaceProtocol  = FASTBOOT_INTERFACE_PROTOCOL;
			inter_dscrptr->iInterface          = SUNXI_FASTBOOT_DEVICE_STRING_INTERFACE_INDEX;

			bytes_remaining 				  -= inter_dscrptr->bLength;
			/* ep_in */
			ep_in->bLength            = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor));
			ep_in->bDescriptorType    = USB_DT_ENDPOINT;
			ep_in->bEndpointAddress   = sunxi_udc_get_ep_in_type(); /* IN */
			ep_in->bmAttributes       = USB_ENDPOINT_XFER_BULK;
			ep_in->wMaxPacketSize 	  = sunxi_udc_get_ep_max();
			ep_in->bInterval          = 0x00;

			bytes_remaining 		 -= ep_in->bLength;
			/* ep_out */
			ep_out->bLength            = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor));
			ep_out->bDescriptorType    = USB_DT_ENDPOINT;
			ep_out->bEndpointAddress   = sunxi_udc_get_ep_out_type(); /* OUT */
			ep_out->bmAttributes       = USB_ENDPOINT_XFER_BULK;
			ep_out->wMaxPacketSize 	   = sunxi_udc_get_ep_max();
			ep_out->bInterval          = 0x00;

			bytes_remaining 		  -= ep_out->bLength;

			sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer);
		}
		break;

		case USB_DT_STRING:
		{
			unsigned char bLength = 0;
			unsigned char string_index = req->wValue & 0xff;

			sunxi_usb_dbg("get string descriptor\n");

			/* Language ID */
			if(string_index == 0)
			{
				bLength = MIN(4, req->wLength);

				sunxi_udc_send_setup(bLength, (void *)sunxi_usb_fastboot_dev[0]);
			}
			else if(string_index < SUNXI_USB_FASTBOOT_DEV_MAX)
			{
				/* Size of string in chars */
				unsigned char i = 0;
				unsigned char str_length = strlen ((const char *)sunxi_usb_fastboot_dev[string_index]);
				unsigned char bLength = 2 + (2 * str_length);

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

				/* Copy device string to fifo, expand to simple unicode */
				for(i = 0; i < str_length; i++)
				{
					buffer[2+ 2*i + 0] = sunxi_usb_fastboot_dev[string_index][i];
					buffer[2+ 2*i + 1] = 0;
				}
				bLength = MIN(bLength, req->wLength);

				sunxi_udc_send_setup(bLength, buffer);
			}
			else
			{
				printf("sunxi usb err: string line %d is not supported\n", string_index);
			}
		}
		break;

		case USB_DT_DEVICE_QUALIFIER:
		{
#ifdef CONFIG_USB_1_1_DEVICE
			/* This is an invalid request for usb 1.1, nak it */
			USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
#else
			struct usb_qualifier_descriptor *qua_dscrpt;

			sunxi_usb_dbg("get qualifier descriptor\n");

			qua_dscrpt = (struct usb_qualifier_descriptor *)buffer;
			memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor));

			qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor)));
			qua_dscrpt->bDescriptorType    = USB_DT_DEVICE_QUALIFIER;
			qua_dscrpt->bcdUSB             = 0x200;
			qua_dscrpt->bDeviceClass       = 0xff;
			qua_dscrpt->bDeviceSubClass    = 0xff;
			qua_dscrpt->bDeviceProtocol    = 0xff;
			qua_dscrpt->bMaxPacketSize0    = 0x40;
			qua_dscrpt->bNumConfigurations = 1;
			qua_dscrpt->bRESERVED          = 0;

			sunxi_udc_send_setup(qua_dscrpt->bLength, buffer);
#endif
		}
		break;

		default:
			printf("err: unkown wValue(%d)\n", req->wValue);

			ret = SUNXI_USB_REQ_OP_ERR;
	}

	return ret;
}
Ejemplo n.º 24
0
/*
*******************************************************************************
*                     do_usb_req_get_descriptor
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer)
{
	int ret = SUNXI_USB_REQ_SUCCESSED;

	//获取描述符
	switch(req->wValue >> 8)
	{
		case USB_DT_DEVICE:		//设备描述符
		{
			struct usb_device_descriptor *dev_dscrptr;

			sunxi_usb_dbg("get device descriptor\n");

			dev_dscrptr = (struct usb_device_descriptor *)buffer;
			memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor));

			dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor));
			dev_dscrptr->bDescriptorType    = USB_DT_DEVICE;
#ifdef CONFIG_USB_1_1_DEVICE
			dev_dscrptr->bcdUSB             = 0x110;
#else
			dev_dscrptr->bcdUSB             = 0x200;
#endif
			dev_dscrptr->bDeviceClass       = 0;
			dev_dscrptr->bDeviceSubClass    = 0;
			dev_dscrptr->bDeviceProtocol    = 0;
			dev_dscrptr->bMaxPacketSize0    = 0x40;
			dev_dscrptr->idVendor           = DRIVER_VENDOR_ID;
			dev_dscrptr->idProduct          = DRIVER_PRODUCT_ID;
			dev_dscrptr->bcdDevice          = 0xffff;
			//ignored
			//dev_dscrptr->iManufacturer      = SUNXI_USB_STRING_IMANUFACTURER;
			//dev_dscrptr->iProduct           = SUNXI_USB_STRING_IPRODUCT;
			//dev_dscrptr->iSerialNumber      = SUNXI_USB_STRING_ISERIALNUMBER;
			dev_dscrptr->iManufacturer      = 0;
			dev_dscrptr->iProduct           = 0;
			dev_dscrptr->iSerialNumber      = 0;
			dev_dscrptr->bNumConfigurations = 1;

			sunxi_udc_send_setup(dev_dscrptr->bLength, buffer);
		}
		break;

		case USB_DT_CONFIG:		//配置描述符
		{
			struct usb_configuration_descriptor *config_dscrptr;
			struct usb_interface_descriptor 	*inter_dscrptr;
			struct usb_endpoint_descriptor 		*ep_in, *ep_out;
			unsigned char bytes_remaining = req->wLength;
			unsigned char bytes_total = 0;

			sunxi_usb_dbg("get config descriptor\n");

			bytes_total = sizeof (struct usb_configuration_descriptor) + \
						  sizeof (struct usb_interface_descriptor) 	   + \
						  sizeof (struct usb_endpoint_descriptor) 	   + \
						  sizeof (struct usb_endpoint_descriptor);

			memset(buffer, 0, bytes_total);

			config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0);
			inter_dscrptr  = (struct usb_interface_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor));
			ep_in 		   = (struct usb_endpoint_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor) + 	\
																	 sizeof(struct usb_interface_descriptor));
			ep_out 		   = (struct usb_endpoint_descriptor 	  *)(buffer + 						\
																	 sizeof(struct usb_configuration_descriptor) + 	\
																	 sizeof(struct usb_interface_descriptor)	 +	\
																	 sizeof(struct usb_endpoint_descriptor));

			/* configuration */
			config_dscrptr->bLength            	= MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor));
			config_dscrptr->bDescriptorType    	= USB_DT_CONFIG;
			config_dscrptr->wTotalLength 		= bytes_total;
			config_dscrptr->bNumInterfaces     	= 1;
			config_dscrptr->bConfigurationValue	= 1;
			config_dscrptr->iConfiguration     	= 0;
			config_dscrptr->bmAttributes       	= 0x80;		//not self powered
			config_dscrptr->bMaxPower          	= 0xFA;		//最大电流500ms(0xfa * 2)

			bytes_remaining 				   -= config_dscrptr->bLength;
			/* interface */
			inter_dscrptr->bLength             = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor));
			inter_dscrptr->bDescriptorType     = USB_DT_INTERFACE;
			inter_dscrptr->bInterfaceNumber    = 0x00;
			inter_dscrptr->bAlternateSetting   = 0x00;
			inter_dscrptr->bNumEndpoints       = 0x02;
			inter_dscrptr->bInterfaceClass     = 0xff;
			inter_dscrptr->bInterfaceSubClass  = 0xff;
			inter_dscrptr->bInterfaceProtocol  = 0xff;
			inter_dscrptr->iInterface          = 0;

			bytes_remaining 				  -= inter_dscrptr->bLength;
			/* ep_in */
			ep_in->bLength            = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor));
			ep_in->bDescriptorType    = USB_DT_ENDPOINT;
			ep_in->bEndpointAddress   = sunxi_udc_get_ep_in_type(); /* IN */
			ep_in->bmAttributes       = USB_ENDPOINT_XFER_BULK;
			ep_in->wMaxPacketSize 	  = sunxi_udc_get_ep_max();
			ep_in->bInterval          = 0x00;

			bytes_remaining 		 -= ep_in->bLength;
			/* ep_out */
			ep_out->bLength            = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor));
			ep_out->bDescriptorType    = USB_DT_ENDPOINT;
			ep_out->bEndpointAddress   = sunxi_udc_get_ep_out_type(); /* OUT */
			ep_out->bmAttributes       = USB_ENDPOINT_XFER_BULK;
			ep_out->wMaxPacketSize 	   = sunxi_udc_get_ep_max();
			ep_out->bInterval          = 0x00;

			bytes_remaining 		  -= ep_out->bLength;

			sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer);
		}
		break;

		case USB_DT_STRING:
		{
			unsigned char bLength = 0;
			unsigned char string_index = req->wValue & 0xff;

			sunxi_usb_dbg("get string descriptor\n");

			/* Language ID */
			if(string_index == 0)
			{
				bLength = MIN(4, req->wLength);

				buffer[0] = bLength;
				buffer[1] = USB_DT_STRING;
				buffer[2] = 9;
				buffer[3] = 4;
				sunxi_udc_send_setup(bLength, (void *)buffer);
			}
			else
			{
				printf("sunxi usb err: string line %d is not supported\n", string_index);
			}
		}
		break;

		case USB_DT_DEVICE_QUALIFIER:
		{
#ifdef CONFIG_USB_1_1_DEVICE
			/* This is an invalid request for usb 1.1, nak it */
			USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0);
#else
			struct usb_qualifier_descriptor *qua_dscrpt;

			sunxi_usb_dbg("get qualifier descriptor\n");

			qua_dscrpt = (struct usb_qualifier_descriptor *)buffer;
			memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor));

			qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor)));
			qua_dscrpt->bDescriptorType    = USB_DT_DEVICE_QUALIFIER;
			qua_dscrpt->bcdUSB             = 0x200;
			qua_dscrpt->bDeviceClass       = 0xff;
			qua_dscrpt->bDeviceSubClass    = 0xff;
			qua_dscrpt->bDeviceProtocol    = 0xff;
			qua_dscrpt->bMaxPacketSize0    = 0x40;
			qua_dscrpt->bNumConfigurations = 1;
			qua_dscrpt->breserved          = 0;

			sunxi_udc_send_setup(qua_dscrpt->bLength, buffer);
#endif
		}
		break;

		default:
			printf("err: unkown wValue(%d)\n", req->wValue);

			ret = SUNXI_USB_REQ_OP_ERR;
	}

	return ret;
}
Ejemplo n.º 25
0
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :   usb初始化动作,完成后,即可开启中断后,使用中断处理程序
*
*
************************************************************************************************************
*/
int sunxi_usb_init(int delaytime)
{
	if(sunxi_udev_active->state_init())
	{
		printf("sunxi usb err: fail to init usb device\n");

		return -1;
	}
	//预先关闭usb中断
	irq_disable(AW_IRQ_USB_OTG);
	//初始化 sunxi_udc用到的资源
    memset(&sunxi_udc_source, 0, sizeof(sunxi_udc_t));
	//获取控制器地址资源
    sunxi_udc_source.usbc_hd = USBC_open_otg(0);
	if(sunxi_udc_source.usbc_hd == 0)
	{
		printf("sunxi usb err : USBC_open_otg failed\n");

		return -1;
	}
	usb_dma_init(sunxi_udc_source.usbc_hd);
	//断开usb
	USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF);
	//预先关闭usb时钟
	usb_close_clock();
	//延时 delaytime  ms
	printf("delay time %d\n", delaytime);
	__msdelay(delaytime);
	//申请DMA资源
	sunxi_udc_source.dma_send_channal = usb_dma_request();
	if(!sunxi_udc_source.dma_send_channal)
	{
		printf("sunxi usb err : unable to request dma for usb send data\n");

		goto __sunxi_usb_init_fail;
	}
	sunxi_usb_dbg("dma send ch %d\n", sunxi_udc_source.dma_send_channal);
	sunxi_udc_source.dma_recv_channal = usb_dma_request();
	if(!sunxi_udc_source.dma_recv_channal)
	{
		printf("sunxi usb err : unable to request dma for usb receive data\n");

		goto __sunxi_usb_init_fail;
	}
	sunxi_usb_dbg("dma recv ch %d\n", sunxi_udc_source.dma_recv_channal);

	sunxi_udc_source.address = 0;
	sunxi_udc_source.speed = USB_SPEED_HIGH;
	sunxi_udc_source.bulk_ep_max = HIGH_SPEED_EP_MAX_PACKET_SIZE;
	sunxi_udc_source.fifo_size    = BULK_FIFOSIZE;
	sunxi_udc_source.bulk_in_addr = 100;
	sunxi_udc_source.bulk_out_addr = sunxi_udc_source.bulk_in_addr + sunxi_udc_source.fifo_size * 2;
	//内存资源
	memset(&sunxi_ubuf, 0, sizeof(sunxi_ubuf_t));

	sunxi_ubuf.rx_base_buffer = (uchar *)malloc(1024);
	if(!sunxi_ubuf.rx_base_buffer)
	{
		printf("sunxi usb err: fail to malloc memory for rx command buffer\n");

		goto __sunxi_usb_init_fail;
	}
	sunxi_ubuf.rx_req_buffer = sunxi_ubuf.rx_base_buffer;

	usb_open_clock();
	//设置为device模式
    USBC_ForceId(sunxi_udc_source.usbc_hd, USBC_ID_TYPE_DEVICE);
	//设置VBUS为高
	USBC_ForceVbusValid(sunxi_udc_source.usbc_hd, USBC_VBUS_TYPE_HIGH);

    USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF);
	//soft connect
    USBC_EnableDpDmPullUp(sunxi_udc_source.usbc_hd);
    USBC_EnableIdPullUp(sunxi_udc_source.usbc_hd);
    //选择使用PIO模式搬移数据
    USBC_SelectBus(sunxi_udc_source.usbc_hd, USBC_IO_TYPE_PIO, 0, 0);
    //映射SRAM buffer
    USBC_ConfigFIFO_Base(sunxi_udc_source.usbc_hd, 0, 0);
	//
    USBC_EnhanceSignal(sunxi_udc_source.usbc_hd);
	//默认采用高速模式传输
#ifdef	CONFIG_USB_1_1_DEVICE
	USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_FS);
#else
	USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_HS);
#endif
	//配置发送端dma资源
	usb_dma_setting(sunxi_udc_source.dma_send_channal, USB_DMA_FROM_DRAM_TO_HOST, SUNXI_USB_BULK_IN_EP_INDEX);
	usb_dma_set_pktlen(sunxi_udc_source.dma_send_channal, HIGH_SPEED_EP_MAX_PACKET_SIZE);
	//配置接收端dma资源
	usb_dma_setting(sunxi_udc_source.dma_recv_channal, USB_DMA_FROM_HOST_TO_DRAM, SUNXI_USB_BULK_OUT_EP_INDEX);
	usb_dma_set_pktlen(sunxi_udc_source.dma_recv_channal, HIGH_SPEED_EP_MAX_PACKET_SIZE);
    /* disable all interrupt */
    USBC_INT_DisableUsbMiscAll(sunxi_udc_source.usbc_hd);
    USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX);
    USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX);

    /* 开启 reset、resume、suspend中断 */
	USBC_INT_EnableUsbMiscUint(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND | USBC_INTUSB_RESUME	\
													   | USBC_INTUSB_RESET   | USBC_INTUSB_SOF);

    /* enbale ep0_tx_irq */
	USBC_INT_EnableEp(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX);

    __usb_bulk_ep_reset();

    USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_ON);

	irq_install_handler(AW_IRQ_USB_OTG, sunxi_usb_irq, NULL);
	irq_enable(AW_IRQ_USB_OTG);

	return 0;

__sunxi_usb_init_fail:
	if(sunxi_udc_source.dma_send_channal)
	{
		usb_dma_release(sunxi_udc_source.dma_send_channal);
	}
	if(sunxi_udc_source.dma_recv_channal)
	{
		usb_dma_release(sunxi_udc_source.dma_recv_channal);
	}
	if(sunxi_udc_source.usbc_hd)
	{
		USBC_close_otg(sunxi_udc_source.usbc_hd);
	}
	if(sunxi_ubuf.rx_base_buffer)
	{
		free(sunxi_ubuf.rx_base_buffer);
	}

	return -1;
}