📄 usbpegasusend.c
字号:
/***************************************************************************** pegasusTxCallback - Invoked upon Transmit IRP completion/cancellation** This function is invoked upon Transmit IRP completion/cancellation** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID pegasusTxCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; int index = 0; int nextIndex; PEGASUS_ENET_IRP* pIrpBfr; PEGASUS_DEVICE * pDevCtrl = pIrp->userPtr; /* Output IRP completed */ for (index = 0; index < pDevCtrl->noOfIrps; index++) { pIrpBfr = pDevCtrl->pEnetIrp + index; if (pIrp == &pIrpBfr->outIrp) { break; } } if (index == pDevCtrl->noOfIrps) return; PEGASUS_LOG (PEGASUS_DBG_TX, "Tx Callback for %d IRP.\n", index, 0, 0, 0, 0, 0); END_TX_SEM_TAKE(&pDevCtrl->endObj,WAIT_FOREVER); pIrpBfr = pDevCtrl->pEnetIrp + index; pIrpBfr->outIrpInUse = FALSE; if (pDevCtrl->txStall) { pDevCtrl->txStall = FALSE; /* Notify higher layers we can restart */ netJobAdd ((FUNCPTR) pegasusMuxTxRestart, (int) &pDevCtrl->endObj, 0, 0, 0, 0); PEGASUS_LOG (PEGASUS_DBG_TX_STALL, "pegasusTxCallback: TX IRP available - Called MuxTxRestart() \n", 0, 0, 0, 0, 0, 0); } if (pIrp->result != OK) { PEGASUS_LOG (PEGASUS_DBG_TX, "Tx error %x.\n", pIrp->result, 0, 0, 0, 0, 0); if (pIrp->result == S_usbHcdLib_STALLED) { if (usbdFeatureClear (pegasusHandle, pDevCtrl->pDev->nodeId, USB_RT_STANDARD | USB_RT_ENDPOINT, 0, 1) == ERROR) { PEGASUS_LOG (PEGASUS_DBG_TX, "Could not clear STALL.\n", pIrp->result, 0, 0, 0, 0, 0); } } pDevCtrl->outErrors++; /* Should also Update MIB */ } else { PEGASUS_LOG (PEGASUS_DBG_TX, "Tx finished.\n", 0, 0, 0, 0, 0, 0); } nextIndex = (index+1) % pDevCtrl->noOfIrps; pIrpBfr = pDevCtrl->pEnetIrp + nextIndex; if (pIrpBfr->outIrpInUse) { PEGASUS_LOG (PEGASUS_DBG_TX_STALL, "pegasusSend: Submitting queued IRP %d %x %d\n", nextIndex, (int)(&pIrpBfr->outIrp), pIrpBfr->outIrp.transferLen, 0, 0, 0); usbdTransfer(pegasusHandle, pDevCtrl->outPipeHandle, &pIrpBfr->outIrp); } else { PEGASUS_LOG (PEGASUS_DBG_TX_STALL, "pegasusSend: No More IRP's\n", 0, 0, 0, 0, 0, 0); pDevCtrl->txActive = FALSE; } END_TX_SEM_GIVE(&pDevCtrl->endObj); }/***************************************************************************** pegasusRxCallback - Invoked when a Packet is received.** This function is invoked wheb a packet is received** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID pegasusRxCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; PEGASUS_DEVICE * pDevCtrl = pIrp->userPtr; /* Input IRP completed */ pDevCtrl->inIrpInUse = FALSE; /* * If the IRP was successful then pass the data back to the client. * Note that the netJobAdd() is not necessary here as the function * is not getting executed in isr context. */ if (pIrp->result != OK) { pDevCtrl->inErrors++; /* Should also update MIB */ if(pIrp->result == S_usbHcdLib_STALLED) { if (usbdFeatureClear (pegasusHandle,pDevCtrl->pDev->nodeId, USB_RT_STANDARD | USB_RT_ENDPOINT, 0, 0) != OK) return; } } else { if( pIrp->bfrList [0].actLen >= 2) { pegasusEndRecv (pDevCtrl,pIrp->bfrList [0].pBfr, pIrp->bfrList [0].actLen); pDevCtrl->rxIndex++; pDevCtrl->rxIndex %= pDevCtrl->noOfInBfrs; } } /* * Unless the IRP was cancelled - implying the channel is being * torn down, re-initiate the "in" IRP to listen for more data from * the printer. */ if (pIrp->result != S_usbHcdLib_IRP_CANCELED) pegasusListenForInput (pDevCtrl); }/***************************************************************************** pegasusMchash - computing the Pegasus multicast hash table value.** The Pegasus has a 64-bit multicast hash table filter. The filter is* accessed via register 0x08 to 0x0F. The bits in the filter are set by * running the multicast address you want to receive through a little-endian * CRC-32 and then masking off all but the lower 6 bits. The resulting value * tells which bit in the 64 bit table to set. ** RETURNS : The hash table value for the multicast address** ERRNO: none** \NOMANUAL*/LOCAL int pegasusMchash ( UINT8 * addr ) { UINT32 crc; int idx, bit; UINT8 data; /* Compute CRC for the address value. */ crc = 0xFFFFFFFF; /* initial value */ /* the little-endian CRC-32 algorithm */ for (idx = 0; idx < 6; idx++) { for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) crc = (crc >> 1) ^ (((crc ^ data) & 1) ? PEGASUS_POLY : 0); } /* masking off all but the lower 6 bits */ return (crc & ((1 << PEGASUS_BITS) - 1)); }/***************************************************************************** pegasusMCastFilterSet - sets a Multicast Address Filter for the device** Even if the host wishes to change a single multicast filter in the device,* it must reprogram the entire list of filters using this function. * <pAddress> shall contain a pointer to this list of multicast addresses* and <noOfFilters> shall hold the number of multicast address filters* being programmed to the device.** RETURNS : OK or ERROR if <noOfFilters> is BIG or if the device NAKs** ERRNO: none** \NOMANUAL*/LOCAL STATUS pegasusMCastFilterSet ( PEGASUS_DEVICE * pDevCtrl /* device to add the mcast filters */ ) { ETHER_MULTI * pCurr; UINT8 table[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int hash, ix; PEGASUS_LOG (PEGASUS_DBG_MCAST, "pegasusMCastFilterSet:..entered.\n", 0, 0, 0, 0, 0, 0); if (pDevCtrl == NULL) return ERROR; pCurr = END_MULTI_LST_FIRST (&pDevCtrl->endObj); /* Go through the multicast list and compute the hash table value */ while (pCurr != NULL) { hash = pegasusMchash((UINT8 *)&pCurr->addr); table[hash >> 3] = 1 << (hash & 0x7); pCurr = END_MULTI_LST_NEXT(pCurr); } /* Set the 64 bit multicast hash table filter * The filter must be accessed by using 8 bit register * read/write command */ for (ix = 0; ix < 8; ix++) { if (usbdVendorSpecific (pegasusHandle, pDevCtrl->pDev->nodeId, USB_PEGASUS_SET_BMREQ, USB_PEGASUS_SET_BREQ, table[ix], 0x08 + ix, 0, NULL, NULL) != OK) { PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers\n", 0, 0, 0, 0, 0, 0); return ERROR; } } return OK; }/***************************************************************************** pegasusFindDevice - searches for a usb enet device for indicated <nodeId>** This function searches for a usb enet device for indicated <nodeId>** RETURNS: pointer to matching dev struct or NULL if not found** ERRNO: none** \NOMANUAL*/LOCAL USB_PEGASUS_DEV * pegasusFindDevice ( USBD_NODE_ID nodeId /* Node Id to find */ ) { USB_PEGASUS_DEV * pDev = usbListFirst (&pegasusDevList); while (pDev != NULL) { if (pDev->nodeId == nodeId) break; pDev = usbListNext (&pDev->devLink); } return pDev; }/***************************************************************************** pegasusEndFindDevice - searches for a usb enet device for a given <productId> and <vendorId>.** This function searches for a usb enet device for a given <productId> and <vendorId>** RETURNS: pointer to matching dev struct or NULL if not found** ERRNO: none** \NOMANUAL*/LOCAL USB_PEGASUS_DEV * pegasusEndFindDevice ( UINT16 vendorId, /* Vendor Id to search for */ UINT16 productId /* Product Id to search for */ ) { USB_PEGASUS_DEV * pDev = usbListFirst (&pegasusDevList); while (pDev != NULL) { if ((pDev->vendorId == vendorId) && (pDev->productId == productId)) break; pDev = usbListNext (&pDev->devLink); } return pDev; }/***************************************************************************** pegasusShutdown - shuts down USB EnetLib** <errCode> should be OK or S_pegasusLib_xxxx. This value will be* passed to ossStatus() and the return value from ossStatus() is the* return value of this function.** RETURNS: OK, or ERROR per value of <errCode> passed by caller** ERRNO: depends on the error code <errCode>** \NOMANUAL*/LOCAL STATUS pegasusShutdown ( int errCode ) { PEGASUS_DEVICE * pDev; /* Dispose of any open connections. */ while ((pDev = usbListFirst (&pegasusDevList)) != NULL) pegasusDestroyDevice (pDev); /* * Release our connection to the USBD. The USBD automatically * releases any outstanding dynamic attach requests when a client * unregisters. */ if (pegasusHandle != NULL) { usbdClientUnregister (pegasusHandle); pegasusHandle = NULL; } /* Release resources. */ if (pegasusMutex != NULL) { OSS_MUTEX_DESTROY (pegasusMutex); pegasusMutex = NULL; } if (pegasusTxMutex != NULL) { OSS_MUTEX_DESTROY (pegasusTxMutex); pegasusTxMutex = NULL; } if (pegasusRxMutex != NULL) { OSS_MUTEX_DESTROY (pegasusRxMutex); pegasusRxMutex = NULL; } return ossStatus (errCode); }/***************************************************************************** pegasusOutIrpInUse - determines if any of the output IRP's are in use** This function determines if any of the output IRP's are in use and returns * the status information* * RETURNS: TRUE if any of the IRP's are in use, FALSE otherwise.** ERRNO: none*/BOOL pegasusOutIrpInUse ( PEGASUS_DEVICE * pDevCtrl ) { BOOL inUse = FALSE; int i; for (i=0;i<pDevCtrl->noOfIrps;i++) { if (pDevCtrl->pEnetIrp[i].outIrpInUse) { inUse = TRUE; break; } } return(inUse); }/***************************************************************************** pegasusDestroyDevice - disposes of a PEGASUS_DEVICE structure** Unlinks the indicated PEGASUS_DEVICE structure and de-allocates* resources associated with the channel.** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL void pegasusDestroyDevice ( PEGASUS_DEVICE * pDevCtrl ) { USB_PEGASUS_DEV * pDev; int index; if (pDevCtrl != NULL) { pDev = pDevCtrl->pDev; /* Unlink the structure. */ usbListUnlink (&pDev->devLink); /* Release pipes and wait for IRPs to be cancelled if necessary. */ if (pDevCtrl->outPipeHandle != NULL) usbdPipeDestroy (pegasusHandle, pDevCtrl->outPipeHandle); if (pDevCtrl->inPipeHandle != NULL) usbdPipeDestroy (pegasusHandle, pDevCtrl->inPipeHandle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -