
#include "OB90A64U1.h"
#include "Timer32.h"
#include "USB.h"
#include "USBDEF.h"
#include "USBCOM.h"
#include "USBTable.h"
#define MIN(X, Y) ( (X) < (Y) ? (X) : (Y) )



void COM_DecodeSetupCommands(USB_SETUP_PACKET* psetup_pkg)
{
    USB_ENUM_ALL_DESCRIPTORS* pusb_all_dscr = &g_usb_all_dscr;
    
    switch(psetup_pkg->cRequest)
    {
    case USB_CMD_CLEAR_FEATURE:     //尚不支援
    case USB_CMD_SET_FEATURE:       //尚不支援
    case USB_CMD_SET_INTERFACE:     //尚不支援
    case USB_CMD_SYNC_FRAME:        //尚不支援
    case USB_CMD_SET_SEL:           //尚不支援
    case USB_CMD_ISO_DELAY:         //尚不支援
    case USB_CMD_SET_CONFIG:        //尚不支援
    case USB_CMD_SET_DESCRIPTOR:    //硬體自動回
    case USB_CMD_GET_CONFIG:        //硬體自動回
    case USB_CMD_SET_ADDRESS:       //硬體自動回
    case USB_CMD_GET_INTERFACE:     //硬體自動回
		USBSetReady(USB_CONTROL_POINT);		
		//rEPDRDY = 0x7E;
        break;

    case USB_CMD_GET_STATUS:
        COM_CmdGetStatus();
        break;

    case USB_CMD_GET_DESCRIPTOR:        
		   COM_CmdGetDescriptor(psetup_pkg, pusb_all_dscr);		
        break;

    case USB_CMD_GET_MAX_LUN:
        COM_CmdGetMaxLun();
        break;

    case USB_CMD_MASS_STORAGE_RESET:
        COM_CmdMassStorageReset();
        break;

    default:
        break;
    }
}

void COM_CmdGetStatus(void)
{
  uint8_t Buff[2];  
	Buff[0] = 0;
  Buff[1] = 0;

 if ( USB_ControlIn(Buff, 2) == USB_STATUS_TIMER_OUT )
       USB_StallEp(USB_CONTROL_POINT);
}

void COM_CmdGetDescriptor(USB_SETUP_PACKET* psetup_pkg, USB_ENUM_ALL_DESCRIPTORS* pusb_all_dscr)
{
    uint8_t*  pBuff;
    uint32_t nDataLen;
    uint32_t nDscrLen;
    uint32_t nReqLen = (psetup_pkg->cLengthH << 0x08) + psetup_pkg->cLengthL;

    switch ( psetup_pkg->cValueH )
    {
    case USB_DSCR_TYPE_DEVICE:
        pBuff    = (uint8_t*)&pusb_all_dscr->dev_dscr;
        nDscrLen = pusb_all_dscr->dev_dscr.cLength;
        nDataLen = MIN(nReqLen, nDscrLen);
        break;

    case USB_DSCR_TYPE_CONFIG:			
        pBuff    =  (uint8_t*)&pusb_all_dscr->config_dscr;
        nDscrLen = (pusb_all_dscr->config_dscr.cTotalLengthH<<0x08) + pusb_all_dscr->config_dscr.cTotalLengthL;
        nDataLen = MIN(nReqLen, nDscrLen); 
        break;

    case USB_DSCR_TYPE_STRING:
        if ( psetup_pkg->cValueL == 0x00 )
        { 
            pBuff    = pusb_all_dscr->pString_dscr_0;
            nDscrLen = pusb_all_dscr->pString_dscr_0[0];
            nDataLen = MIN(nReqLen, nDscrLen);
        }
        else if ( psetup_pkg->cValueL == 0x01 )
        {
            pBuff    = pusb_all_dscr->pString_dscr_1;
            nDscrLen = pusb_all_dscr->pString_dscr_1[0];
            nDataLen = MIN(nReqLen, nDscrLen);
        }
        else if ( psetup_pkg->cValueL == 0x02 )
        {
          
					pBuff    = pusb_all_dscr->pString_dscr_2;
            nDscrLen = pusb_all_dscr->pString_dscr_2[0];
            nDataLen = MIN(nReqLen, nDscrLen);
					 
        }
        else if ( psetup_pkg->cValueL == 0x03 )
        {
            pBuff    = pusb_all_dscr->pString_dscr_3;
            nDscrLen = pusb_all_dscr->pString_dscr_3[0];
            nDataLen = MIN(nReqLen, nDscrLen);
        }
				else
					nDataLen = 0;
        break;

    case USB_DSCR_TYPE_INTERFACE:
        pBuff    =  (uint8_t*)&pusb_all_dscr->infterface_dscr;
        nDscrLen = pusb_all_dscr->infterface_dscr.cLength;
        nDataLen = MIN(nReqLen, nDscrLen);
        break;

    case USB_DSCR_TYPE_ENDPOINT:
        pBuff    =  (uint8_t*)&pusb_all_dscr->endpoint3_dscr;
        nDscrLen = pusb_all_dscr->endpoint3_dscr.cLength * pusb_all_dscr->infterface_dscr.cNumEndpoints;
        nDataLen = MIN(nReqLen, nDscrLen);
        break;

    default:
        USB_StallEp(USB_CONTROL_POINT);
        return;
        
    }

    if ( USB_ControlIn(pBuff, nDataLen) == USB_STATUS_TIMER_OUT )
        USB_StallEp(USB_CONTROL_POINT);
}

void COM_CmdGetMaxLun(void)
{
  uint8_t Buff[2];  
  Buff[0] = 0;
    if ( USB_ControlIn(Buff, 1) == USB_STATUS_TIMER_OUT)
    {
        USB_StallEp(USB_CONTROL_POINT);
    }
}

void COM_CmdMassStorageReset(void)
{
	uint8_t Buff[2];   
	Buff[0] = 0;

    if ( USB_ControlIn(Buff, 0) == USB_STATUS_TIMER_OUT )
    {
        USB_StallEp(USB_CONTROL_POINT);
    }
}


void COM_ProcBulkPkg(void)
{

    uint8_t     RcvBuffer[4]; 
	  uint8_t SendBuffer[4] = {5, 6, 7, 8};
	  uint32_t  UsbStatus;
    UsbStatus = USB_Transfer_Out(RcvBuffer, USB_BULK_OUT_POINT,  sizeof(RcvBuffer));
    if ( UsbStatus != USB_STATUS_OK)	
        goto ERROR_HAPPENED;
    
    SendBuffer[0] = RcvBuffer[0] + 1;
    SendBuffer[1] = RcvBuffer[1] + 1;
    SendBuffer[2] = RcvBuffer[2] + 1;
    SendBuffer[3] = RcvBuffer[3] + 1;        
		UsbStatus =  USB_Transfer_In(SendBuffer, USB_BULK_IN_POINT,sizeof(SendBuffer), sizeof(SendBuffer));
    if ( UsbStatus != USB_STATUS_OK)
        goto ERROR_HAPPENED;     

	return;
		
ERROR_HAPPENED:
 	USB_StallEp(USB_BULK_IN_POINT);

	return;
}
