📄 td1120p.c
字号:
urb->lengthSoFar += size;
/* Transfer finished, no more data */
if (urb->dataPosition >= urb->length)
{
if (!(urb->dataPosition % ep->maxPktSize))
{
/* There will be no "done" interrupt because the last packet
is not less than maxpacketsize
*/
TD1120P_EpTransferDone(pc, ep->epNumber, ISOUT);
}
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
return;
}
/* Get the received bytes from EP descriptor */
size = TD1120P_GetReceivedByteCount(pc->ioBase, ep->epNumber);
if (!size)
{
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
return;
}
} while (size);
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
}
/*------------------------------------------------------------------------------
Name : TD1120P_DoEpIn
Purpose : Copy data to chip and update the status after In token completed.
Arguments : dc - Device controller handle
urb - pointer to urb structure
Return : None
Notes :
------------------------------------------------------------------------------*/
void TD1120P_DoEpIn(TdiPeriphController* pc, TdiPurb* urb)
{
volatile U32 filledSize, emptySize, temp;
TdiPeriphEp* ep;
U32 size;
ep = urb->ep;
/* Disable interrupts on the controller */
PCD_DisableControllerIntr(pc);
/* Transfer finished, no more data */
if (urb->dataPosition >= urb->length)
{
if (!(urb->dataPosition % ep->maxPktSize))
{
/* There will be no "done" interrupt because the last packet
is not less than maxpacketsize
*/
TD1120P_EpTransferDone(pc, ep->epNumber, ISIN);
}
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
return;
}
do
{
/* Read the number of bytes in the FIFO */
filledSize = (SYS_Read1120P_Register(pc->ioBase, \
TD1120_DEV_EP_IN_BYTE_COUNT_REG(ep->epNumber)) & \
TD1120_DEV_IN_BYTE_COUNT_MASK);
emptySize = ep->controllerBufferSize;
if (filledSize)
{
emptySize -= filledSize;
}
if (!emptySize)
{
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
return;
}
size = urb->length - urb->dataPosition;
if (size > emptySize)
{
temp = emptySize/ep->maxPktSize;
if (temp)
{
size = (ep->maxPktSize * temp);
}
else
{
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
return;
}
}
/* Write the data to the FIFO */
TD1120P_Write1120Buffer(pc->ioBase, \
TD1120_DEV_EP_IN_FIFO_WRITE(ep->epNumber), ep->epNumber,
(urb->data + urb->dataPosition), size);
urb->dataPosition += size;
urb->lengthSoFar += size;
}
while (urb->length - urb->dataPosition);
/* Enable interrupts on the controller */
PCD_EnableControllerIntr(pc);
}
/*------------------------------------------------------------------------------
Name : TD1120P_DoEpTransfer
Purpose : service routine with Ep1-15
Arguments : pc - peripheral controller handle
epNumber - endpoint number
type - In or Out direction
Return : None
Notes :
------------------------------------------------------------------------------*/
void TD1120P_DoEpTransfer(TdiPeriphController *pc, U32 epNumber, U8 type)
{
TdiPeriphEp *ep;
/* For other endpoints */
ep = pc->ep[epNumber];
if (ep == NULL)
{
return;
}
if (ep->urb == NULL)
{
return;
}
if (type == ISIN)
{
/* send */
TD1120P_DoEpIn((TdiPeriphController *)pc, ep->urb);
}
else if (type == ISOUT)
{
/* recv */
TD1120P_DoEpOut((TdiPeriphController *)pc, ep->urb);
}
}
/*------------------------------------------------------------------------------
Name : TD1120P_GoSuspend
Purpose : set dc suspend.
Arguments : pc - peripheral controller handle
Return : None
Notes :
------------------------------------------------------------------------------*/
void TD1120P_GoSuspend(TdiPeriphController* pc)
{
/* Just notify for now */
pc->isSuspended = SCC_TRUE;
TD1120P_CallEventService(pc, USB_SERVICE_SUSPEND_EVENT, 0);
}
/*------------------------------------------------------------------------------
Name : TD1120P_GoResume
Purpose : set dc back from suspend.
Arguments : pc - peripheral controller handle
Return : None
Notes :
------------------------------------------------------------------------------*/
void TD1120P_GoResume(TdiPeriphController* pc)
{
/* Just notify for now */
pc->isSuspended = SCC_FALSE;
TD1120P_CallEventService(pc, USB_SERVICE_RESUME_EVENT, 0);
}
/*------------------------------------------------------------------------------
Name : TD1120P_Transfer
Purpose : Get ready for a new Urb.
Arguments : pc - peripheral controller handle
urb - pointer to urb structure
Returns : Success
Notes : This function will be called for any endpoint.
Control enpoint will directly call TD1120P_DoEp0XXX by dbase, which
is little confusing.
-----------------------------------------------------------------------------*/
SctStatus TD1120P_Transfer(TdiPeriphController* pc, TdiPurb* urb)
{
U16 pktCount = 0;
TdiPeriphEp *ep;
if (pc == NULL)
{
return SCS_ERROR_INVALID_HANDLE;
}
ep = urb->ep;
if (ep == NULL)
{
return SCS_EP_INVALID;
}
if (urb->direction == USB_REQUEST_DIRECTION_IN)
{
if (urb->length == 0)
{
/* Send zero length packet */
/* Explicitly Validate FIFO */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_VALIDATION_REG, \
((ep->epNumber << 4) | TD1120_DEV_EP_VALID_CODE_0_BYTE));
}
else
{
/* copy data to TD1120 data buffer */
TD1120P_DoEpIn(pc, urb);
}
}
else
{
if (urb->length)
{
pktCount = (urb->length / ep->maxPktSize);
if (urb->length % ep->maxPktSize)
{
pktCount++;
}
}
else
{
pktCount = 1;
}
SYS_Write1120P_Register(pc->ioBase, \
TD1120_DEV_EP_OUT_PKT_COUNT_REG(ep->epNumber), pktCount);
/* Clear OUT NAK so that we can receive packets */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_NAK_CLEAR_REG, \
(1 << urb->ep->epNumber));
}
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_SetTestMode
Purpose : Set Test Mode
Arguments : pc - peripheral controller handle
testMode - test mode
Returns : None
Notes :
-----------------------------------------------------------------------------*/
void TD1120P_SetTestMode(TdiPeriphController* pc, U32 testMode)
{
if (pc->testModePending)
{
if (pc->testModePending == 3)
{
/* Empty the IN endpoint so that it NAKs --- Clear the IN FIFO */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_FIFO_CLEAR_REG, 1);
}
else
{
if (pc->testModePending == 4)
{
pc->testModePending = 3;
/* Initialize the control endpoint 0 */
TD1120P_Configure_EP(pc->ioBase, 1, 0, 1, 64, 64, \
0x100, 0x17C); /* Control EP 0 */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_EN_SET_REG, 0x2);
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_FIFO_CLEAR_REG, 0x2);
TD1120P_Write1120Buffer(pc->ioBase, TD1120_DEV_EP_IN_FIFO_WRITE(1), 1, \
testPacket, 53);
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_ADDRESS_REG, 0x0);
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG, \
TD1120_DEV_CTRL_PSEUDO_SOF_EN);
/* Explicitly Validate FIFO */
}
pc->testModePending |= TD1120_DEV_TEST_MODE_EN;
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_TEST_MODE_REG, pc->testModePending);
}
}
else
{
pc->testModePending = ((testMode & 0xFF00) >> 8);
/* Explicitly Validate FIFO */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_VALIDATION_REG, ((0 << 4) | \
TD1120_DEV_EP_VALID_CODE_0_BYTE));
}
}
/*------------------------------------------------------------------------------
Name : TD1120P_ResetTestMode
Purpose : Reset Test Mode
Arguments : pc - peripheral controller handle
testMode - test mode
Returns : None
Notes :
-----------------------------------------------------------------------------*/
void TD1120P_ResetTestMode(TdiPeriphController* pc, U32 testMode)
{
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_TEST_MODE_REG, 0);
}
/*------------------------------------------------------------------------------
Name : TD1120P_GetSpeed
Purpose : Get the negotiated speed of the peripheral
Arguments : pc - peripheral controller handle
speed - speed of the bus
Returns : None
Notes : This should be called only after bus reset operation is completed.
-----------------------------------------------------------------------------*/
SctStatus TD1120P_GetSpeed(TdiPeriphController* pc, U32* speed)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_GetSpeed: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
*speed = (SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG) & \
TD1120_DEV_CTRL_SPEED);
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_RegisterDescriptor
Purpose : Register the USB descriptors
Arguments : pc - peripheral controller handle
descrType - type of descriptor
descriptor - pointer to descriptor
index - descriptor index
Returns : None
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_RegisterDescriptor(TdiPeriphController* pc, U32 descrType, \
U8* descriptor, U8 index)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_RegisterDescriptor: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
switch (descrType)
{
case USB_DEVICE_DESCRIPTOR:
pc->currentDeviceDescriptor = descriptor;
break;
case USB_CONFIG_DESCRIPTOR:
pc->currentConfigDescriptors[index] = descriptor;
break;
case USB_DEVICE_QUALIFIER_DESCRIPTOR:
pc->deviceQualifierDescriptor = descriptor;
break;
case USB_OTHER_SPEED_CONFIG_DESCRIPTOR:
pc->currentOtherSpeedConfigDescriptors[index] = descriptor;
break;
case USB_STRING_DESCRIPTOR:
pc->stringDescriptors[index] = descriptor;
break;
default:
return (SCS_ERROR);
break;
}
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_IsVBusOn
Purpose : Check whether Vbus is on
Arguments : pc - peripheral controller handle
Return : SCC_TRUE if on, else SCC_FALSE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -