📄 usbdcorelib.c
字号:
/* defines */#define USBD_VERSION 0x0001 /* USBD version in BCD */#define USBD_MFG "Zhao house Systems, Inc." /* USBD Mfg */#define INTERNAL_CLIENT_NAME "usbd"/* includes */#include "usb/usbPlatform.h"#include "string.h"#include "usb/ossLib.h"#include "usb/usbQueueLib.h"#include "usb/usbLib.h" /* USB utility functions */#include "usbdCoreLib.h" /* our API */#include "drv/usb/usbHcd.h" /* HCD interface */#include "usb/usbHcdLib.h" /* HCD function library */#include "usb/usbdStructures.h" /* usbdCoreLib data structures *//* defines */#define PENDING 1#define CALLBACK_Q_DEPTH 128 /* Needs to be fairly deep to handle */ /* a potentially large number of */ /* notification callbacks */#define BUS_Q_DEPTH 32 /* Outstanding bus service requests *//* clientThread request codes...stored in msg field of OSS_MESSAGE. */#define CALLBACK_FNC_TERMINATE 0 /* Terminate the callback thread */#define CALLBACK_FNC_IRP_COMPLETE 1 /* issue an IRP completion callback */#define CALLBACK_FNC_NOTIFY_ATTACH 2 /* issue an attach callback */#define CALLBACK_FNC_MNGMT_EVENT 3 /* management event callback */#define CALLBACK_TIMEOUT 5000 /* Wait 5 seconds for callback to */ /* exit in response to terminate fnc *//* busThread request codes...stored in msg field of OSS_MESSAGE. */#define BUS_FNC_TERMINATE 0 /* Terminate the bus monitor thread */#define BUS_FNC_UPDATE_HUB 1 /* update a hub */#define BUS_TIMEOUT 5000 /* Wait 5 seconds for bus monitor */ /* thread to terminate *//* general timeout */#define IO_TIMEOUT 5000 /* 5 seconds */#define EXCLUSION_TIMEOUT 10000 /* 10 seconds *//* HUB_STATUS_LEN() returns length of status structure for indicated hub node */#define HUB_STATUS_LEN(pNode) \ min ((pNode->numPorts + 1 + 7) / 8, (int) MAX_HUB_STATUS_LEN)/* Constants used by resetDataToggle(). */#define ANY_CONFIGURATION 0xffff#define ANY_INTERFACE 0xffff#define ANY_ENDPOINT 0xfffftypedef struct notification { USBD_ATTACH_CALLBACK callback; /* client's callback routine */ USBD_NODE_ID nodeId; /* node being attached/removed */ UINT16 attachCode; /* attach code */ UINT16 configuration; /* config matching notify request */ UINT16 interface; /* interface matching notify request */ UINT16 deviceClass; /* device/interface class */ UINT16 deviceSubClass; /* device/interface sub class */ UINT16 deviceProtocol; /* device/interface protcol */ } NOTIFICATION, *pNOTIFICATION;/* locals */LOCAL int initCount = 0;LOCAL MUTEX_HANDLE structMutex = NULL; /* guards USBD structures */LOCAL LIST_HEAD hcdList = {0}; /* List of attached HCDs */LOCAL LIST_HEAD clientList = {0}; /* list of registered clients */LOCAL USBD_CLIENT_HANDLE internalClient = NULL; /* internal client *//* forward declarations */LOCAL BOOL initHubIrp ( pUSBD_NODE pNode );LOCAL pUSBD_NODE createNode ( pUSBD_BUS pBus, /* node's parent bus */ USBD_NODE_ID rootId, /* root id */ USBD_NODE_ID parentHubId, /* parent hub id */ UINT16 parentHubPort, /* parent hub port no */ UINT16 nodeSpeed, /* node speed */ UINT16 topologyDepth /* this node's depth in topology */ );LOCAL BOOL validateClient ( USBD_CLIENT_HANDLE clientHandle, /* client to be validated */ pUSBD_CLIENT *ppClient /* ptr to USBD_CLIENT if valid */ ) { if (usbHandleValidate (clientHandle, USBD_CLIENT_SIG, (pVOID *) ppClient) != OK) return FALSE; return TRUE; }LOCAL BOOL validateNode ( USBD_NODE_ID nodeId, /* Node to be validated */ pUSBD_NODE *ppNode /* ptr to USBD_NODE if valid */ ) { if (usbHandleValidate (nodeId, USBD_NODE_SIG, (pVOID *) ppNode) != OK || (*ppNode)->nodeDeletePending) return FALSE; return TRUE; }LOCAL BOOL validatePipe ( USBD_PIPE_HANDLE pipeHandle, /* pipe to be validated */ pUSBD_PIPE *ppPipe /* ptr to USBD_PIPE if valid */ ) { if (usbHandleValidate (pipeHandle, USBD_PIPE_SIG, (pVOID *) ppPipe) != OK || (*ppPipe)->pipeDeletePending || (*ppPipe)->pNode->nodeDeletePending) return FALSE; return TRUE; }LOCAL int validateUrb ( pVOID pUrb, UINT16 expectedLen, pUSBD_CLIENT *ppClient ) { pURB_HEADER pHeader = (pURB_HEADER) pUrb; if (initCount == 0) return S_usbdLib_NOT_INITIALIZED; if (pHeader->urbLength != expectedLen) return S_usbdLib_BAD_PARAM; if (ppClient != NULL) { if (!validateClient (pHeader->handle, ppClient)) { return S_usbdLib_BAD_HANDLE; } } return OK; }LOCAL int setUrbResult ( pURB_HEADER pUrb, /* Completed URB */ int result /* S_usbdLib_xxxx code */ ) { if (result != PENDING) { pUrb->result = result; if (pUrb->callback != NULL) (*pUrb->callback) (pUrb); } return result; }LOCAL VOID doShutdown (void) { /* unregister any clients which may still be registered */ pUSBD_CLIENT pClient; pUSBD_HCD pHcd; while ((pClient = usbListFirst (&clientList)) != NULL) usbdClientUnregister (pClient->handle); /* detach any HCDs which may still be attached */ while ((pHcd = usbListFirst (&hcdList)) != NULL) usbdHcdDetach (pHcd->attachToken); /* release the structure guard mutex */ if (structMutex != NULL) { OSS_MUTEX_DESTROY (structMutex); structMutex = NULL; } /* Shut down libraries */ usbHandleShutdown (); ossShutdown (); }LOCAL int fncInitialize ( pURB_HEADER pUrb ) { int s = OK; if (initCount == 0) { /* Initialize the osServices library */ if (ossInitialize () != OK) return S_usbdLib_GENERAL_FAULT; if (usbHandleInitialize (0 /* use default */) != OK) { ossShutdown (); return S_usbdLib_GENERAL_FAULT; } ++initCount; /* Initialize the lists of HCDs and clients */ if (OSS_MUTEX_CREATE (&structMutex) != OK) s = S_usbdLib_OUT_OF_RESOURCES; memset (&hcdList, 0, sizeof (hcdList)); memset (&clientList, 0, sizeof (clientList)); } if (s == OK) { /* Register an internal client for hub I/O, etc. */ internalClient = NULL; if (usbdClientRegister (INTERNAL_CLIENT_NAME, &internalClient) != OK) s = S_usbdLib_GENERAL_FAULT; } if (s != OK) { doShutdown (); initCount = 0; } return s; }LOCAL int fncShutdown ( pURB_HEADER pUrb ) { int s; /* validate URB */ if ((s = validateUrb (pUrb, sizeof (*pUrb), NULL)) != OK) return s; if (initCount == 1) doShutdown (); --initCount; return s; }LOCAL VOID clientThread ( pVOID param /* thread parameter */ ) { pUSBD_CLIENT pClient = (pUSBD_CLIENT) param; USB_MESSAGE msg; pUSB_IRP pIrp; pNOTIFICATION pNotification; do { if (usbQueueGet (pClient->callbackQueue, &msg, OSS_BLOCK) != OK) break; switch (msg.msg) { case CALLBACK_FNC_IRP_COMPLETE: pIrp = (pUSB_IRP) msg.lParam; if (pIrp->userCallback != NULL) (*pIrp->userCallback) (pIrp); break; case CALLBACK_FNC_NOTIFY_ATTACH: pNotification = (pNOTIFICATION) msg.lParam; (*pNotification->callback) (pNotification->nodeId, pNotification->attachCode, pNotification->configuration, pNotification->interface, pNotification->deviceClass, pNotification->deviceSubClass, pNotification->deviceProtocol); OSS_FREE (pNotification); break; case CALLBACK_FNC_MNGMT_EVENT: if (pClient->mngmtCallback != NULL) (*pClient->mngmtCallback) (pClient->mngmtCallbackParam, (USBD_NODE_ID) msg.lParam, msg.wParam); break; } } while (msg.msg != CALLBACK_FNC_TERMINATE); /* Mark the callback routine as having terminated. */ OSS_SEM_GIVE (pClient->callbackExit); }LOCAL int doTransferAbort ( pUSBD_PIPE pPipe, /* Pipe owning transfer */ pUSB_IRP pIrp /* IRP to be cancelled */ ) { pPipe->irpBeingDeleted = pIrp; pPipe->irpDeleted = FALSE; if (usbHcdIrpCancel (&pPipe->pNode->pBus->pHcd->nexus, pIrp) != OK) return S_usbdLib_CANNOT_CANCEL; while (!pPipe->irpDeleted) OSS_THREAD_SLEEP (1); return OK; }LOCAL VOID destroyNotify ( pUSBD_NOTIFY_REQ pNotify ) { usbListUnlink (&pNotify->reqLink); OSS_FREE (pNotify); }LOCAL VOID destroyPipe ( pUSBD_PIPE pPipe ) { pUSB_IRP pIrp; pUSBD_BUS pBus; if (pPipe != NULL) { pPipe->pipeDeletePending = TRUE; while ((pIrp = usbListFirst (&pPipe->irps)) != NULL) doTransferAbort (pPipe, pIrp); /* Release bandwidth and notify HCD that the pipe is going away. */ pBus = pPipe->pNode->pBus; pBus->nanoseconds -= pPipe->nanoseconds; usbHcdPipeDestroy (&pBus->pHcd->nexus, pPipe->hcdHandle); /* Unlink pipe from owning client's list of pipes */ if (pPipe->pClient != NULL) usbListUnlink (&pPipe->clientPipeLink); /* Unlink pipe from owning node's list of pipes */ if (pPipe->pNode != NULL) usbListUnlink (&pPipe->nodePipeLink); /* Release pipe handle */ if (pPipe->handle != NULL) usbHandleDestroy (pPipe->handle); OSS_FREE (pPipe); } }LOCAL VOID destroyClient ( pUSBD_CLIENT pClient ) { pUSBD_NOTIFY_REQ pNotify; pUSBD_PIPE pPipe; pUSBD_HCD pHcd; UINT16 busNo; usbListUnlink (&pClient->clientLink); while ((pNotify = usbListFirst (&pClient->notifyReqs)) != NULL) destroyNotify (pNotify); while ((pPipe = usbListFirst (&pClient->pipes)) != NULL) destroyPipe (pPipe); pHcd = usbListFirst (&hcdList); while (pHcd != NULL) { for (busNo = 0; busNo < pHcd->busCount; busNo++) if (pHcd->pBuses [busNo].pSofMasterClient == pClient) pHcd->pBuses [busNo].pSofMasterClient = NULL; pHcd = usbListNext (&pHcd->hcdLink); } if (pClient->callbackThread != NULL) { /* Terminate the client callback thread */ usbQueuePut (pClient->callbackQueue, CALLBACK_FNC_TERMINATE, 0, 0, CALLBACK_TIMEOUT); OSS_SEM_TAKE (pClient->callbackExit, CALLBACK_TIMEOUT); OSS_THREAD_DESTROY (pClient->callbackThread); } if (pClient->callbackQueue != NULL) usbQueueDestroy (pClient->callbackQueue); if (pClient->callbackExit != NULL) OSS_SEM_DESTROY (pClient->callbackExit); if (pClient->handle != NULL) usbHandleDestroy (pClient->handle); OSS_FREE (pClient); }LOCAL int fncClientReg ( pURB_CLIENT_REG pUrb ) { pUSBD_CLIENT pClient; int s; /* validate URB */ if ((s = validateUrb (pUrb, sizeof (*pUrb), NULL)) != OK) return s; /* Create structures/resources/etc., required by new client */ if ((pClient = OSS_CALLOC (sizeof (*pClient))) == NULL) return S_usbdLib_OUT_OF_MEMORY; memcpy (pClient->clientName, pUrb->clientName, USBD_NAME_LEN); if (usbHandleCreate (USBD_CLIENT_SIG, pClient, &pClient->handle) != OK || OSS_SEM_CREATE (1, 0, &pClient->callbackExit) != OK || usbQueueCreate (CALLBACK_Q_DEPTH, &pClient->callbackQueue) != OK || OSS_THREAD_CREATE (clientThread, pClient, OSS_PRIORITY_INHERIT, "tUsbdClnt", &pClient->callbackThread) != OK) s = S_usbdLib_OUT_OF_RESOURCES; else { /* The client was initialized successfully. Add it to the list */ usbListLink (&clientList, pClient, &pClient->clientLink, LINK_TAIL); /* return the client's USBD_CLIENT_HANDLE */ pUrb->header.handle = pClient->handle; } if (s != OK) { destroyClient (pClient); } return s; }LOCAL int fncClientUnreg ( pURB_CLIENT_UNREG pUrb ) { pUSBD_CLIENT pClient; int s; /* validate Urb */ if ((s = validateUrb (pUrb, sizeof (*pUrb), &pClient)) != OK) return s; /* destroy client */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -