⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbprinterlib.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* usbPrinterLib.c - USB printer class drive with vxWorks SIO interface *//* Copyright 2000-2002 Wind River Systems, Inc. *//*modification history--------------------01j,26apr02,wef  evaluating SPR #7179301i,11mar02,wef  remove previous change.  01h,04feb02,wef  Fix bug in listenForInput().  IRP bfr was incorrectly set to		 be the address of the bfr ptr and not the bfr ptr SPR # 71793.01g,30oct01,wef  Remove automatic buffer creations and repalce with OSS_MALLOC.01f,18sep01,wef  merge from wrs.tor2_0.usb1_1-f for veloce01e,01feb01,wef  Fixed tab stops01d,12apr00,wef  Fixed uninitialized variable warning: pInEp in 		 configureSioChan() 01c,20mar00,rcb  Re-write code to fetch maxPacketSize from endpoint descriptor		 on machines which don't support non-aligned word access.01b,23nov99,rcb  Change return statement in usbPrinterTxStartup() to return 		 status (formerly always returned OK).01a,01sep99,rcb  written.*//*DESCRIPTIONThis module implements the USB printer class driver for the vxWorks operatingsystem.  This module presents an interface which is a superset of the vxWorksSIO (serial IO) driver model.  That is, this driver presents the external APIswhich would be expected of a standard "multi-mode serial (SIO) driver" andadds certain extensions which are needed to address adequately the requirementsof the hot-plugging USB environment.USB printers are described in the USB Printer Class definition.  This classdriver specification presents two kinds of printer: uni-directional printers(output only) and bi-directional printers (capable of both output and input).This class driver is capable of handling both kinds of printers.  If a printeris uni-directional, then the SIO driver interface only allows characters to bewritten to the printer.  If the printer is bi-directional, then the SIO interfaceallows both output and input streams to be written/read.Unlike most SIO drivers, the number of channels supported by this driver is notfixed.	Rather, USB printers may be added or removed from the system at anytime.  This creates a situation in which the number of channels is dynamic, andclients of usbPrinterLib.c need to be made aware of the appearance and disappearance of channels.  Therefore, this driver adds an additional set offunctions which allows clients to register for notification upon the insertionand removal of USB printers, and hence the creation and deletion of channels.This module itself is a client of the Universal Serial Bus Driver (USBD).  Allinteraction with the USB buses and devices is handled through the USBD.INITIALIZATIONAs with standard SIO drivers, this driver must be initialized by callingusbPrinterDevInit().  usbPrinterDevInit() in turn initializes its connection to the USBD and other internal resources needed for operation.  Unlike some SIO drivers, there are no usbPrinterLib.c data structures which need to be initialized prior to calling usbPrinterDevInit().Prior to calling usbPrinterDevInit(), the caller must ensure that the USBDhas been properly initialized by calling - at a minimum - usbdInitialize().It is also the caller's responsibility to ensure that at least one USB HCD(USB Host Controller Driver) is attached to the USBD - using the USBD functionusbdHcdAttach() - before printer operation can begin.  However, it is not necessary for usbdHcdAttach() to be alled prior to initializating usbPrinterLib.c.usbPrinterLib.c uses the USBD dynamic attach services and is capable of recognizing USB printer attachment and removal on the fly.  Therefore, it is possible for USB HCDs to be attached to or detached from the USBD at run time- as may be required, for example, in systems supporting hot swapping ofhardware.usbPrinterLib.c does not export entry points for transmit, receive, and errorinterrupt entry points like traditional SIO drivers.  All "interrupt" drivenbehavior is managed by the underlying USBD and USB HCD(s), so there is noneed for a caller (or BSP) to connect interrupts on behalf of usbPrinterLib.c.For the same reason, there is no post-interrupt-connect initialization codeand usbPrinterLib.c therefore also omits the "devInit2" entry point.OTHER FUNCTIONSusbPrinterLib.c also supports the SIO ioctl interface.	However, attempts toset parameters like baud rates and start/stop bits have no meaning in the USBenvironment and will be treated as no-ops.  Additional ioctl functions have been added to allow the caller to retrieve theUSB printer's "device ID" string, the type of printer (uni- or bi-directional),and the current printer status.  The "device ID" string is discussed in moredetail in the USB printer class specification and is based on the IEEE-1284"device ID" string used by most 1284-compliant printers.  The printer statusfunction can be used to determine if the printer is selected, out of paper, orhas an error condition.DATA FLOWFor each USB printer connected to the system, usbPrinterLib.c sets up a USB pipeto output bulk data to the printer.  This is the pipe through which printercontrol and page description data will be sent to the printer.	Additionally,if the printer is bi-directional, usbPrinterLib.c also sets up a USB pipe toreceive bulk input data from the printer.  The meaining of data received froma bi-directional printer depends on the specific make/model of printer.The USB printer SIO driver supports only the SIO "interrupt" mode of operation- SIO_MODE_INT.  Any attempt to place the driver in the polled mode will returnan error.INCLUDE FILES:sioLib.h usbPrinterLib.h*//* includes */#include "vxWorks.h"#include "string.h"#include "sioLib.h"#include "errno.h"#include "ctype.h"#include "usb/usbPlatform.h"#include "usb/ossLib.h" 	/* operations system srvcs */#include "usb/usb.h"		/* general USB definitions */#include "usb/usbPrinter.h"	/* USB printer definitions */#include "usb/usbListLib.h"	/* linked list functions */#include "usb/usbdLib.h"	/* USBD interface */#include "usb/usbLib.h" 	/* USB utility functions */#include "drv/usb/usbPrinterLib.h"  /* our API *//* defines */#define PRN_CLIENT_NAME     "usbPrinterLib" /* our USBD client name */#define PRN_OUT_BFR_SIZE    4096	/* size of output bfr */#define PRN_IN_BFR_SIZE     64		/* size of input bfr */#define PRN_OUTPUT_TIMEOUT  30000	/* 30 second timeout *//* IS_BIDIR() returns TRUE if deviceProtocol indicates device is bi-dir. */#define IS_BIDIR(p) ((p) == USB_PROTOCOL_PRINTER_BIDIR)/* typedefs *//* * ATTACH_REQUEST */typedef struct attach_request    {    LINK reqLink;			/* linked list of requests */    USB_PRN_ATTACH_CALLBACK callback;	/* client callback routine */    pVOID callbackArg;			/* client callback argument */    } ATTACH_REQUEST, *pATTACH_REQUEST;/* USB_PRN_SIO_CHAN is the internal data structure we use to track each USB * printer. */typedef struct usb_prn_sio_chan    {    SIO_CHAN sioChan;		/* must be first field */    LINK sioLink;		/* linked list of printer structs */    UINT16 lockCount;		/* Count of times structure locked */    USBD_NODE_ID nodeId;	/* printer node Id */    UINT16 configuration;	/* configuration/interface reported as */    UINT16 interface;		/* a printer by this device */    UINT8 alternateSetting;    UINT16 protocol;		/* protocol reported by device */    BOOL connected;		/* TRUE if printer currently connected */    USBD_PIPE_HANDLE outPipeHandle; /* USBD pipe handle for bulk OUT pipe */    USB_IRP outIrp;		/* IRP to transmit output data */    BOOL outIrpInUse;		/* TRUE while IRP is outstanding */    char *outBfr;		/* pointer to output buffer */    UINT16 outBfrLen;		/* size of output buffer */    UINT32 outErrors;		/* count of IRP failures */    USBD_PIPE_HANDLE inPipeHandle;  /* USBD pipe handle for bulk IN pipe */    USB_IRP inIrp;		/* IRP to monitor input from printer */    BOOL inIrpInUse;		/* TRUE while IRP is outstanding */    char *inBfr;		/* pointer to input buffer */    UINT16 inBfrLen;		/* size of input buffer */    UINT32 inErrors;		/* count of IRP failures */    int mode;			/* always SIO_MODE_INT */    STATUS (*getTxCharCallback) (); /* tx callback */    void *getTxCharArg; 	/* tx callback argument */    STATUS (*putRxCharCallback) (); /* rx callback */    void *putRxCharArg; 	/* rx callback argument */    } USB_PRN_SIO_CHAN, *pUSB_PRN_SIO_CHAN;/* forward static declarations */LOCAL int usbPrinterTxStartup (SIO_CHAN * pSioChan);LOCAL int usbPrinterCallbackInstall (SIO_CHAN *pSioChan, int callbackType,				     STATUS (*callback)(), void *callbackArg);LOCAL int usbPrinterPollOutput (SIO_CHAN *pSioChan, char    outChar);LOCAL int usbPrinterPollInput (SIO_CHAN *pSioChan, char *thisChar);LOCAL int usbPrinterIoctl (SIO_CHAN *pSioChan, int request, void *arg);LOCAL VOID usbPrinterIrpCallback (pVOID p);/* locals */LOCAL UINT16 initCount = 0;	/* Count of init nesting */LOCAL MUTEX_HANDLE prnMutex;	/* mutex used to protect internal structs */LOCAL LIST_HEAD sioList;	/* linked list of USB_PRN_SIO_CHAN */LOCAL LIST_HEAD reqList;	/* Attach callback request list */LOCAL USBD_CLIENT_HANDLE usbdHandle; /* our USBD client handle *//* Channel function table. */LOCAL SIO_DRV_FUNCS usbPrinterSioDrvFuncs =    {    usbPrinterIoctl,    usbPrinterTxStartup,    usbPrinterCallbackInstall,    usbPrinterPollInput,    usbPrinterPollOutput    };/***************************************************************************** initiateOutput - initiates data transmission to printer** 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*/LOCAL STATUS initiateOutput    (    pUSB_PRN_SIO_CHAN pSioChan    )    {    pUSB_IRP pIrp = &pSioChan->outIrp;    UINT16 count;    /* Return immediately if the output IRP is already in use. */    if (pSioChan->outIrpInUse)	return OK;    /* If there is no tx callback, return an error */    if (pSioChan->getTxCharCallback == NULL)	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;    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 = usbPrinterIrpCallback;    pIrp->timeout = PRN_OUTPUT_TIMEOUT;    pIrp->transferLen = count;    pIrp->bfrCount = 1;    pIrp->bfrList [0].pid = USB_PID_OUT;    pIrp->bfrList [0].pBfr = (UINT8 *) pSioChan->outBfr;    pIrp->bfrList [0].bfrLen = count;    /* Submit IRP */    if (usbdTransfer (usbdHandle, pSioChan->outPipeHandle, pIrp) != OK)	return ERROR;    pSioChan->outIrpInUse = TRUE;    return OK;    }/***************************************************************************** listenForInput - Initialize IRP to listen for input from printer** RETURNS: OK, or ERROR if unable to submit IRP to listen for input*/LOCAL STATUS listenForInput    (    pUSB_PRN_SIO_CHAN pSioChan    )    {    pUSB_IRP pIrp = &pSioChan->inIrp;    /* Initialize IRP */    memset (pIrp, 0, sizeof (*pIrp));    pIrp->userPtr = pSioChan;    pIrp->irpLen = sizeof (*pIrp);    pIrp->userCallback = usbPrinterIrpCallback;    pIrp->timeout = USB_TIMEOUT_NONE;    pIrp->transferLen = pSioChan->inBfrLen;    pIrp->bfrCount = 1;    pIrp->bfrList [0].pid = USB_PID_IN;    pIrp->bfrList [0].pBfr = (UINT8 *) pSioChan->inBfr;    pIrp->bfrList [0].bfrLen = pSioChan->inBfrLen;    /* Submit IRP */    if (usbdTransfer (usbdHandle, pSioChan->inPipeHandle, pIrp) != OK)	return ERROR;    pSioChan->inIrpInUse = TRUE;    return OK;    }/***************************************************************************** usbPrinterIrpCallback - Invoked upon IRP completion/cancellation** Examines the cause of the IRP completion.  If completion was successful,* interprets the USB printer's boot report and re-submits the IRP.** RETURNS: N/A*/LOCAL VOID usbPrinterIrpCallback    (    pVOID p	    /* completed IRP */    )    {    pUSB_IRP pIrp = (pUSB_IRP) p;    pUSB_PRN_SIO_CHAN pSioChan = pIrp->userPtr;    UINT16 count;    OSS_MUTEX_TAKE (prnMutex, OSS_BLOCK);    /* Determine if we're dealing with the output or input IRP. */    if (pIrp == &pSioChan->outIrp)	{	/* Output IRP completed */	pSioChan->outIrpInUse = FALSE;	if (pIrp->result != OK)	    pSioChan->outErrors++;	/* Unless the IRP was cancelled - implying the channel is being	 * torn down, see if there's any more data to send.	 */	if (pIrp->result != S_usbHcdLib_IRP_CANCELED)	    initiateOutput (pSioChan);	}    else	{	/* Input IRP completed */	pSioChan->inIrpInUse = FALSE;	if (pIrp->result != OK)	    pSioChan->inErrors++;	/* If the IRP was successful, and if an "rx callback" has been	 * installed, then pass the data back to the client.	 */	if (pIrp->result == OK && 	    pSioChan->putRxCharCallback != NULL)	    {	    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.** RETURNS: pointer to matching endpoint descriptor or NULL if not found*/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*/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;        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -