📄 usbtarglib.c
字号:
/* usbTargLib.c - USB Target Library *//* Copyright 2000 Wind River Systems, Inc. *//*Modification history--------------------01d,12apr00,wef Fixed uninitialized variable warning: direction2 in usbTargPipeCreate01c,23nov99,rcb Change #include ../xxx references to lower case.01b,24sep99,rcb Change packet count calculation in usbTargErpCallback() to handle case where a single 0-length packet is transferred.01a,05aug99,rcb First.*//*DESCRIPTIONThis module implements the hardware-independent USB target API.usbTargLib can manage one or more USB TCDs (Target Controller Drivers).usbTargLib provides hardware-independent target services and managementwhile the USB TCDs provide the hardware-dependent USB interface.usbTargLib must be initialized by calling usbTargInitialize(). Beforeoperation can begin, at least one TCD must be attached to usbTargLibby calling usbTargTcdAttach(). In response to a successful TCDattachment, usbTargLib returns a USB_TARG_CHANNEL handle to the caller.This handle must be used in all subsequent calls to usbTargLib toidentify a given target channel.USB devices (targets) almost never initiate activity on the USB (theexception being RESUME signalling). So, as part of the call to usbTargTcdAttach(), the caller must provide a pointer to a USB_TARG_CALLBACK_TABLE structure. This table contains a collection ofcallback function pointers initialized by the caller prior to invokingthe usbTargTcdAttach() function. Through these callbacks, usbTargLibnotifies the calling application of various USB events and requests fromthe host. The calling application is not required to provide callbackfunctions for all possible events. The callback pointers for whichthe calling application has no interest should be NULL.usbTargLib automatically establishes the default control pipe foreach attached target channel and monitors all control pipe requests.If the calling application provides a non-NULL callback for thecorresponding request, usbTargLib invokes the function. If the callbackfunction chooses to handle the control pipe request itself, then itreturns OK, and usbTargLib generally performs no further automaticprocessing. If the callback instead returns FALSE, then usbTargLibhandles the control pipe request automatically using a default behavior.Generally, requests through the control pipe will result in the need forthe target to establish one or more additional pipes to the host. Eachpipe is assigned to a particular endpoint on the device. The callingapplication then submits USB_ERPs (endpoint request packets) which causedata transfers to be performed on specific pipes.*//* includes */#include "usb/usbPlatform.h" /* platform defintions */#include "string.h"#include "usb/ossLib.h" /* o/s services */#include "usb/usb.h" /* general USB definitions */#include "usb/usbListLib.h" /* linked list functions */#include "usb/usbHandleLib.h" /* handle functions */#include "usb/target/usbTcdLib.h" /* interface to USB TCD */#include "usb/target/usbTargLib.h" /* our API *//* defines */#define TARG_VERSION 0x0001 /* TARG version in BCD */#define TARG_MFG "Wind River Systems, Inc." /* TARG Mfg */#define TARG_TCD_SIG ((UINT32) 0xaaaa00cd)#define TARG_PIPE_SIG ((UINT32) 0xaaaa000e)/* Constants used by resetDataToggle(). */#define ANY_CONFIGURATION 0xffff#define ANY_INTERFACE 0xffff#define ANY_ENDPOINT 0xffff#define NO_CONFIGURATION 0xfffe#define NO_INTERFACE 0xfffe#define NO_ENDPOINT 0xfffe/* typedefs *//* TARG_TCD */typedef struct targ_tcd { LINK tcdLink; /* linked list of TCDs */ USB_TARG_CHANNEL targChannel; /* handle allocated for channel */ UINT16 deviceAddress; /* current device address */ pUSB_TARG_CALLBACK_TABLE pCallbacks;/* table of application callbacks */ pVOID callbackParam; /* caller-defined callback param */ TCD_NEXUS tcdNexus; /* our TCD "nexus" */ UINT16 speed; /* target speed: USB_SPEED_xxxx */ UINT16 numEndpoints; /* number of endpoints */ pUSB_TARG_ENDPOINT_INFO pEndpoints; /* ptr to array of endpoints */ LIST_HEAD pipes; /* list of pipes on this target */ USB_TARG_PIPE controlPipe; /* Pipe opened for control channel */ USB_ERP setupErp; /* ERP to receive control pipe setup */ UINT8 setupBfr [sizeof (USB_SETUP)]; /* bfr for control SETUP packet */ BOOL setupErpPending; /* TRUE when ERP is pending */ USB_ERP dataErp; /* ERP to send/receive control data */ UINT8 dataBfr [USB_MAX_DESCR_LEN]; /* bfr for control IN/OUT packet */ BOOL dataErpPending; /* TRUE when ERP is pending */ USB_ERP statusErp; /* ERP to manage status phase packet */ BOOL statusErpPending; /* TRUE when ERP is pending */ } TARG_TCD, *pTARG_TCD;/* TARG_PIPE */typedef struct targ_pipe { LINK pipeLink; /* linked list of pipes */ USB_TARG_PIPE pipeHandle; /* handle allocated for pipe */ pTARG_TCD pTcd; /* TCD for this pipe */ UINT16 configuration; /* configuration associated with pipe */ UINT16 interface; /* interface associated with pipe */ pUSB_TARG_ENDPOINT_INFO pEndpoint; /* ptr to TCD endpoint info */ pUSB_TARG_ENDPOINT_INFO pEndpoint2; /* 2nd endpoint for ctrl pipes */ UINT16 dataToggle; /* current DATA0/DATA1 state */ LIST_HEAD erps; /* list of outstanding ERPs */ pUSB_ERP erpBeingDeleted; /* ptr to ERP with cancel pending */ BOOL erpDeleted; /* TRUE when ERP canceled */ } TARG_PIPE, *pTARG_PIPE;/* locals */LOCAL UINT16 initCount = 0; /* init count nesting */LOCAL BOOL ossInitialized; /* TRUE when ossLib initialized */LOCAL BOOL handleInitialized; /* TRUE when usbHandleLib initialized */LOCAL MUTEX_HANDLE targMutex; /* guards data structures */LOCAL LIST_HEAD tcdList; /* list of attached TCDs *//* forward declarations */LOCAL VOID setupErpCallback (pVOID p);LOCAL VOID responseErpCallback (pVOID p);LOCAL VOID statusErpCallback (pVOID p);/* functions *//***************************************************************************** cancelErp - Cancel an IRP and wait for the ERP callback** RETURNS: OK or S_usbTargLib_xxxx if couldn't cancel ERP*/LOCAL int cancelErp ( pTARG_PIPE pPipe, pUSB_ERP pErp ) { /* Mark ERP being canceled */ pPipe->erpBeingDeleted = pErp; pPipe->erpDeleted = FALSE; /* Try to cancel ERP */ if (usbTcdErpCancel (&pPipe->pTcd->tcdNexus, pErp) != OK) return S_usbTargLib_CANNOT_CANCEL; while (!pPipe->erpDeleted) OSS_THREAD_SLEEP (1); return OK; }/***************************************************************************** mngmtFunc - Invokes target applications mngmtFunc callback.** If there is no mngmtFunc, returns OK.** RETURNS: return code (OK, ERROR) from mngmtFunc.*/LOCAL STATUS mngmtFunc ( pTARG_TCD pTcd, UINT16 mngmtCode ) { if (pTcd->pCallbacks->mngmtFunc == NULL) return OK; return (*pTcd->pCallbacks->mngmtFunc) (pTcd->callbackParam, pTcd->targChannel, mngmtCode); }/***************************************************************************** destroyPipe - Shuts down a pipe and releases its resources** RETURNS: N/A*/LOCAL VOID destroyPipe ( pTARG_PIPE pPipe ) { pUSB_ERP pErp; if (pPipe != NULL) { /* Unlink the pipe */ usbListUnlink (&pPipe->pipeLink); /* Cancel outstanding ERPs */ while ((pErp = usbListFirst (&pPipe->erps)) != NULL) cancelErp (pPipe, pErp); /* Release endpoint(s) assigned to pipe. */ if (pPipe->pEndpoint != NULL) usbTcdEndpointRelease (&pPipe->pTcd->tcdNexus, pPipe->pEndpoint->endpointId); if (pPipe->pEndpoint2 != NULL) usbTcdEndpointRelease (&pPipe->pTcd->tcdNexus, pPipe->pEndpoint2->endpointId); /* release handle */ usbHandleDestroy (pPipe->pipeHandle); OSS_FREE (pPipe); } }/***************************************************************************** destroyTcd - Shuts down a target channel and releases its resources** RETURNS: N/A*/LOCAL VOID destroyTcd ( pTARG_TCD pTcd ) { pTARG_PIPE pPipe; if (pTcd != NULL) { /* Unlink TCD */ usbListUnlink (&pTcd->tcdLink); /* Notify target application that the channel is going down. */ mngmtFunc (pTcd, TCD_MNGMT_DETACH); /* Destroy outstanding pipes */ while ((pPipe = usbListFirst (&pTcd->pipes)) != NULL) destroyPipe (pPipe); /* Detach TCD */ usbTcdDetach (&pTcd->tcdNexus); /* release handle */ if (pTcd->targChannel != NULL) usbHandleDestroy (pTcd->targChannel); ossFree (pTcd); } }/***************************************************************************** validateTarg - validate a target channel and the state of usbTargLib** If <ppTcd> is not NULL, then validate the <targChannel> parameter.* Also checks to make sure usbTargLib has been properly initialized.** RETURNS: OK or ERROR if unable to validate target channel** ERRNO:* S_usbTargLib_NOT_INITIALIZED* S_usbTargLib_BAD_HANDLE*/LOCAL int validateTarg ( USB_TARG_CHANNEL targChannel, pTARG_TCD *ppTcd ) { if (initCount == 0) return ossStatus (S_usbTargLib_NOT_INITIALIZED); if (ppTcd != NULL) { if (usbHandleValidate (targChannel, TARG_TCD_SIG, (pVOID *) ppTcd) != OK) return ossStatus (S_usbTargLib_BAD_HANDLE); } return OK; }/***************************************************************************** validatePipe - validates a pipe handle** RETURNS: OK or ERROR if unable to validate pipe handle** ERRNO:* S_usbTargLib_BAD_HANDLE*/LOCAL STATUS validatePipe ( USB_TARG_PIPE pipeHandle, pTARG_PIPE *ppPipe ) { if (usbHandleValidate (pipeHandle, TARG_PIPE_SIG, (pVOID *) ppPipe) != OK) return ossStatus (S_usbTargLib_BAD_HANDLE); return OK; }/***************************************************************************** findEndpointById - Return pUSB_TARG_ENDPOINT_INFO for endpointId** RETURNS: pointer to USB_TARG_ENDPOINT_INFO or NULL if invalid endpointId*/LOCAL pUSB_TARG_ENDPOINT_INFO findEndpointById ( pTARG_TCD pTcd, UINT16 endpointId ) { pUSB_TARG_ENDPOINT_INFO pEndpoint; UINT16 i; for (i = 0; i < pTcd->numEndpoints; i++) if ((pEndpoint = &pTcd->pEndpoints [i])->endpointId == endpointId) return pEndpoint; return NULL; }/***************************************************************************** validateEndpoint - checks if an endpointId can be used as requested** Checks if <endpointId> is a valid endpoint ID and if the endpoint it* indicates supports the <transferType> and <direction>. If the endpoint* is valid and supports the requested transfer type/direction, then* returns a pointer to the USB_TARG_ENDPOINT_INFO structure for the* endpoint.** RETURNS: OK, or ERROR if unable to validate endpoint** ERRNO:* S_usbTargLib_BAD_PARAM* S_usbTargLib_ENDPOINT_IN_USE*/LOCAL STATUS validateEndpoint ( pTARG_TCD pTcd, UINT16 endpointId, UINT16 transferType, UINT16 direction, pUSB_TARG_ENDPOINT_INFO *ppEndpoint ) { pUSB_TARG_ENDPOINT_INFO pEndpoint; /* Check if endpoint number is valid */ if ((pEndpoint = findEndpointById (pTcd, endpointId)) == NULL) return ossStatus (S_usbTargLib_BAD_PARAM); /* See if the endpointId is in use. */ if ((pEndpoint->flags & TCD_ENDPOINT_IN_USE) != 0) return ossStatus (S_usbTargLib_ENDPOINT_IN_USE); /* See if the endpoint supports the direction */ if (direction == USB_DIR_IN) { if ((pEndpoint->flags & TCD_ENDPOINT_IN_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else if (direction == USB_DIR_OUT) { if ((pEndpoint->flags & TCD_ENDPOINT_OUT_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else return ossStatus (S_usbTargLib_BAD_PARAM); /* See if the endpoint supports the request transfer type */ if (transferType == USB_XFRTYPE_CONTROL) { if ((pEndpoint->flags & TCD_ENDPOINT_CTRL_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else if (transferType == USB_XFRTYPE_BULK) { if ((pEndpoint->flags & TCD_ENDPOINT_BULK_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else if (transferType == USB_XFRTYPE_INTERRUPT) { if ((pEndpoint->flags & TCD_ENDPOINT_INT_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else if (transferType == USB_XFRTYPE_ISOCH) { if ((pEndpoint->flags & TCD_ENDPOINT_ISOCH_OK) == 0) return ossStatus (S_usbTargLib_BAD_PARAM); } else return ossStatus (S_usbTargLib_BAD_PARAM); *ppEndpoint = pEndpoint; return OK; }/***************************************************************************** resetDataToggle - reset data toggle on affected pipes** This function is called when a "configuration event" is detected* for a given node. This function searches all pipes associated with* the node for any that might be affected by the configuration event* and resets their data toggles to DATA0.** RETURNS: N/A*/LOCAL VOID resetDataToggle (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -