📄 xsusbhostapi.c
字号:
/******************************************************************************
**
** COPYRIGHT (C) 2000, 2001, 2002 Intel Corporation.
**
** This software as well as the software described in it is furnished under
** license and may only be used or copied in accordance with the terms of the
** license. The information in this file is furnished for informational use
** only, is subject to change without notice, and should not be construed as
** a commitment by Intel Corporation. Intel Corporation assumes no
** responsibility or liability for any errors or inaccuracies that may appear
** in this document or any software that may be provided in association with
** this document.
** Except as permitted by such license, no part of this document may be
** reproduced, stored in a retrieval system, or transmitted in any form or by
** any means without the express written consent of Intel Corporation.
**
** FILENAME: XsUsbHostAPI.c
**
** PURPOSE: This file contains the OpenHCI driver for any OpenHCI compliant device.
**
** LAST MODIFIED: $Modtime: 7/17/03 1:01p $
******************************************************************************/
/*
*******************************************************************************
* HEADER FILES
*******************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "systypes.h"
#include "timedelays.h"
#include "DM_Debug.h"
#include "DM_Errors.h"
#include "XsUsbHostDrv.h"
#include "XsUsbHostAPI.h"
#include "xllp_udc.h"
#include "xsudc.h"
#include "USBClient.h"
#define USBX_TIMEOUT_FC 1000 // timeout in frames
#define ADDR_OFFSET 1 // port ID offset to form device address
/*----------------------------------------------------------------------
* Simple loopback polling enable
*/
static int loopbackMode = 0;
static int debugUsbNoTimeout = 0;
static int fakeLoopbackTest = 0;
/*----------------------------------------------------------------------
* Host port controller registers
*/
static volatile USB_HostPortRegs_T * hcP;
/*----------------------------------------------------------------------
* Host port communication area, must be in non cached address space
*/
static volatile USB_HostControllerCommunicationArea_T * hccaP;
/*----------------------------------------------------------------------
* Transfer descriptor list, must be in non cached address space
*/
static volatile USB_TransferDescriptor_T * tdListP;
static volatile USB_IsoTransferDescriptor_T * tdIsoListP;
/*----------------------------------------------------------------------
* Endpoint list, must be in non cached address space
*/
static volatile USB_EndpointDescriptor_T * edListP;
/*----------------------------------------------------------------------
* Message buffer list, could be in non cached address space
*/
static char * bufListP;
//static char bufAlloc[USBD_MAX_BUF];
static char * bufAllocP;
/*----------------------------------------------------------------------
* Static endpoints for periodic table, must be in non cached memory
*/
static volatile USB_EndpointDescriptor_T * periodicTableP;
/*----------------------------------------------------------------------
* Device table, can be in any memory
*/
static USBD_Device_T deviceTable[USBD_MAX_DEV];
/*----------------------------------------------------------------------
* Device info table
*/
static USBD_DeviceInfo_T deviceInfoTable[USBD_MAX_DEV_INFO];
/*----------------------------------------------------------------------
* Statistics
*/
typedef struct Usbx_Stats_S {
int controlStarts;
int isoStarts;
int bulkStarts;
int intStarts;
int timeout;
int halted;
int doneLost;
int noTransfer;
int badIsoBuffer;
int noBuffer;
int noDevice;
int noEndpoint;
int badMaxPacket;
int bufferOverflow;
int badDevice;
int badInterface;
int badVersion;
int noSuspend;
int badBuffer;
int haltedReset;
} Usbx_Stats_T;
static Usbx_Stats_T usbxStats;
/*----------------------------------------------------------------------
* Descriptor definitions for debug display
*/
#define offsetof(a,b) (int)&((a*)0)->b
#define Device USB_DeviceDescriptor_T
USBD_DescriptorDefinition_T deviceDescription[] = {
"bLength", offsetof(Device,bLength), 1,
"bDescriptorType", offsetof(Device,bDescriptorType), 1,
"bcdUSB", offsetof(Device,bcdUSB), 2,
"bDeviceClass", offsetof(Device,bDeviceClass), 1,
"bDeviceSubClass", offsetof(Device,bDeviceSubClass), 1,
"bDeviceProtocol", offsetof(Device,bDeviceProtocol), 1,
"bMaxPacketSize0", offsetof(Device,bMaxPacketSize0), 1,
"idVendor", offsetof(Device,idVendor), 2,
"idProduct", offsetof(Device,idProduct), 2,
"bcdDevice", offsetof(Device,bcdDevice), 2,
"iManfacturer", offsetof(Device,iManfacturer), 1,
"iProduct", offsetof(Device,iProduct), 1,
"iSerialNumber", offsetof(Device,iSerialNumber), 1,
"bNumConfigurations", offsetof(Device,bNumConfigurations), 1,
{ 0 }
};
#undef Device
#define Configuration USB_ConfigurationDescriptor_T
USBD_DescriptorDefinition_T configurationDescription[] = {
"bLength", offsetof(Configuration,bLength), 1,
"bDescriptorType", offsetof(Configuration,bDescriptorType), 1,
"wTotalLength", offsetof(Configuration,wTotalLength), 2,
"bNumInterfaces", offsetof(Configuration,bNumInterfaces), 1,
"bConfigurationValue",offsetof(Configuration,bConfigurationValue), 1,
"iConfiguration", offsetof(Configuration,iConfiguration), 1,
"bmBitmap", offsetof(Configuration,bmBitmap), 1,
"bMaxPower", offsetof(Configuration,bMaxPower), 1,
{ 0 }
};
#undef Config
#define Interface USB_InterfaceDescriptor_T
USBD_DescriptorDefinition_T interfaceDescription[] = {
"bLength", offsetof(Interface,bLength), 1,
"bDescriptorType", offsetof(Interface,bDescriptorType), 1,
"bInterfaceNumber", offsetof(Interface,bInterfaceNumber), 1,
"bAlternateSetting", offsetof(Interface,bAlternateSetting), 1,
"bNumEndpoints", offsetof(Interface,bNumEndpoints), 1,
"bInterfaceClass", offsetof(Interface,bInterfaceClass), 1,
"bInterfaceSubClass", offsetof(Interface,bInterfaceSubClass), 1,
"bInterfaceProtocol", offsetof(Interface,bInterfaceProtocol), 1,
"iInterface", offsetof(Interface,iInterface), 1,
{ 0 }
};
#undef Interface
#define Endpoint USB_EndpointDescriptorX_T
USBD_DescriptorDefinition_T endpointDescription[] = {
"bLength", offsetof(Endpoint,bLength), 1,
"bDescriptorType", offsetof(Endpoint,bDescriptorType), 1,
"bEndpointAddress", offsetof(Endpoint,bEndpointAddress),1,
"bmAttributes", offsetof(Endpoint,bmAttributes), 1,
"wMaxPacketSize", offsetof(Endpoint,wMaxPacketSize), 2,
"bInterval", offsetof(Endpoint,bInterval), 1,
{ 0 }
};
#undef Endpoint
typedef struct defList_S {
int type;
char * name;
USBD_DescriptorDefinition_T * list;
} defList_T;
#define MAX_DEF 32
defList_T descriptorList[MAX_DEF] = {
UsbDescTypeConfiguration,"Configuration Descriptor",configurationDescription,
UsbDescTypeInterface, "Interface Descriptor", interfaceDescription,
UsbDescTypeEndpoint, "Endpoint Descriptor", endpointDescription,
};
/*----------------------------------------------------------------------
* Clear stats block
*/
static
void clearUsbxStats(void)
{
memset(&usbxStats,0,sizeof(usbxStats));
}
/*----------------------------------------------------------------------
* Check for a registered device callback when the device changes state.
*/
static
void CheckCallback(int state, USBD_Device_T * devP)
{
int i;
for (i=0; i < USBD_MAX_DEV_INFO; i++) {
if ((deviceInfoTable[i].VendorId == devP->VendorId) &&
(deviceInfoTable[i].DeviceId == devP->DeviceId) &&
(deviceInfoTable[i].Callback)) {
deviceInfoTable[i].Callback(state, devP);
}
}
}
/*----------------------------------------------------------------------
* This function will dump a structured region of memory. memcpy is used to
* allow any memory alignment to be used. Note, USB descriptors are NOT
* aligned and can not be used directly in memory unless steps are taken to
* insure their base address alignment. The configuration descriptor is
* particularly troubling because it contains a concatenation of unaligned
* descriptors, yuk!
*/
static
void doStructDump(char * name, void * bufP, USBD_DescriptorDefinition_T * defP)
{
int val;
printf("%s\r\n", name);
while(defP->name) {
val = 0;
memcpy(&val,(char*)bufP+defP->offset,defP->size);
printf(" %s=%d(%x)\r\n",defP->name, val, val);
defP++;
}
}
/*----------------------------------------------------------------------
*
*/
static
void displayDeviceDescriptor(void * bufP)
{
doStructDump("Device Descriptor",bufP,deviceDescription);
}
/*----------------------------------------------------------------------
*
*/
static
void displayUnknownDescriptor(USB_GenericDescriptor_T * gP)
{
char * p = (char*)gP;
char buffer[64];
int i;
printf("Unknown %d(%x) Descriptor\r\n",
gP->bDescriptorType,
gP->bDescriptorType);
buffer[0] = '\0';
for (i=0; i < gP->bLength; i++) {
sprintf(buffer,"%s %02X ", buffer, p[i]);
if ((i % 8) == 7) {
printf("%s\r\n", buffer);
buffer[0] = '\0';
}
}
if ((i % 8) != 0)
printf("%s\r\n", buffer);
}
/*----------------------------------------------------------------------
*
*/
static
defList_T * findDescriptorList(int type)
{
int i;
for (i=0; i < MAX_DEF; i++) {
if (descriptorList[i].type == type)
return &descriptorList[i];
}
return NULL;
}
/*----------------------------------------------------------------------
*
*/
static
void displayConfigurationDescriptorAll(int numConfig,
USB_ConfigurationDescriptor_T * confP)
{
USB_GenericDescriptor_T * gP;
defList_T * listP;
int i, j;
for (j=0; j < numConfig; j++) {
gP = (USB_GenericDescriptor_T*)confP;
for(i=0; (i > 0) && (i < confP->wTotalLength); ) {
if ((listP=findDescriptorList(gP->bDescriptorType)) != NULL)
doStructDump(listP->name, (void*)gP, listP->list);
else
displayUnknownDescriptor((USB_GenericDescriptor_T *)gP);
i += gP->bLength;
gP = (USB_GenericDescriptor_T*)((char*)gP + gP->bLength);
}
confP = (USB_ConfigurationDescriptor_T *)gP;
}
}
/*----------------------------------------------------------------------
* Debug function to display a buffer
*/
static
void dumpBuffer(char * p, int length)
{
char buffer[64];
int i;
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Received %d bytes\n", length);
buffer[0] = '\0';
for (i=0; i < length; i++) {
sprintf(buffer,"%s %02X ", buffer, p[i]);
if ((i % 8) == 7) {
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "%s\n", buffer);
buffer[0] = '\0';
}
}
if ((i % 8) != 0)
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "%s\n", buffer);
}
/*----------------------------------------------------------------------
* Function to display a buffer
*/
extern
void XsUsbHostDisplayBuffer(char * banner, char * p, int length)
{
char buffer[64];
int i;
printf("%s %d bytes\r\n", banner, length);
buffer[0] = '\0';
for (i=0; i < length; i++) {
sprintf(buffer,"%s %02X ", buffer, p[i]);
if ((i % 8) == 7) {
printf("%s\r\n", buffer);
buffer[0] = '\0';
}
}
if ((i % 8) != 0)
printf("%s\r\n", buffer);
}
/*----------------------------------------------------------------------
* Debug function to display a list of transfer descriptors
*/
static
void dumpTransferList(USB_TransferDescriptor_T * tdP)
{
while(tdP) {
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "List %08X %08X %08X %08X %08X\n",
tdP,
tdP->Control.d,
tdP->CurrentBufferPointer.p,
tdP->NextTD.p,
tdP->BufferEnd.p);
tdP = tdP->NextTD.p;
}
}
/*----------------------------------------------------------------------
* Get/free message buffers. Very simple allocation mechanism and fixed
* length buffers.
*/
static
void freeBuffer(void * p)
{
int i = ((char*)p - bufListP) / USBD_BUFSIZ;
if ((i < 0) || (i > USBD_MAX_BUF))
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free buffer index out of range, %d\n", i);
else {
// if (!bufAlloc[i])
if (!(*(bufAllocP + i)))
DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Free buffer %d not allocated\n", i);
// bufAlloc[i] = 0;
*(bufAllocP + i) = 0;
}
}
/*----------------------------------------------------------------------
*
*/
static
void * newBuffer(void)
{
int i;
for (i=0; i < USBD_MAX_BUF; i++) {
/*
if (bufAlloc[i] == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -