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

📄 usbacmlib.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* usbAcmLib.c - USB Communications Class - Abstract Control Model Driver *//* Copyright 2000-2001 Wind River systems, Inc *//*modification history--------------------01b,08aug01,dat  Removing warnings01a,19sep00,bri  Created*//*DESCRIPTIONThis module implements the USB ACM 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 modems are described in the USBcommunications class / acm sub class definition.  The Client (user) interaction with the device is via the VxWorks IO system. This device appears as an SIO device and the driver exports the functions as required by VxWorks SIO driver Model. Unlike most SIO drivers, the number of channels supported by this driver is notfixed.	Rather, USB modems may be added or removed from the system at anytime.  This creates a situation in which the number of modems is dynamic, andclients of usbAcmLib 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 modems, 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.INITIALIZATIONThis driver must be initialized by calling usbAcmLibInit(). usbAcmLibInit() inturn initializes its connection to the USBD and other internal resources neededfor operation.Prior to calling usbAcmLibInit(), 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 modem operation can begin.  However, it is not necessary for usbdHcdAttach() to be called prior to initializating usbAcmLib.usbAcmLib uses the USBD dynamic attach services and is capable of recognizing USB Modem 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.usbAcmLib 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 usbAcmLib.For the same reason, there is no post-interrupt-connect initialization codeand usbAcmLib.c therefore also omits the "devInit2" entry point.OTHER FUNCTIONSusbAcmLib also supports the SIO ioctl interface. All the set baudrate, get baud rate functions will work as per the SIO driver specification. Additional ioctl functions have been added to allow the caller to use the additional commands specified in the USB ACM class specification. However the modem can be treated as any serial modem and can be controlled.Modems work on AT commands. The AT commands can be sent via the standardway i.e., through the Bulk Out pipe. Here the driver doesn't differentiate between AT commands and any other data. DATA FLOWFor each USB modem connected to the system, usbAcmLib sets up  USB pipesto transmit and receive data to the Modem. The USB Modem 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:usbAcmLib.h*//* includes */#include "vxWorks.h"#include "string.h"#include "stdio.h"#include "sioLib.h"#include "errno.h"#include "ctype.h"#include "logLib.h"#include "usb/usbPlatform.h"#include "usb/ossLib.h"			/* operations system srvcs */#include "usb/usb.h"			/* general USB definitions */#include "usb/usbListLib.h"		/* linked list functions */#include "usb/usbdLib.h"		/* USBD interface */#include "usb/usbLib.h"			/* USB utility functions */#include "usb/usbCommdevices.h"#include "drv/usb/usbAcmLib.h"		/* our API *//* defines */#define ACM_CLIENT_NAME     "usbAcmLib" /* USBD client name *//* for debugging */#define USB_ACM_DEBUG#ifdef	USB_ACM_DEBUG#define USB_ACM_DEBUG_OFF		0x0000#define USB_ACM_DEBUG_RX		0x0001#define	USB_ACM_DEBUG_TX		0x0002#define USB_ACM_DEBUG_BLOCK		0x0004#define	USB_ACM_DEBUG_ATTACH		0X0008#define	USB_ACM_DEBUG_INIT		0x0010#define	USB_ACM_DEBUG_OPEN		0x0020#define	USB_ACM_DEBUG_CLOSE		0x0040#define	USB_ACM_DEBUG_IOCTL		0x0080#define	USB_ACM_DEBUG_INT		0x0100int	usbAcmDebug = (0x0);	#define USB_ACM_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)    \	if (usbAcmDebug & FLG)                           \            logMsg(X0, X1, X2, X3, X4, X5, X6);#else /*USB_ACM_DEBUG*/#define USB_ACM_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)#endif /*USB_ACM_DEBUG*//* * ATTACH_REQUEST */typedef struct attach_request    {        LINK reqLink;			/* linked list of requests  */    USB_ACM_CALLBACK callback;		/* client callback routine  */    pVOID callbackArg;			/* client callback argument */        }ATTACH_REQUEST, *pATTACH_REQUEST;/* forward static declarations */int 	usbAcmTxStartup 	(SIO_CHAN * pSioChan);LOCAL 	int usbAcmPollOutput 	(SIO_CHAN * pSioChan, char    outChar);LOCAL 	int usbAcmPollInput  	(SIO_CHAN * pSioChan, char *thisChar);int 	usbAcmIoctl 	   	(SIO_CHAN * pSioChan, int request, void *arg);LOCAL VOID usbAcmTxIrpCallback 	(pVOID p);LOCAL VOID usbAcmRxIrpCallback 	(pVOID p);LOCAL VOID destroySioChan 	(pUSB_ACM_SIO_CHAN pSioChan);LOCAL STATUS usbAcmCtrlCmdSend 	(pUSB_ACM_SIO_CHAN pSioChan, 				 UINT16 request,             	  	  		 UINT8 * pBuf,               				 UINT16  count               			        );LOCAL STATUS usbAcmOpen		(SIO_CHAN * pSioChan);/* locals */LOCAL UINT16 initCount = 0;	 /* Count of init nesting */LOCAL MUTEX_HANDLE acmMutex;	 /* mutex used to protect internal structs */LOCAL LIST_HEAD sioList;	 /* linked list of USB_ACM_SIO_CHAN */LOCAL LIST_HEAD reqList;	 /* Attach callback request list */LOCAL USBD_CLIENT_HANDLE usbdHandle; /* our USBD client handle */LOCAL SEM_HANDLE   acmIrpSem;    /* Semaphore for IRP Synchronisation *//* Channel function table. */LOCAL SIO_DRV_FUNCS usbAcmSioDrvFuncs =    {    usbAcmIoctl,    usbAcmTxStartup,    usbAcmCallbackRegister,    usbAcmPollInput,    usbAcmPollOutput    };/***************************************************************************** notifyAttach - Notifies registered callers of attachment/removal events** RETURNS: N/A*/LOCAL VOID notifyAttach    (    pUSB_ACM_SIO_CHAN pSioChan,    UINT16 attachCode    )    {    pATTACH_REQUEST pRequest = usbListFirst (&reqList);    while (pRequest != NULL)	{        /* Invoke the Callback registered */        (*pRequest->callback) (pRequest->callbackArg, 	    (SIO_CHAN *) pSioChan, attachCode, NULL, NULL);                /* Move to the next client */	pRequest = usbListNext (&pRequest->reqLink);	}    }/***************************************************************************** findEndpoint - Searches for a <type> endpoint of the <direction> direction.** RETURNS: pointer to matching endpoint descriptor or NULL if not found*/LOCAL pUSB_ENDPOINT_DESCR findEndpoint    (    pUINT8 pBfr,    UINT16 bfrLen,    UINT16 direction,    UINT16 attributes    )    {    pUSB_ENDPOINT_DESCR pEp;    while ((pEp = usbDescrParseSkip (&pBfr, &bfrLen, USB_DESCR_ENDPOINT)) 		  != NULL)	{	if ((pEp->attributes & USB_ATTR_EPTYPE_MASK) == attributes &&	    (pEp->endpointAddress & USB_ENDPOINT_DIR_MASK) == direction)	    break;	}    return pEp;    }/***************************************************************************** configureSioChan - configure USB Modem for operation.** Selects the configuration/interfaces specified in the <pSioChan>* structure.  These values come from the USBD dynamic attach callback,* which in turn are retrieved from the configuration/interface* descriptors which reported the device to be a modem.** ACM Specification requires that the device supporting two interfaces.* 1. Communication Interface class* 2. Data Interface class.** We've registered (with usbd) for getting notified when a ACM device * is attached.  While registering, we supplied the Communications Class * information and Communications interface class information.  The * configuration with the communication interface class also should support * the data interface class.  Also the communication interface class shall * support the common AT command set protocol.** RETURNS: OK if successful, else ERROR if failed to configure channel*/LOCAL STATUS configureSioChan    (    pUSB_ACM_SIO_CHAN pSioChan,    UINT16 configuration,    UINT16 interface    )    {    pUSB_CONFIG_DESCR pCfgDescr;    pUSB_INTERFACE_DESCR pIfDescr;    pUSB_ENDPOINT_DESCR pOutEp = NULL;    pUSB_ENDPOINT_DESCR pInEp = NULL;    pUSB_ENDPOINT_DESCR pIntrEp = NULL;    UINT8 bfr [USB_MAX_DESCR_LEN];    pUINT8 pBfr;    UINT16 actLen;    UINT16 ifNo;    /*      * 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, 			   (configuration - 1), 			   0, 			   sizeof (bfr), 			   bfr, 			   &actLen) != OK)	return ERROR;    if ((pCfgDescr = usbDescrParse (bfr, actLen, USB_DESCR_CONFIGURATION)) 	== NULL)	return ERROR;    pSioChan->configuration = configuration;    /*     * Now look for the Data Interface Class  and Communication interface      * Class. Then find the Corresponding End points     */        ifNo = 0;    pBfr = bfr;    while ((pIfDescr = usbDescrParseSkip (&pBfr, &actLen, USB_DESCR_INTERFACE)) 					 != NULL)	{                if (pIfDescr->interfaceClass == USB_CLASS_COMMINTERFACE)            {                        if (pIfDescr->interfaceProtocol == USB_COMM_PROTOCOL_COMMONAT)                {                                pSioChan->ifaceCommClass = ifNo;                pSioChan->ifaceCommAltSetting = pIfDescr->alternateSetting;                pSioChan->protocol = USB_COMM_PROTOCOL_COMMONAT;                /* It should have an interrupt end point. Find out */                if ((pIntrEp = findEndpoint (pBfr, actLen,                                             USB_ENDPOINT_IN,                                             USB_ATTR_INTERRUPT)) == NULL)                    {                    USB_ACM_LOG (USB_ACM_DEBUG_ATTACH,                                 " No Interrupt End point \n",0, 0, 0, 0, 0, 0);                    return ERROR;                                        }                usbdInterfaceSet (usbdHandle, pSioChan->nodeId,            	                pSioChan->ifaceCommClass,                                 pSioChan->ifaceCommAltSetting);                }            }        else            {            if (pIfDescr->interfaceClass == USB_CLASS_DATAINTERFACE)                {                  pSioChan->ifaceDataClass = ifNo;                  pSioChan->ifaceDataAltSetting = pIfDescr->alternateSetting;                  /* It should have a Bulk I/P and a Bulk O/P end points */                                    if ((pInEp = findEndpoint (pBfr, 					     actLen,                                              USB_ENDPOINT_IN,                                             USB_ATTR_BULK)) == NULL)                      {                                          USB_ACM_LOG (USB_ACM_DEBUG_ATTACH,                                    " No Input End point \n",0, 0, 0, 0, 0, 0);                      return ERROR;                                            }                                    if ((pOutEp = findEndpoint (pBfr, actLen,                                             USB_ENDPOINT_OUT,                                             USB_ATTR_BULK)) == NULL)                      {                                            USB_ACM_LOG (USB_ACM_DEBUG_ATTACH,                                    " No Output End point \n",0, 0, 0, 0, 0, 0);                      return ERROR;                                            }                  usbdInterfaceSet (usbdHandle, pSioChan->nodeId,            	                    pSioChan->ifaceDataClass,                                     pSioChan->ifaceDataAltSetting);                }            }        ifNo++;        if (pIntrEp != NULL)            if (pOutEp != NULL)                if (pInEp != NULL)                    break;        }    if (pIfDescr == NULL)        {        USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, " No appropriate interface \            descriptor ",0, 0, 0, 0, 0, 0);	return ERROR;        }    if ((pInEp == NULL) || (pOutEp == NULL) || (pIntrEp == NULL))	{	USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, " No End points \n",0, 0, 0, 0, 0, 0);	}    USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, "Intr EP : 0x%x :: \        In EP : 0x%x  :: Out EP : 0x%x \n", (UINT16)pIntrEp->endpointAddress,                   (UINT16)(pInEp->endpointAddress),                   (UINT16)(pOutEp->endpointAddress), 0, 0, 0);    /* Fill in the maximum packet sizes */    pSioChan->outBfrLen = pOutEp->maxPacketSize;    pSioChan->inBfrLen = pInEp->maxPacketSize;    /* Select the configuration. */    if (usbdConfigurationSet (usbdHandle, 			      pSioChan->nodeId,			      pCfgDescr->configurationValue, 			      pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) 			    != OK)	return ERROR;    /* Create a pipe for output to the modem. */    if (usbdPipeCreate (usbdHandle, 			pSioChan->nodeId, 			pOutEp->endpointAddress, 			pCfgDescr->configurationValue,			pSioChan->ifaceDataClass, 			USB_XFRTYPE_BULK, 			USB_DIR_OUT,				FROM_LITTLEW (pOutEp->maxPacketSize), 			0, 			0, 			&pSioChan->outPipeHandle) 		       != OK)	{	return ERROR;	}    /*      * Create a pipe to listen for input from the device      */    if (usbdPipeCreate (usbdHandle, 			pSioChan->nodeId, 			pInEp->endpointAddress, 			pCfgDescr->configurationValue,			pSioChan->ifaceDataClass, 			USB_XFRTYPE_BULK, 			USB_DIR_IN,				FROM_LITTLEW (pInEp->maxPacketSize), 			0, 			0, 			&pSioChan->inPipeHandle) 		      != OK)	{	return ERROR;	}    /* set the default settings for the modem */    pSioChan->lineCode.baudRate = 9600;    /* Bits/sec */    pSioChan->lineCode.noOfStopBits = USB_ACM_STOPBITS_1; /* 1 stop bit */    pSioChan->lineCode.parityType = USB_ACM_PARITY_NONE; /* No parity */    pSioChan->lineCode.noOfDataBits = 8;   /* 8 data bits */    if (usbAcmCtrlCmdSend (pSioChan, 			   USB_ACM_REQ_LINE_CODING_SET, 			   (UINT8 *)(&pSioChan->lineCode), 			   sizeof(pSioChan->lineCode)) 			 == ERROR)	{        USB_ACM_LOG (USB_ACM_DEBUG_ATTACH, "LineCode could not be set\n",	    0, 0, 0, 0, 0, 0);	}    return OK;    }/***************************************************************************** createSioChan - creates a new USB_ACM_SIO_CHAN structure** Creates a new USB_ACM_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 modem for this device.*

⌨️ 快捷键说明

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