?? usbtransunitdata.c
字號:
/* usbTransUnitData.c - Translation Unit Data Transfer Interfaces *//* Copyright 2003 Wind River Systems, Inc. *//*Modification history--------------------01c,15oct04,ami Apigen Changes01o,06oct04,ami Removal of warning messages for SPR #94684 Fix01n,15sep04,hch Fix diab compiler warning01m,24aug04,hch Removed big static arrays in usbdTransfer function01l,03aug04,ami Warning Messages Removed01k,05jul04,??? Short packet flag enabled for vendor specific data transfer01j,12apr04,cfc Apigen fixes01i,17nov03,??? correcting refgen errors.01h,15oct03,cfc Merge from Bangalore, check for NULL ptr01g,30sep03,cfc Fix for dual class driver devices from ODC01f,17sep03,cfc Remove direct calls to wvEvent01e,08sep03,cfc URB callbacks with msgQSend01d,16Jul03,gpd added the status updation and actual transfer length updation of IRP in the callback function.01c,16jun03,mathew prefixed "usb" to file name, and callback routine names.01b,06jun03,mathew Wind View Instrumentation.01a,06jun03,mathew Wind River Coding Convention API changes.*//*DESCRIPTIONImplements the Translation Unit Data Transfer Interfaces.INCLUDE FILES: usbTransUnit.h, usbHcdInstr.h*//* includes */#include "drv/usb/usbTransUnit.h"#include "usb2/usbHcdInstr.h"/* forward declarations */USBHST_STATUS usbtuDataUrbCompleteCallback ( pUSBHST_URB urbPtr );USBHST_STATUS usbtuDataVendorSpecificCallback (pUSBHST_URB urbPtr );/* mutex of Translation Unit */extern MUTEX_HANDLE usbtuMutex;/***************************************************************************** usbdPipeCreate - Creates a USB pipe for subsequent transfers** This function establishes a pipe which can subsequently be used by a* client to exchange data with a USB device endpoint.** <nodeId> and <endpoint> identify the device and device endpoint,* respectively, to which the pipe should be "connected." <configuration>* and <interface> specify the configuration and interface, respectively,* with which the pipe is associated.** <transferType> specifies the type of data transfers for which this pipe* will be used:** \is* \i 'USB_XFRTYPE_CONTROL'* Control transfer pipe (message)** \i 'USB_XFRTYPE_ISOCH'* Isochronous transfer pipe (stream)** \i 'USB_XFRTYPE_INTERRUPT'* Interrupt transfer pipe (stream)** \i 'USB_XFRTYPE_BULK'* Bulk transfer pipe (stream)* \ie** <direction> specifies the direction of the pipe as:** \is* \i 'USB_DIR_IN'* Data moves from device to host** \i 'USB_DIR_OUT'* Data moves from host to device** \i 'USB_DIR_INOUT'* Data moves bidirectionally (message pipes only)* \ie** If the <direction> is specified as USB_DIR_INOUT, the USBD assumes that* both the IN and OUT endpoints identified by endpoint will be used by* this pipe (see the discussion of message pipes in Chapter 5 of the USB* Specification). USB_DIR_INOUT may be specified only for Control pipes.** <maxPayload> specifies the largest data payload supported by this endpoint.* Normally a USB device will declare the maximum payload size it supports on* each endpoint in its configuration descriptors. The client will typically* read these descriptors using the USBD Configuration Functions and then* parse the descriptors to retrieve the appropriate maximum payload value.** <bandwidth> specifies the bandwidth required for this pipe. For control* and bulk pipes, this parameter should be 0. For interrupt pipes, this* parameter should express the number of bytes per frame to be transferred.* for isochronous pipes, this parameter should express the number of bytes* per second to be transferred.** <serviceInterval> specifies the maximum latency for the pipe in* milliseconds. So, if a pipe needs to be serviced, for example, at least* every 20 milliseconds, then the <serviceInterval> value should be 20. The* <serviceInterval> parameter is required only for interrupt pipes. For* other types of pipes, <serviceInterval> should be 0.** If the USBD succeeds in creating the pipe it returns a pipe handle in* <pPipeHandle>. The client must use the pipe handle to identify the pipe* in subsequent calls to the USBD Transfer Functions. If there is* insufficient bus bandwidth available to create the pipe (as might happen* for an isochronous or interrupt pipe), then the USBD will return an error* and a NULL handle in <pPipeHandle>.** RETURNS: OK, or ERROR if pipe could not be create** ERRNO: N/A*/STATUS usbdPipeCreate ( USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_NODE_ID nodeId, /* Node Id of device/hub */ UINT16 endpoint, /* Endpoint address */ UINT16 configuration, /* config w/which pipe associated */ UINT16 interface, /* interface w/which pipe associated */ UINT16 transferType, /* Type of transfer: control, bulk... */ UINT16 direction, /* Specifies IN or OUT endpoint */ UINT16 maxPayload, /* Maximum data payload per packet */ UINT32 bandwidth, /* Bandwidth required for pipe */ UINT16 serviceInterval, /* Required service interval */ pUSBD_PIPE_HANDLE pPipeHandle /* pipe handle returned by USBD */ ) { pUSB_CONFIG_DESCR pCfgDescr; pUSB_INTERFACE_DESCR pIfDescr; pUSB_ENDPOINT_DESCR pEpDescr; UINT8 * pBfr; UINT8 * pScratchBfr; UINT16 actLen; UINT16 ifNo; pUSBTU_PIPE_INFO pipeInfo; pUSBTU_DEVICE_DRIVER pDriver = (pUSBTU_DEVICE_DRIVER) clientHandle; /* Wind View Instrumentation */ if ((usbtuInitWvFilter & USBTU_WV_FILTER) == TRUE) { char evLog[USBTU_WV_LOGSIZE]; strncpy ((char*)evLog, (char *)pDriver->clientName,USBD_NAME_LEN ); strcat(evLog, " : Pipe Create "); USB_HCD_LOG_EVENT(USBTU_WV_CLIENT_TRANSFER, evLog, USBTU_WV_FILTER); } USBTU_LOG ( "usbdPipeCreate entered \n "); if ((pBfr = OSS_CALLOC ( USB_MAX_DESCR_LEN)) == NULL) { USBTU_LOG ( "usbdPipeCreate returns ERROR : malloc failed \n "); return ERROR; } /* Read the configuration descriptor */ if (usbdDescriptorGet (clientHandle, nodeId, USB_RT_DEVICE, USB_DESCR_CONFIGURATION, 0, 0, USB_MAX_DESCR_LEN, pBfr, &actLen) != OK) { OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns ERROR: usbdDescriptorGet failed \n"); return ERROR; } if ((pCfgDescr = usbDescrParse (pBfr, actLen, USB_DESCR_CONFIGURATION)) == NULL) { OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns ERROR : usbDescrParse failed \n "); return ERROR; } /* Look for the interface */ ifNo = 0; /* * usbDescrParseSkip() modifies the value of the pointer it recieves * so we pass it a copy of our buffer pointer */ pScratchBfr = pBfr; while ((pIfDescr = usbDescrParseSkip (&pScratchBfr, &actLen, USB_DESCR_INTERFACE)) != NULL) { if (ifNo == interface) break; ifNo++; } if (pIfDescr == NULL) { OSS_FREE (pBfr); return ERROR; } /* get the endpoint descriptor */ while ((pEpDescr = usbDescrParseSkip (&pScratchBfr, &actLen, USB_DESCR_ENDPOINT)) != NULL) { if (pEpDescr->endpointAddress == endpoint) break; } if (pEpDescr == NULL) { OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns ERROR : usbDescrParseSkip1 failed\n"); return ERROR; } /* Check to make sure the max packet size is in the byte order endian */ pEpDescr->maxPacketSize = OS_UINT16_LE_TO_CPU(pEpDescr->maxPacketSize); /* check the maximum payload */ if (pEpDescr->maxPacketSize > maxPayload) { OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns ERROR : bandwidth not available\n "); return ERROR; } /* allocate a structure for the pipe */ if ( !(pipeInfo = OSS_CALLOC( sizeof (USBTU_PIPE_INFO)))) { OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns ERROR: malloc1 failed \n "); return ERROR; } /* initialize the pipe structure */ pipeInfo->hDevice = (UINT32)nodeId; pipeInfo->endpointAddress = pEpDescr->endpointAddress; pipeInfo->transferType = transferType; pipeInfo->irpList = NULL; pipeInfo->markedForDeletion = 0; pipeInfo->uMaxPacketSize = maxPayload; pipeInfo->bandwidth = bandwidth; /* Return result */ if (pPipeHandle != NULL) *pPipeHandle = pipeInfo; OSS_FREE (pBfr); USBTU_LOG ( "usbdPipeCreate returns OK \n "); return OK; }/***************************************************************************** usbdPipeDestroy - Destroys a USB data transfer pipe** This function destroys a pipe previous created by calling usbdPipeCreate().* The caller must pass the <pipeHandle> originally returned by usbdPipeCreate().*** RETURNS: OK, or ERROR if unable to destroy pipe.** ERRNO: N/A*/STATUS usbdPipeDestroy ( USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_PIPE_HANDLE pipeHandle /* pipe handle */ ) { pUSBTU_PIPE_INFO pipeInfo = (pUSBTU_PIPE_INFO) pipeHandle; pUSBTU_DEVICE_DRIVER pDriver = (pUSBTU_DEVICE_DRIVER) clientHandle; STATUS status; /* Wind View Instrumentation */ if ((usbtuInitWvFilter & USBTU_WV_FILTER) == TRUE) { char evLog[USBTU_WV_LOGSIZE]; strncpy ((char*)evLog,(char *)pDriver->clientName,USBD_NAME_LEN ); strcat(evLog, " : Pipe Destroy "); USB_HCD_LOG_EVENT(USBTU_WV_CLIENT_TRANSFER, evLog, USBTU_WV_FILTER); } USBTU_LOG ( "usbdPipeDestroy entered \n "); /* release the pipe structure */ if (pipeHandle == NULL) { USBTU_LOG ( "usbdPipeDestroy returns ERROR \n "); return ERROR; } /* Access the mutex */ OSS_MUTEX_TAKE (usbtuMutex, OSS_BLOCK); /* Indicate that pipe is marked for deletion * This is to ensure that IRP callback does not resubmit IRP while pipe * is being deleted */ pipeInfo->markedForDeletion = 1; /* If there are requests queued for the pipe, create the semaphore * which will be signalled by the callback * if the cancellation is not successful */ if (pipeInfo->irpList) { pipeInfo->PipeDelete = semBCreate (SEM_Q_FIFO,SEM_EMPTY); /* Check if sem creation is successful */ if (pipeInfo->PipeDelete == NULL) { USBTU_LOG("usbdPipeDestroy-Pipe deletion sem not created \n "); OSS_MUTEX_RELEASE (usbtuMutex); return ERROR; } } /* Search through the list of IRPs and cancel all of them */ while(pipeInfo->irpList != NULL) { /* Call the function to cancel the IRP */ status = usbdTransferAbort( clientHandle, pipeHandle ,pipeInfo->irpList->pIrp); /* The status can be an error * 1. if the parameters are not valid * or * 2. if the transfer is already completed. * We ignore the first case, as it is ensured that the * parameters are valid. * This check will be pass only if the transfer is already completed. */ if (status == ERROR) { /* Release the mutex. This is done as the mutex will be * taken by the completion routine also */ OSS_MUTEX_RELEASE (usbtuMutex); /* Wait for the pipe deletion semaphore to be signalled from the * completion routine */ semTake(pipeInfo->PipeDelete ,WAIT_FOREVER); /* Release the mutex */ OSS_MUTEX_TAKE (usbtuMutex, OSS_BLOCK); } } /* Delete the semaphore created */ if(pipeInfo->PipeDelete) semDelete(pipeInfo->PipeDelete); /* Release the acquired mutex */ OSS_MUTEX_RELEASE (usbtuMutex); OSS_FREE( pipeHandle); USBTU_LOG ( "usbdPipeDestroy returns OK \n "); return OK; }/***************************************************************************** usbdTransfer - Initiates a transfer on a USB pipe** A client uses this function to initiate an transfer on the pipe indicated* by <pipeHandle>. The transfer is described by an IRP, or I/O request* packet, which must be allocated and initialized by the caller prior to* invoking usbdTransfer().** The USB_IRP structure is defined in usb.h as:** \cs* typedef struct usb_bfr_list* {* UINT16 pid;* pUINT8 pBfr;* UINT16 bfrLen;* UINT16 actLen;* } USB_BFR_LIST;** typedef struct usb_irp* {* LINK usbdLink; // used by USBD* pVOID usbdPtr; // used by USBD* LINK hcdLink; // used by HCD* pVOID hcdPtr; // used by HCD* pVOID userPtr;* UINT16 irpLen;* int result; // returned by USBD/HCD* IRP_CALLBACK usbdCallback; // used by USBD* IRP_CALLBACK userCallback;* UINT16 dataToggle; // filled in by USBD* UINT16 flags;* UINT32 timeout; // defaults to 5 seconds if zero* UINT16 startFrame;* UINT16 transferLen;* UINT16 dataBlockSize;* UINT16 bfrCount;* USB_BFR_LIST bfrList [1];* } USB_IRP, *pUSB_IRP;* \ce** The length of the USB_IRP structure must be stored in <irpLen> and varies* depending on the number of <bfrList> elements allocated at the end of the* structure. By default, the default structure contains a single <bfrList>* element, but clients may allocate a longer structure to accommodate a larger* number of <bfrList> elements.** <flags> define additional transfer options. The currently defined flags are:** \is* \i 'USB_FLAG_SHORT_OK'* Treats receive (IN) data underrun as OK** \i 'USB_FLAG_SHORT_FAIL'* Treats receive (IN) data underrun as error** \i 'USB_FLAG_ISO_ASAP'* Start an isochronous transfer immediately* \ie** When the USB is transferring data from a device to the host the data may* "underrun". That is, the device may transmit less data than anticipated by* the host. This may or may not indicate an error condition depending on the* design of the device. For many devices, the underrun is completely normal* and indicates the end of data stream from the device. For other devices,* the underrun indicates a transfer failure. By default, the USBD and* underlying USB HCD (Host Controller Driver) treat underrun as the end-of-data* indicator and do not declare an error. If the USB_FLAG_SHORT_FAIL flag is* set, then the USBD/HCD will instead treat underrun as an error condition.** For isochronous transfers the USB_FLAG_ISO_ASAP specifies that the* isochronous transfer should begin as soon as possible. If USB_FLAG_ISO_ASAP* is not specified, then <startFrame> must specify the starting frame number* for the transfer. The usbdCurrentFrameGet() function allows a client to* retrieve the current frame number and a value called the frame scheduling
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -