📄 xsusbhostapi.c
字号:
bufAlloc[i] = 1;
*/
if (*(bufAllocP + i) == 0) {
*(bufAllocP + i) = 1;
return &bufListP[i*USBD_BUFSIZ];
}
}
return NULL;
}
/*----------------------------------------------------------------------
* Get/free general transfer descriptors, init with defaults
*/
static
void freeGeneralTransfer(USB_TransferDescriptor_T * p)
{
if (p->Control.s.Used == 0)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Attempt to free non allocated transfer descriptor!\n");
LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_NODESCRIPTOR, 1, ERR_T_ILLPARAM,
0, 0, 0);
return;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free transfer %x\n", p);
memset(p,0,sizeof(USB_TransferDescriptor_T));
}
/*----------------------------------------------------------------------
*
*/
static
USB_TransferDescriptor_T * newGeneralTransfer (void)
{
int i;
USB_TransferDescriptor_T * this = NULL;
for (i=0; i < USBD_MAX_TD; i++) {
if (!tdListP[i].Control.s.Used) {
this = (USB_TransferDescriptor_T *)&tdListP[i];
break;
}
}
if (this == NULL) {
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "No more transfer descriptors\n");
return NULL;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Allocate transfer %x\n", this);
memset(this,0,sizeof(USB_TransferDescriptor_T));
this->Control.s.Used = 1;
return this;
}
/*----------------------------------------------------------------------
* Get/free isochronous transfer descriptors, init with defaults
*/
static
void freeIsoTransfer(USB_IsoTransferDescriptor_T * p)
{
if (p->Control.s.Used == 0)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Attempt to free non allocated transfer descriptor!\n");
LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_NODESCRIPTOR, 2, ERR_T_ILLPARAM,
0, 0, 0);
return;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free transfer %x\n", p);
memset(p,0,sizeof(USB_IsoTransferDescriptor_T));
}
/*----------------------------------------------------------------------
*
*/
static
USB_IsoTransferDescriptor_T * newIsoTransfer(void)
{
int i;
USB_IsoTransferDescriptor_T * this = NULL;
for (i=0; i < USBD_MAX_TD; i++) {
if (!tdIsoListP[i].Control.s.Used) {
this = (USB_IsoTransferDescriptor_T *)&tdIsoListP[i];
break;
}
}
if (this == NULL) {
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "No more transfer descriptors\n");
return NULL;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Allocate transfer %x\n", this);
memset(this,0,sizeof(USB_IsoTransferDescriptor_T));
this->Control.s.Used = 1;
return this;
}
/*----------------------------------------------------------------------
*
*/
static
void freeGeneralTransferList(USB_TransferDescriptor_T * firstP)
{
USB_TransferDescriptor_T * nextP, * tdP;
for(tdP=firstP->NextTD.p; tdP; tdP = nextP) {
nextP = tdP->NextTD.p;
freeGeneralTransfer(tdP);
}
firstP->NextTD.p = NULL;
}
/*----------------------------------------------------------------------
* Get/free endpoint descriptors, init with defaults
*/
static
void freeEndpoint(USB_EndpointDescriptor_T * p)
{
if (p->Control.s.Used == 0)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Attempt to free non allocated endpoint descriptor!\n");
LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_NODESCRIPTOR, 3, ERR_T_ILLPARAM,
0, 0, 0);
return;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free endpoint %x\n", p);
memset(p,0,sizeof(USB_EndpointDescriptor_T));
}
/*
*******************************************************************************
*
* FUNCTION: newEndpoint
*
* DESCRIPTION: This procedure configures the new endpoint. It gets the pointer
* to the first empty slot in endpoints list, loads the endpoint
* descriptor with a default settings, gets the pointer to the
* new the transfer descriptor and adds it to the TD list.
*
* INPUT PARAMETERS: INT format - indicates the format of the Transfer Descriptor
* linked to the Endpoint descriptor. 0 for General TD and 1 for ISO TD
*
* RETURNS: USB_EndpointDescriptor_T * is a pointer to the Endpoint Descriptor
*
* GLOBAL EFFECTS: none.
*
* ASSUMPTIONS: none.
*
* CALLS: newGeneralTransfer, newIsoTransfer
*
* CALLED BY: addEndpoint
*
* PROTOTYPE: USB_EndpointDescriptor_T * newEndpoint(int format)
*
*******************************************************************************
*/
static
USB_EndpointDescriptor_T * newEndpoint(int format)
{
int i;
USB_EndpointDescriptor_T * this = NULL;
for (i=0; i < USBD_MAX_ED; i++)
{
if (!edListP[i].Control.s.Used)
{
this = (USB_EndpointDescriptor_T *)&edListP[i];
break;
}
}
if (this == NULL)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "No more ED descriptors!\n");
return NULL;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Allocate endpoint %x\n", this);
// Init the endpoint, caller can override these defaults.
memset(this,0,sizeof(USB_EndpointDescriptor_T));
this->Control.s.Used = 1;
this->Control.s.Direction = UsbEDFromTD;
this->Control.s.Format = format;
this->Control.s.MaximumPacketSize = 64; // Default to largest for control
this->Control.s.EndpointId = i;
// Get the pointer to the new TD
if (format)
this->HeadP.ip = newIsoTransfer();
else
this->HeadP.p = newGeneralTransfer();
// Add new TD to the tail of the TD list
this->TailP.p = this->HeadP.p;
this->NextED.p = NULL;
// Return the pointer to the Endpoint Descriptor
return this;
}
/*----------------------------------------------------------------------
* Get/free device descriptors, init with defaults
*/
static
void freeDevice(USBD_Device_T * p)
{
if (p->State == UsbdStateFree)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Attempt to free non allocated device!\n");
LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_BADDEVICE, 1, ERR_T_ILLPARAM,
0, 0, 0);
return;
}
CheckCallback(UsbdStateFree, p);
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free device %x\n", p);
memset(p,0,sizeof(USBD_Device_T));
}
/*
*******************************************************************************
*
* FUNCTION: newDevice
*
* DESCRIPTION: This procedure allocates the memory in the device table,
* returns the pointer to this entry and marks this entry as used
*
* INPUT PARAMETERS: INT portId - Port ID number
*
* RETURNS: USBD_Device_T * is a pinter to new entry in device table
*
* GLOBAL EFFECTS: none.
*
* ASSUMPTIONS: none.
*
* CALLS: none.
*
* CALLED BY: addDevice
*
* PROTOTYPE: USBD_Device_T * newDevice (int portId)
*
*******************************************************************************
*/
static
USBD_Device_T * newDevice (int portId)
{
USBD_Device_T * this = NULL;
if (deviceTable[portId].State == UsbdStateFree)
{
// Set the pointer to the new entry in the table
this = &deviceTable[portId];
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Allocate device %x\n", this);
memset(this,0,sizeof(USBD_Device_T));
// Mark this entry as used by USBD
this->State = UsbdStateUsed;
}
return this;
}
/*----------------------------------------------------------------------
* Remove transfer descriptors from halted (or stopped) endpoint.
*/
static
void clearTDs(USB_EndpointDescriptor_T* edP)
{
USB_TransferDescriptor_T * tdP, * nextP;
int controlListEnable = hcP->HcControl.rw.ControlListEnable;
int bulkListEnable = hcP->HcControl.rw.BulkListEnable;
int oldSkip = edP->Control.s.sKip;
edP->Control.s.sKip = 1;
hcP->HcControl.rw.ControlListEnable = 0;
hcP->HcControl.rw.BulkListEnable = 0;
DM_WaitMs(5);
for (tdP = (USB_TransferDescriptor_T*)(edP->HeadP.s.HeadP << 4);
tdP != edP->TailP.p; tdP = nextP) {
if ((nextP = tdP->NextTD.p) == NULL)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_1, "NULL tail pointer\n");
LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_CLEARTD, 1, ERR_T_ILLPARAM,
0, 0, 0);
break;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Remove TD %x, cc %d\n", tdP, tdP->Control.s.ConditionCode);
freeGeneralTransfer(tdP);
}
/* Reset the head pointer, clear halted and leave ToggleCarry.
*/
edP->HeadP.s.HeadP = (unsigned)edP->TailP.p >> 4;
edP->HeadP.s.Halted = 0;
edP->Control.s.sKip = oldSkip;
hcP->HcControl.rw.ControlListEnable = controlListEnable;
hcP->HcControl.rw.BulkListEnable = bulkListEnable;
}
/*----------------------------------------------------------------------
* Initialize the periodic list. We use a slightly modified algorithm from
* that described in the OHCI spec.
*/
static
void initPeriodicLists()
{
int i, j;
int thisBase;
int nextBase;
for (i=5; i > 0; i--)
{ /* Loop thru all lists (32ms,16ms,8ms,4ms,2ms,1ms) */
thisBase = (1 << i) - 1; /* Base index of this list set */
nextBase = (1 << (i-1)) - 1; /* Base index of next list set */
for (j=0; j < (1 << i); j++)
{ /* Loop thru all lists in this set */
periodicTableP[j + thisBase].NextED.p =
(USB_EndpointDescriptor_T *)&periodicTableP[(j & nextBase) + nextBase];
periodicTableP[j + thisBase].Control.s.sKip = 1;
}
}
periodicTableP[0].Control.s.sKip = 1;
/* Set the base pointers in the HCCA */
for (i=0; i < USB_HCCA_MAX_INT_LIST; i++)
hccaP->HccaInterruptTable[i].p =
(USB_EndpointDescriptor_T *)&periodicTableP[USBD_32MS_BASE+i];
}
/*----------------------------------------------------------------------
* Process descriptors on the done queue
*/
static
void processDoneQueue()
{
USB_TransferDescriptor_T * tdP, * nextP;
USB_IsoTransferDescriptor_T * itdP;
volatile USB_EndpointDescriptor_T * edP;
/* Enable the HC to update again.
*/
tdP = (USB_TransferDescriptor_T*)hccaP->HccaDoneHead.p;
hccaP->HccaDoneHead.p = NULL;
hcP->HcInterruptStatus.rw.WritebackDoneHead = 1;
/* Process the list of descriptors
*/
for (/* Empty */; tdP; tdP = nextP) {
int bytes = 0;
if ((nextP = tdP->NextTD.p) == NULL) {
#if 0 /* Wait until next interrupt */
nextP = (USB_TransferDescriptor_T*)hccaP->HccaDoneHead.p;
hccaP->HccaDoneHead.p = NULL;
hcP->HcInterruptStatus.rw.WritebackDoneHead = 1;
#endif
}
/* Look for control bits cleared problem
*/
if (((unsigned)tdP & 0xffff) == 0)
{
DM_CwDbgPrintf(DM_CW_USB_HOST_0,"TD control bits cleared!\n");
}
/* Cheezy overlay use of format bit ;-) */
if (tdP->Control.s.Format == UsbFormatGeneral)
edP=&edListP[tdP->Control.s.EndpointId];
else
edP=&edListP[((USB_IsoTransferDescriptor_T*)tdP)->Control.s.EndpointId];
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Done q, edp %x, tdp %x, *tdp %x\n", edP, tdP, tdP->Control.d);
/* Get the endpoint reference and handle packet type */
if (edP != NULL) {
/* General packet decrements the outstanding counter (used to indicate
* message complete) and updates the byte transfer counts.
*/
if (edP->Control.s.Format == UsbFormatGeneral) {
edP->TotalOutstandingTD--;
if (tdP->Control.s.DataTransfer) {
if (tdP->CurrentBufferPointer.p) /* zero on success/full buffer */
bytes = ((int)tdP->Control.s.ByteCount -
(int)((char*)tdP->BufferEnd.p+1 -
(char*)tdP->CurrentBufferPointer.p));
else
bytes = (int)tdP->Control.s.ByteCount;
edP->TotalTransferBytes += bytes;
}
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Done general TD %x, cc %d, size %d, bytes %d, reqs %d\n",
tdP,
tdP->Control.s.ConditionCode,
tdP->Control.s.ByteCount,
bytes,
edP->TotalOutstandingTD);
DM_CwDbgPrintf(DM_CW_USB_HOST_0, " cbp %x, be %x\n",
tdP->CurrentBufferPointer.p,
tdP->BufferEnd.p);
/* If this is the last transfer in a message call the completion
* routine. If the endpoint has halted we to call also as there
* will be no more descriptors retired.
*/
if (edP->CompletionFunction) {
int reason = edP->HeadP.s.Halted ? USBD_CompletionHalted :
USBD_CompletionNormal;
edP->CompletionFunction(reason,
tdP,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -