📄 usbprinterlib.c
字号:
{ 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 * torn down, re-initiate the "in" IRP to listen for more data from * the printer. */ if (pIrp->result != S_usbHcdLib_IRP_CANCELED) listenForInput (pSioChan); } OSS_MUTEX_RELEASE (prnMutex); }/***************************************************************************** findEndpoint - Searches for a BULK endpoint of the indicated direction.** This function searches for a bulk endpoitn of the indicated <direction>** RETURNS: pointer to matching endpoint descriptor or NULL if not found** ERRNO: none** \NOMANUAL*/LOCAL pUSB_ENDPOINT_DESCR findEndpoint ( pUINT8 pBfr, UINT16 bfrLen, UINT16 direction ) { pUSB_ENDPOINT_DESCR pEp; while ((pEp = usbDescrParseSkip (&pBfr, &bfrLen, USB_DESCR_ENDPOINT)) != NULL) { if ((pEp->attributes & USB_ATTR_EPTYPE_MASK) == USB_ATTR_BULK && (pEp->endpointAddress & USB_ENDPOINT_DIR_MASK) == direction) break; } return pEp; }/***************************************************************************** configureSioChan - configure USB printer for operation** Selects the configuration/interface specified in the <pSioChan>* structure. These values come from the USBD dynamic attach callback,* which in turn retrieved them from the configuration/interface* descriptors which reported the device to be a printer.** RETURNS: OK if successful, else ERROR if failed to configure channel** ERRNO: none** \NOMANUAL*/LOCAL STATUS configureSioChan ( pUSB_PRN_SIO_CHAN pSioChan ) { pUSB_CONFIG_DESCR pCfgDescr; pUSB_INTERFACE_DESCR pIfDescr; pUSB_ENDPOINT_DESCR pOutEp; pUSB_ENDPOINT_DESCR pInEp = NULL; UINT8 * pBfr; UINT8 * pScratchBfr; UINT16 actLen; UINT16 ifNo; UINT16 maxPacketSizeIn; UINT16 maxPacketSizeOut; if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL) return ERROR; /* Read the configuration descriptor to get the configuration selection * value and to determine the device's power requirements. */ if (usbdDescriptorGet (usbdHandle, pSioChan->nodeId, USB_RT_STANDARD | USB_RT_DEVICE, USB_DESCR_CONFIGURATION, 0, 0, USB_MAX_DESCR_LEN, pBfr, &actLen) != OK) { OSS_FREE (pBfr); return ERROR; } if ((pCfgDescr = usbDescrParse (pBfr, actLen, USB_DESCR_CONFIGURATION)) == NULL) { OSS_FREE (pBfr); return ERROR; } /* Look for the interface indicated in the pSioChan structure. */ 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 == pSioChan->interface) break; ifNo++; } if (pIfDescr == NULL) { OSS_FREE (pBfr); return ERROR; } /* Retrieve the endpoint descriptor(s) following the identified interface * descriptor. */ if ((pOutEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_OUT)) == NULL) { OSS_FREE (pBfr); return ERROR; } if (IS_BIDIR (pSioChan->protocol)) if ((pInEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_IN)) == NULL) { OSS_FREE (pBfr); return ERROR; } /* Select the configuration. */ if (usbdConfigurationSet (usbdHandle, pSioChan->nodeId, pCfgDescr->configurationValue, pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) != OK) { OSS_FREE (pBfr); return ERROR; } /* Select interface * * NOTE: Some devices may reject this command, and this does not represent * a fatal error. Therefore, we ignore the return status. */ pSioChan->alternateSetting = pIfDescr->alternateSetting; usbdInterfaceSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, pIfDescr->alternateSetting); /* Create a pipe for output to the printer. */ maxPacketSizeOut = *((pUINT8) &pOutEp->maxPacketSize) | (*(((pUINT8) &pOutEp->maxPacketSize) + 1) << 8); if (usbdPipeCreate (usbdHandle, pSioChan->nodeId, pOutEp->endpointAddress, pCfgDescr->configurationValue, pSioChan->interface, USB_XFRTYPE_BULK, USB_DIR_OUT, maxPacketSizeOut, 0, 0, &pSioChan->outPipeHandle) != OK) { OSS_FREE (pBfr); return ERROR; } /* If the device is bi-direction, create a pipe to listen for input from * the device and submit an IRP to listen for input. */ if (IS_BIDIR (pSioChan->protocol)) { maxPacketSizeIn = *((pUINT8) &pInEp->maxPacketSize) | (*(((pUINT8) &pInEp->maxPacketSize) + 1) << 8); if (usbdPipeCreate (usbdHandle, pSioChan->nodeId, pInEp->endpointAddress, pCfgDescr->configurationValue, pSioChan->interface, USB_XFRTYPE_BULK, USB_DIR_IN, maxPacketSizeIn, 0, 0, &pSioChan->inPipeHandle) != OK) { OSS_FREE (pBfr); return ERROR; } if (listenForInput (pSioChan) != OK) { OSS_FREE (pBfr); return ERROR; } } OSS_FREE (pBfr); return OK; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** This functon disposes of an ATTACH_REQUEST structure** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID destroyAttachRequest ( pATTACH_REQUEST pRequest ) { /* Unlink request */ usbListUnlink (&pRequest->reqLink); /* Dispose of structure */ OSS_FREE (pRequest); }/***************************************************************************** destroySioChan - disposes of a USB_PRN_SIO_CHAN structure** Unlinks the indicated USB_PRN_SIO_CHAN structure and de-allocates* resources associated with the channel.** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID destroySioChan ( pUSB_PRN_SIO_CHAN pSioChan ) { if (pSioChan != NULL) { /* Unlink the structure. */ usbListUnlink (&pSioChan->sioLink); /* Release pipes and wait for IRPs to be cancelled if necessary. */ if (pSioChan->outPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pSioChan->outPipeHandle); if (pSioChan->inPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pSioChan->inPipeHandle); /* The outIrpInUse or inIrpInUse can be set to FALSE only when the mutex * is released. So releasing the mutex here */ OSS_MUTEX_RELEASE (prnMutex); while (pSioChan->outIrpInUse || pSioChan->inIrpInUse) OSS_THREAD_SLEEP (1); /* Acquire the mutex again */ OSS_MUTEX_TAKE (prnMutex, OSS_BLOCK); /* release buffers */ if (pSioChan->outBfr != NULL) OSS_FREE (pSioChan->outBfr); if (pSioChan->inBfr != NULL) OSS_FREE (pSioChan->inBfr); /* Release structure. */ OSS_FREE (pSioChan); } }/***************************************************************************** createSioChan - creates a new USB_PRN_SIO_CHAN structure** Creates a new USB_PRN_SIO_CHAN structure for the indicated <nodeId>.* If successful, the new structure is linked into the sioList upon * return.** <configuration> and <interface> identify the configuration/interface* that first reported itself as a printer for this device.** RETURNS: pointer to newly created structure, or NULL if failure** ERRNO: none** \NOMANUAL*/LOCAL pUSB_PRN_SIO_CHAN createSioChan ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface, UINT16 deviceProtocol ) { pUSB_PRN_SIO_CHAN pSioChan; /* Try to allocate space for a new printer struct */ if ((pSioChan = OSS_CALLOC (sizeof (*pSioChan))) == NULL || (pSioChan->outBfr = OSS_MALLOC (PRN_OUT_BFR_SIZE)) == NULL) { destroySioChan (pSioChan); return NULL; } if (IS_BIDIR (deviceProtocol)) if ((pSioChan->inBfr = OSS_MALLOC (PRN_IN_BFR_SIZE)) == NULL) { destroySioChan (pSioChan); return NULL; } pSioChan->outBfrLen = PRN_OUT_BFR_SIZE; pSioChan->inBfrLen = PRN_IN_BFR_SIZE; pSioChan->sioChan.pDrvFuncs = &usbPrinterSioDrvFuncs; pSioChan->nodeId = nodeId; pSioChan->connected = TRUE; pSioChan->mode = SIO_MODE_INT; pSioChan->configuration = configuration; pSioChan->interface = interface; pSioChan->protocol = deviceProtocol; /* Try to configure the printer. */ if (configureSioChan (pSioChan) != OK) { destroySioChan (pSioChan); return NULL; } /* Link the newly created structure. */ usbListLink (&sioList, pSioChan, &pSioChan->sioLink, LINK_TAIL); return pSioChan; }/***************************************************************************** findSioChan - Searches for a USB_PRN_SIO_CHAN for indicated node ID** This function searches for the pointer to USB_PRN_SIO_CHAN structure for* specified <nodeId>.* * RETURNS: pointer to matching USB_PRN_SIO_CHAN or NULL if not found** ERRNO: none** \NOMANUAL*/LOCAL pUSB_PRN_SIO_CHAN findSioChan ( USBD_NODE_ID nodeId ) { pUSB_PRN_SIO_CHAN pSioChan = usbListFirst (&sioList); while (pSioChan != NULL) { if (pSioChan->nodeId == nodeId) break; pSioChan = usbListNext (&pSioChan->sioLink); } return pSioChan; }/***************************************************************************** notifyAttach - Notifies registered callers of attachment/removal** This function notifies the regsitered clients about the attachment and removal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -