📄 usbprinterlib.c
字号:
/* 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** RETURNS: N/A*/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*/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); while (pSioChan->outIrpInUse || pSioChan->inIrpInUse) OSS_THREAD_SLEEP (1); /* 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*/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** RETURNS: pointer to matching USB_PRN_SIO_CHAN or NULL if not found*/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** RETURNS: N/A*/LOCAL VOID notifyAttach ( pUSB_PRN_SIO_CHAN pSioChan, UINT16 attachCode ) { pATTACH_REQUEST pRequest = usbListFirst (&reqList); while (pRequest != NULL) { (*pRequest->callback) (pRequest->callbackArg, (SIO_CHAN *) pSioChan, attachCode); pRequest = usbListNext (&pRequest->reqLink); } }/***************************************************************************** usbPrinterAttachCallback - called by USBD when printer attached/removed** The USBD will invoke this callback when a USB printer is attached to or* removed from the system. <nodeId> is the USBD_NODE_ID of the node being* attached or removed. <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.* printers generally report their class information at the interface level,* so <configuration> and <interface> will indicate the configuratin/interface* that reports itself as a printer. <deviceClass> and <deviceSubClass> * will match the class/subclass for which we registered. <deviceProtocol>* will tell us if this is a uni- or bi-directional device.** NOTE: The USBD will invoke this function once for each configuration/* interface which reports itself as a printer. So, it is possible that* a single device insertion/removal may trigger multiple callbacks. We* ignore all callbacks except the first for a given device.** RETURNS: N/A*/LOCAL VOID usbPrinterAttachCallback ( USBD_NODE_ID nodeId, UINT16 attachAction, UINT16 configuration, UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol ) { pUSB_PRN_SIO_CHAN pSioChan; OSS_MUTEX_TAKE (prnMutex, OSS_BLOCK); /* Depending on the attach code, add a new printer or disable one * that's already been created. */ switch (attachAction) { case USBD_DYNA_ATTACH: /* A new device is being attached. Check if we already * have a structure for this device. */ if (findSioChan (nodeId) != NULL) break; /* Create a new structure to manage this device. If there's * an error, there's nothing we can do about it, so skip the * device and return immediately. */ if ((pSioChan = createSioChan (nodeId, configuration, interface, deviceProtocol)) == NULL) break; /* Notify registered callers that a new printer has been * added and a new channel created. */ notifyAttach (pSioChan, USB_PRN_ATTACH); break; case USBD_DYNA_REMOVE: /* A device is being detached. Check if we have any * structures to manage this device. */ if ((pSioChan = findSioChan (nodeId)) == NULL) break; /* The device has been disconnected. */ pSioChan->connected = FALSE; /* Notify registered callers that the printer has been * removed and the channel disabled. * * NOTE: We temporarily increment the channel's lock count * to prevent usbPrinterSioChanUnlock() from destroying the * structure while we're still using it. */ pSioChan->lockCount++; notifyAttach (pSioChan, USB_PRN_REMOVE); pSioChan->lockCount--; /* If no callers have the channel structure locked, destroy * it now. If it is locked, it will be destroyed later during * a call to usbPrinterUnlock(). */ if (pSioChan->lockCount == 0) destroySioChan (pSioChan); break; } OSS_MUTEX_RELEASE (prnMutex); }/***************************************************************************** doShutdown - shuts down USB printer SIO driver** <errCode> should be OK or S_usbPrinterLib_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*/LOCAL STATUS doShutdown ( int errCode ) { pATTACH_REQUEST pRequest; pUSB_PRN_SIO_CHAN pSioChan; /* Dispose of any outstanding notification requests */ while ((pRequest = usbListFirst (&reqList)) != NULL) destroyAttachRequest (pRequest); /* Dispose of any open printer connections. */ while ((pSioChan = usbListFirst (&sioList)) != NULL) destroySioChan (pSioChan); /* Release our connection to the USBD. The USBD automatically * releases any outstanding dynamic attach requests when a client * unregisters. */ if (usbdHandle != NULL) { usbdClientUnregister (usbdHandle); usbdHandle = NULL; } /* Release resources. */ if (prnMutex != NULL) { OSS_MUTEX_DESTROY (prnMutex); prnMutex = NULL; } return ossStatus (errCode); }/***************************************************************************** usbPrnDeviceIdGet - Reads USB printer device ID** RETURNS: OK, or ERROR if unable to read device ID.*/LOCAL STATUS usbPrnDeviceIdGet ( pUSB_PRN_SIO_CHAN pSioChan, pUSB_PRINTER_CAPABILITIES pBfr ) { UINT16 actLen; if (usbdVendorSpecific (usbdHandle, pSioChan->nodeId, USB_RT_DEV_TO_HOST | USB_RT_CLASS | USB_RT_INTERFACE, USB_REQ_PRN_GET_DEVICE_ID, pSioChan->configuration, (pSioChan->interface << 8) | pSioChan->alternateSetting, USB_PRN_MAX_DEVICE_ID_LEN, (pUINT8) pBfr, &actLen) != OK || actLen < sizeof (UINT16) /* size of 1284 device ID length prefix */) { return ERROR; } return OK; }/***************************************************************************** usbPrnPortStatusGet - Reads USB printer status** RETURNS: OK, or ERROR if unable to read printer status.*/LOCAL STATUS usbPrnPortStatusGet ( pUSB_PRN_SIO_CHAN pSioChan, pUSB_PRINTER_PORT_STATUS pBfr ) { UINT16 actLen; if (usbdVendorSpecific (usbdHandle, pSioChan->nodeId, USB_RT_DEV_TO_HOST | USB_RT_CLASS | USB_RT_INTERFACE, USB_REQ_PRN_GET_PORT_STATUS, 0, pSioChan->interface, sizeof (*pBfr), (pUINT8) pBfr, &actLen) != OK || actLen < sizeof (*pBfr)) { return ERROR; } return OK; }/***************************************************************************** usbPrnSoftReset - Issues soft reset to printer device** RETURNS: OK, or ERROR if unable to issue soft reset.*/LOCAL STATUS usbPrnSoftReset ( pUSB_PRN_SIO_CHAN pSioChan )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -