Exemple #1
0
static void pcd_setup( pcd_struct_t *_pcd )
{

	struct usb_ctrlrequest	ctrl = _pcd->setup_pkt.req;
	dwc_ep_t	*ep0 = &g_dwc_eps[0];
	deptsiz0_data_t doeptsize0 = { 0};

	if(_pcd->request_enable == 0)
		return;

//	_pcd->setup_pkt.d32[0] = 0;
//	_pcd->setup_pkt.d32[1] = 0;
	unsigned short status = 0;
	_pcd->request_enable = 0;

        doeptsize0.d32 = dwc_read_reg32( DWC_REG_OUT_EP_TSIZE(0));

        if (ctrl.bRequestType & USB_DIR_IN) {        
                ep0->is_in = 1;
                _pcd->ep0state = EP0_IN_DATA_PHASE;
        } else {
                ep0->is_in = 0;
                _pcd->ep0state = EP0_OUT_DATA_PHASE;
        }


	if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) {
		/* handle non-standard (class/vendor) requests in the gadget driver */
		//do_gadget_setup(_pcd, &ctrl );
		DBG("Vendor requset\n");
		do_vendor_request(_pcd, &ctrl );
		dwc_otg_ep_req_start(_pcd,0);
		return;
	}

        /** @todo NGS: Handle bad setup packet? */

        switch (ctrl.bRequest) {

        case USB_REQ_GET_STATUS:

                switch (ctrl.bRequestType & USB_RECIP_MASK) {
                case USB_RECIP_DEVICE:
                        status = 0x1; /* Self powered */
                        status |= 0;//_pcd->remote_wakeup_enable << 1; 
                        break;
		}
		_pcd->buf = (char *)&status;
		_pcd->length = 2;
		dwc_otg_ep_req_start(_pcd,0);
		break;
#if 0
                case USB_RECIP_INTERFACE:
                        *status = 0;
                        break;                        

                case USB_RECIP_ENDPOINT:
                        ep = get_ep_by_addr(_pcd, ctrl.wIndex);
                        if ( ep == 0 || ctrl.wLength > 2) {
                                ep0_do_stall(_pcd, -EOPNOTSUPP);
                                return;
                        }
                        /** @todo check for EP stall */
                        *status = ep->stopped;
                        break;
                }
                _pcd->ep0_pending = 1;

                ep0->dwc_ep.start_xfer_buff = (uint8_t *)status;
                ep0->dwc_ep.xfer_buff = (uint8_t *)status;
                ep0->dwc_ep.dma_addr = _pcd->status_buf_dma_handle;
                ep0->dwc_ep.xfer_len = 2;
                ep0->dwc_ep.xfer_count = 0;
                ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
                dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep );
                break;

        case USB_REQ_CLEAR_FEATURE:
                do_clear_feature( _pcd );
                break;

        case USB_REQ_SET_FEATURE:
                do_set_feature( _pcd );
                break;
 #endif               
        case USB_REQ_SET_ADDRESS:
                if (ctrl.bRequestType == USB_RECIP_DEVICE) {
                        dcfg_data_t dcfg = { 0 };

			    //DBG("Set address: %d\n",ctrl.wValue);
                        dcfg.b.devaddr = ctrl.wValue;
                        dwc_modify_reg32(DWC_REG_DCFG,0, dcfg.d32);
                        do_setup_in_status_phase( _pcd );
                        return;
                }
                break;

        case USB_REQ_SET_INTERFACE:
        case USB_REQ_SET_CONFIGURATION:
                _pcd->request_config = 1;   /* Configuration changed */
               // do_gadget_setup(_pcd, &ctrl );
               // break;
                
        default:
                /* Call the Gadget Driver's setup functions */        
                do_gadget_setup(_pcd, &ctrl );
                dwc_otg_ep_req_start(_pcd,0);
		break;
        }
Exemple #2
0
/**
 * This function is used to submit an I/O Request to an EP.
 *
 *	- When the request completes the request's completion callback
 *	  is called to return the request to the driver.
 *	- An EP, except control EPs, may have multiple requests
 *	  pending.
 *	- Once submitted the request cannot be examined or modified.
 *	- Each request is turned into one or more packets.
 *	- A BULK EP can queue any amount of data; the transfer is
 *	  packetized.
 *	- Zero length Packets are specified with the request 'zero'
 *	  flag.
 */
static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep, 
								struct usb_request *_req, int _gfp_flags)
{
	int prevented = 0;
	dwc_otg_pcd_request_t *req;
	dwc_otg_pcd_ep_t *ep;
	dwc_otg_pcd_t	*pcd;
	unsigned long flags = 0;

	DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p,%d)\n", 
				__func__, _ep, _req, _gfp_flags);
		
	req = container_of(_req, dwc_otg_pcd_request_t, req);
	if (!_req || !_req->complete || !_req->buf || 
			!list_empty(&req->queue)) 
	{
		if( !_req ) printk("bad _req\n");
		if( !_req->complete ) printk("bad _req->complete\n");
		if( !_req->buf ) printk("bad _req->buf\n");
		if( !list_empty(&req->queue) ) printk("bad list_empty\n");
		DWC_WARN("%s, bad params\n", __func__);
		return -EINVAL;
	}
		
	ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
	if (!_ep || (!ep->desc && ep->dwc_ep.num != 0)) 
	{
		DWC_WARN("%s, bad ep\n", __func__);
		return -EINVAL;
	}
	pcd = ep->pcd;

//cathy, if suspended, drop request
	if ( (GET_CORE_IF(pcd)->dev_if->suspended == 1) && (ep->dwc_ep.num != 0) )
	{
		DWC_DEBUGPL(DBG_PCDV,"%s, epnum = %d, drop request\n", __func__, ep->dwc_ep.num);
		return -ESHUTDOWN;	
	}

	if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) 
	{
		DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", pcd->gadget.speed);
		DWC_WARN("%s, bogus device state\n", __func__);
		return -ESHUTDOWN;
	}


	DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
				   _ep->name, _req, _req->length, _req->buf);

	if (!GET_CORE_IF(pcd)->core_params->opt) 
	{
		if (ep->dwc_ep.num != 0) 
		{
			DWC_ERROR("%s queue req %p, len %d buf %p\n",
					  _ep->name, _req, _req->length, _req->buf);
		}
	}

	SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags);

#if defined(DEBUG) & defined(VERBOSE)
	dump_msg(_req->buf, _req->length);
#endif	

	_req->status = -EINPROGRESS;
	_req->actual = 0;

	/* 
	 * For EP0 IN without premature status, zlp is required?
	 */
	if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) 
	{
		DWC_DEBUGPL(DBG_PCDV, "%s-OUT ZLP\n", _ep->name);
		//_req->zero = 1;
	}

	/* Start the transfer */
	if (list_empty(&ep->queue) && !ep->stopped) 
	{
		/* EP0 Transfer? */
		if (ep->dwc_ep.num == 0) 
		{
			switch (pcd->ep0state) 
			{
			case EP0_IN_DATA_PHASE:
				DWC_DEBUGPL(DBG_PCD, 
								"%s ep0: EP0_IN_DATA_PHASE\n", 
								__func__);
				break;

			case EP0_OUT_DATA_PHASE:
				DWC_DEBUGPL(DBG_PCD, 
								"%s ep0: EP0_OUT_DATA_PHASE\n", 
								__func__);
				if (pcd->request_config) 
				{ 
					/* Complete STATUS PHASE */
					ep->dwc_ep.is_in = 1;
					pcd->ep0state = EP0_STATUS;
				}
				break;
						
			default:
				DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", 
											pcd->ep0state);
				SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags);
				return -EL2HLT;
			}
			ep->dwc_ep.dma_addr = (u32)_req->buf & ~Uncache_Mask;   //_req->dma;	//cathy
			ep->dwc_ep.start_xfer_buff = _req->buf;
			ep->dwc_ep.xfer_buff = _req->buf;
			ep->dwc_ep.xfer_len = _req->length;
			ep->dwc_ep.xfer_count = 0;
			ep->dwc_ep.sent_zlp = 0;
			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
			dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), 
										&ep->dwc_ep );
		} 
		else 
		{
			/* Setup and start the Transfer */
			ep->dwc_ep.dma_addr = (u32)_req->buf  & ~Uncache_Mask;   //_req->dma;	//cathy
			//ep->dwc_ep.dma_addr = _req->dma;
			ep->dwc_ep.start_xfer_buff = _req->buf;
			ep->dwc_ep.xfer_buff = _req->buf;
			ep->dwc_ep.xfer_len = _req->length;
			ep->dwc_ep.xfer_count = 0;
			ep->dwc_ep.sent_zlp = 0;
			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
			dwc_otg_ep_start_transfer( GET_CORE_IF(pcd), 
									   &ep->dwc_ep );
		}
	}

	if ((req != 0) || prevented) 
	{
		++pcd->request_pending;
		list_add_tail(&req->queue, &ep->queue);
//cathy
#if 0
		if (ep->dwc_ep.is_in && ep->stopped && !(GET_CORE_IF(pcd)->dma_enable)) 
		{
			/** @todo NGS Create a function for this. */
			diepmsk_data_t diepmsk = { .d32 = 0};
			diepmsk.b.intktxfemp = 1;
			dwc_modify_reg32( &GET_CORE_IF(pcd)->dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32 );
		}
#endif		
	}