📄 usbacmlib.c
字号:
if ((pRequest = OSS_CALLOC (sizeof (*pRequest))) == NULL) { status = S_usbAcmLib_OUT_OF_MEMORY; } else { pRequest->callback = (USB_ACM_CALLBACK)callback; pRequest->callbackArg = arg; usbListLink (&reqList, pRequest, &pRequest->reqLink, LINK_TAIL); /* * Perform an initial notification of all currrently * attached modems. */ pSioChan = usbListFirst (&sioList); while (pSioChan != NULL) { if (pSioChan->connected) (*callback) (arg, (SIO_CHAN *) pSioChan, USB_ACM_CALLBACK_ATTACH, NULL, 0); pSioChan = usbListNext (&pSioChan->sioLink); } } OSS_MUTEX_RELEASE (acmMutex); return ossStatus (status); case USB_ACM_CALLBACK_SIO_TX : case SIO_CALLBACK_GET_TX_CHAR : /* Callback for getting Tx Chars : Normal VxWorks SIO Model */ USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, "Tx callback installed \n", 0, 0, 0, 0, 0, 0); pSioChan->callbackStatus |= USB_ACM_CALLBACK_SIO_TX; pSioChan->getTxCharCallback = (FUNCPTR)callback; pSioChan->getTxCharArg = arg; return OK; case USB_ACM_CALLBACK_SIO_RX : case SIO_CALLBACK_PUT_RCV_CHAR : /* Callback for returning rx Chars : Normal VxWorks SIO Model */ USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, "Rx callback installed \n", 0, 0, 0, 0, 0, 0); pSioChan->callbackStatus |= USB_ACM_CALLBACK_SIO_RX; pSioChan->putRxCharCallback = (FUNCPTR)callback; pSioChan->putRxCharArg = arg; return OK; default : return ossStatus (S_usbAcmLib_BAD_PARAM); } return OK; }/**************************************************************************** usbAcmCallbackRemove - De-Registers a callback for an event.** This function removess a (previously installed) <callback> callback routine * for a <callbackType> event. ** Though this function provides a way to remove the callbacks even for the* transmit and receive functionality, it is adviced that these callbacks be* not removed. Note that the <pChan> paramter shall be NULL for the Dynamic * attachment notification requests, indicating that the event is not for any * particular device. Similary, <callback> can be NULL for all the other * events other than the dynamic attachment / removal events.** Different <callbackType> events suppoted by this driver are mentioned in * usbAcmCallbackRegister. Please refer to the corresponding entry.** RETURNS: OK, or ERROR if unable to remove a callback.** ERRNO : * S_usbAcmLib_BAD_PARAM* S_usbAcmLib_NOT_REGISTERED**/STATUS usbAcmCallbackRemove ( SIO_CHAN * pChan, /* Channel for de-registering callbacks */ UINT callbackType, /* Event the call back is to be removed */ USB_ACM_CALLBACK callback /* callback to be unregistered */ ) { pUSB_ACM_SIO_CHAN pSioChan = (pUSB_ACM_SIO_CHAN)pChan; pATTACH_REQUEST pRequest; int status = OK; /* Check for the validity of the input paramaters */ if ((callbackType != USB_ACM_CALLBACK_ATTACH) && (callbackType != USB_ACM_CALLBACK_DETACH)) { /* * Except for attachment/removal requests, pChan should never * be Null */ if (pSioChan == NULL) return ossStatus (S_usbAcmLib_BAD_PARAM); /* Check if there is a callback for this event. */ if ((pSioChan->callbackStatus & callbackType) == 0) return ossStatus (S_usbAcmLib_NOT_REGISTERED); /* De-Register the callback.*/ pSioChan->callbackStatus &= ~callbackType; /* Thats all required , return now.*/ return OK; } if (callback == NULL) return ossStatus (S_usbAcmLib_BAD_PARAM); status = S_usbAcmLib_NOT_REGISTERED; OSS_MUTEX_TAKE (acmMutex, OSS_BLOCK); pRequest = usbListFirst (&reqList); while (pRequest != NULL) { if (callback == pRequest->callback) { /* We found a matching notification request. */ destroyAttachRequest (pRequest); status = OK; break; } pRequest = usbListNext (&pRequest->reqLink); } OSS_MUTEX_RELEASE (acmMutex); return ossStatus (status); }/***************************************************************************** usbAcmSioChanLock - Marks SIO_CHAN structure as in use** A caller uses usbAcmSioChanLock() to notify usbAcmLib that* it is using the indicated SIO_CHAN structure. usbAcmLib maintains* a count of users using a particular SIO_CHAN structure so that it * knows when it is safe to dispose of a structure when the underlying* USB Modem is removed from the system. As long as the "lock count"* is greater than zero, usbAcmLib will not dispose of an SIO_CHAN* structure.** RETURNS: OK, or ERROR if unable to mark SIO_CHAN structure in use.*/STATUS usbAcmSioChanLock ( SIO_CHAN *pChan /* SIO_CHAN to be marked as in use */ ) { pUSB_ACM_SIO_CHAN pSioChan = (pUSB_ACM_SIO_CHAN) pChan; pSioChan->lockCount++; return OK; }/***************************************************************************** usbAcmSioChanUnlock - Marks SIO_CHAN structure as unused** This function releases a lock placed on an SIO_CHAN structure. When a* caller no longer needs an SIO_CHAN structure for which it has previously* called usbAcmSioChanLock(), then it should call this function to* release the lock.** NOTE: If the underlying USB Modem device has already been removed* from the system, then this function will automatically dispose of the* SIO_CHAN structure if this call removes the last lock on the structure.* Therefore, a caller must not reference the SIO_CHAN again structure after* making this call.** RETURNS: OK, or ERROR if unable to mark SIO_CHAN structure unused** ERRNO: S_usbAcmLib_NOT_LOCKED**/STATUS usbAcmSioChanUnlock ( SIO_CHAN *pChan /* SIO_CHAN to be marked as unused */ ) { pUSB_ACM_SIO_CHAN pSioChan = (pUSB_ACM_SIO_CHAN) pChan; int status = OK; OSS_MUTEX_TAKE (acmMutex, OSS_BLOCK); if (pSioChan->lockCount == 0) status = S_usbAcmLib_NOT_LOCKED; else { /* * If this is the last lock and the underlying USB modem is * no longer connected, then dispose of the acm struct. */ if (--pSioChan->lockCount == 0 && !pSioChan->connected) destroySioChan (pSioChan); } OSS_MUTEX_RELEASE (acmMutex); return ossStatus (status); }/***************************************************************************** initiateOutput - initiates SIO model data transmission to modem.** If the output IRP is not already in use, this function fills the output* buffer by invoking the "tx char callback". If at least one character is* available for output, the function then initiates the output IRP.** RETURNS: OK, or ERROR if unable to initiate transmission** NOMANUAL*/STATUS initiateOutput ( pUSB_ACM_SIO_CHAN pSioChan ) { pUSB_IRP pIrp = &pSioChan->outIrp; UINT16 count; /* Return immediately if the output IRP is already in use. */ if (pSioChan->outIrpInUse) { logMsg(" OutIrp in Use..\n",0,0,0,0,0,0); return ERROR; } /* If there is no tx callback, return an error */ if (pSioChan->getTxCharCallback == NULL) { logMsg("No TxCallback \n",0,0,0,0,0,0); return ERROR; } /* * Fill the output buffer until it is full or until the tx callback * has no more data. Return if there is no data available. */ count = 0; USB_ACM_LOG(USB_ACM_DEBUG_TX," Preparing data \n",0,0,0,0,0,0); while (count < pSioChan->outBfrLen && (*pSioChan->getTxCharCallback) (pSioChan->getTxCharArg, &pSioChan->outBfr [count]) == OK) { count++; } if (count == 0) return OK; /* Initialize IRP */ memset (pIrp, 0, sizeof (*pIrp)); pIrp->userPtr = pSioChan; pIrp->irpLen = sizeof (*pIrp); pIrp->userCallback = usbAcmTxIrpCallback; pIrp->timeout = 2000; pIrp->transferLen = count; pIrp->bfrCount = 1; pIrp->bfrList [0].pid = USB_PID_OUT; pIrp->bfrList [0].pBfr = pSioChan->outBfr; pIrp->bfrList [0].bfrLen = count; USB_ACM_LOG(USB_ACM_DEBUG_TX," Irp framed %d bytes\n",count,0,0,0,0,0); pSioChan->outIrpInUse = TRUE; /* This is a MUST */ /* Submit IRP */ if (usbdTransfer (usbdHandle, pSioChan->outPipeHandle, pIrp) != OK) return ERROR; USB_ACM_LOG(USB_ACM_DEBUG_TX," Data.submitted for tx \n",0,0,0,0,0,0); /* Wait for IRP to complete or cancel by timeout */ if ( OSS_SEM_TAKE (acmIrpSem, 2000 + 1000) == ERROR ) { printf ("ACM:initiateOutput: Fatal Error \n"); } USB_ACM_LOG(USB_ACM_DEBUG_TX," returning \n",0,0,0,0,0,0); return OK; }/***************************************************************************** listenForInput - Initialize IRP to listen for input from Modem** RETURNS: OK, or ERROR if unable to submit IRP to listen for input*/LOCAL STATUS listenForInput ( pUSB_ACM_SIO_CHAN pSioChan ) { pUSB_IRP pIrp = &pSioChan->inIrp; /* Initialize IRP */ memset (pIrp, 0, sizeof (*pIrp)); pIrp->userPtr = pSioChan; pIrp->irpLen = sizeof (*pIrp); pIrp->userCallback = usbAcmRxIrpCallback; pIrp->timeout = USB_TIMEOUT_NONE; pIrp->transferLen = pSioChan->inBfrLen; pIrp->bfrCount = 1; pIrp->bfrList [0].pid = USB_PID_IN; pIrp->bfrList [0].pBfr = (pUINT8) &pSioChan->inBfr; pIrp->bfrList [0].bfrLen = pSioChan->inBfrLen; pSioChan->inIrpInUse = TRUE; /* Submit IRP */ if (usbdTransfer (usbdHandle, pSioChan->inPipeHandle, pIrp) != OK) return ERROR; return OK; }/***************************************************************************** usbAcmTxIrpCallback - Invoked upon IRP completion/cancellation** Examines the cause of the IRP completion and re-submits the IRP.** RETURNS: N/A*/LOCAL VOID usbAcmTxIrpCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSB_ACM_SIO_CHAN pSioChan = pIrp->userPtr; pSioChan->outIrpInUse = FALSE; if (pIrp->result != OK) pSioChan->outErrors++; /* * If a Block transmission occured, we just return. Otherwise * we'll see if some more data is to be transmitted. */ if (pSioChan->callbackStatus | USB_ACM_CALLBACK_BLK_TX) { pSioChan->callbackStatus &= ~USB_ACM_CALLBACK_BLK_TX; } OSS_SEM_GIVE (acmIrpSem); }/***************************************************************************** usbAcmRxIrpCallback - Invoked upon IRP completion/cancellation** Examines the cause of the IRP completion and re-submits the IRP.** RETURNS: N/A*/LOCAL VOID usbAcmRxIrpCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSB_ACM_SIO_CHAN pSioChan = pIrp->userPtr; UINT16 count; USB_ACM_LOG(USB_ACM_DEBUG_RX," RxCallBack \n",0,0,0,0,0,0); /* Input IRP completed */ pSioChan->inIrpInUse = FALSE; if (pIrp->result != OK) pSioChan->inErrors++; /* * If the IRP was successful then pass the data back to the client. */ if (pIrp->result == OK) { /* * How to pass the data to clients? If a BlockRxCallback is installed, * then that callback shall be used to send back the data. Otherwise * it shall be the Vxworks SIO model callback */ /* Its the normal VxWorks SIO model now */ USB_ACM_LOG(USB_ACM_DEBUG_RX," Passing data up \n",0,0,0,0,0,0); if (pSioChan->putRxCharCallback == NULL) { logMsg("ACM: Rx Callback Null!!!\n",0,0,0,0,0,0); ossStatus (S_usbAcmLib_NOT_REGISTERED); return; } for (count = 0; count < pIrp->bfrList [0].actLen; count++) { (*pSioChan->putRxCharCallback) (pSioChan->putRxCharArg, pIrp->bfrList [0].pBfr [count]); } } /* * Unless the IRP was cancelled - implying the channel is being * shutdown, re-initiate the "in" IRP to listen for more data from * the modem. */ USB_ACM_LOG(USB_ACM_DEBUG_RX," Passing data up ..done \n",0,0,0,0,0,0); if (pIrp->result != S_usbHcdLib_IRP_CANCELED) listenForInput (pSioChan); } /***************************************************************************** usbAcmCtrlCmdSend - Sends a Control command to the Modem.** This function sends an AT command to the modem. The response to the command* will be passed to the client via a previously installed callback for the* Modem response.** RETURNS: OK or ERROR if the command could not be sent.**/LOCAL STATUS usbAcmCtrlCmdSend ( pUSB_ACM_SIO_CHAN pSioChan, /* Modem reference */ UINT16 request, /* Command to send */ UINT8 * pBuf, /* Modem command buffer */ UINT16 count /* no of bytes in command */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -