/* usbdCoreLib.c - USBD core logic */
/* Copyright 2000-2002 Wind River Systems, Inc. */
/*
Modification history
--------------------
01l,08nov01,wef USBD_NODE struture element changed from hubStatus to
pHubStatus, reflect this change
01k,25oct01,wef repalce automatic buffer creations with calls to OSS_MALLOC
in places where the buffer is passed to the hardware (related
to SPR 70492).
01j,18sep01,wef merge from wrs.tor2_0.usb1_1-f for veloce
01i,08aug01,dat Removing warnings
01h,12aug00,bri Modify interrogateDeviceClass() to
1. Allow multifunction devices that belong to same USB class
but have interfaces belonging to different subclasses.
2. Store the configuration Value as mentioned in the
configuration descriptor in the nodeClass.
3. Ensure nodeclasses are created for all devices.
01g,20mar00,rcb Add USB_DEVICE_DESCR field to USBD_NODE.
01f,17jan00,rcb Modify interrogateDeviceClass() to use usbConfigDescrGet()...
ensures that all descriptors associated with a configuration
descriptor will be read, even if the total length is very long.
01e,20dec99,rcb Fix benign bug in fncConfigSet() regarding pRoot.
Fix benign bug in HCD detach logic which detached the HCD
before deleting all pipes.
01d,23nov99,rcb Replace HCD bandwidth alloc/release with pipe create/destroy
in order to generalize approach for OHCI HCD.
01c,24sep99,rcb Change packet count calculation in transferIrpCallback()
to handle case where a single 0-length packet is transferred.
01b,07sep99,rcb Add support for management callbacks and set-bus-state API.
01a,08jun99,rcb First.
*/
/*
DESCRIPTION
This module contains the primary USBD entry point, usbdUrbExec() and the
individual USBD function execution routines. usbdUrbExec() is responsible for
interpreting each URB's function code and then fanning-out to the individual
function processor.
IMPLEMENTATION NOTES
When the USBD is first initialized it creates an internal "client" which is
used by the USBD when performing control pipe transfers to each hub/device. This
"client" remains active until the USBD is shut down.
For each client registered with the USBD, including the internal client, the USBD
allocates an individual task, and that task inherits the priority of the client
task which invokes the usbdClientRegister() function. This task is normally
inactive, and only wakes up when a client callback is to be executed. Therefore,
each client's callbacks are invoked on a task which is unique to that client.
Other USBD tasks (see below) are therefore shielded from the behavoir of an
individual client's callback routine.
For each USB which is attached to the USBD through the usbdHcdAttach() function,
the USBD also creates a unique "bus monitor" task. This task is responsible
for configuring and monitoring each hub on a given USB. Whenever a hub or device
is attached/removed from the USB, the bus monitor thread is responsible for
updating internal data structures, configuring/re-configuring hubs, and for
triggering "dynamic attach/removal" callbacks - which themselves are performed by
each individual client's callback task.
All USBD internal data structures, e.g., client lists, HCD lists and releated
node structures, are protected by a single mutex, structMutex. All threads which
rely on the stability of internal data structures or which can modify internal
data structures take this mutex. usbdCoreEntry() is the single entry point
responsible for taking this mutex when clients invoke the USBD. Each "bus
monitor" thread also takes this mutex each time it may update bus structures.
IRP callback, however, do not take the mutex. While certain IRP "userPtr" fields
may point to other USBD structures, the organization of the code guarantees that
IRPs will be completed or canceled prior to dismantling the USBD structures with
which they are associated.
*/
/* defines */
#define USBD_VERSION 0x0001 /* USBD version in BCD */
#define USBD_MFG "Wind River Systems, Inc." /* USBD Mfg */
#define INTERNAL_CLIENT_NAME "usbd"
/* includes */
#include "usb/usbPlatform.h"
#include "string.h"
#include "usb/ossLib.h"
#include "usb/usbQueueLib.h"
#include "usb/usbLib.h" /* USB utility functions */
#include "usb/usbdCoreLib.h" /* our API */
#include "drv/usb/usbHcd.h" /* HCD interface */
#include "usb/usbHcdLib.h" /* HCD function library */
#include "usb/usbdStructures.h" /* usbdCoreLib data structures */
/* defines */
#define PENDING 1
#define CALLBACK_Q_DEPTH 128 /* Needs to be fairly deep to handle */
/* a potentially large number of */
/* notification callbacks */
#define BUS_Q_DEPTH 32 /* Outstanding bus service requests */
/* clientThread request codes...stored in msg field of OSS_MESSAGE. */
#define CALLBACK_FNC_TERMINATE 0 /* Terminate the callback thread */
#define CALLBACK_FNC_IRP_COMPLETE 1 /* issue an IRP completion callback */
#define CALLBACK_FNC_NOTIFY_ATTACH 2 /* issue an attach callback */
#define CALLBACK_FNC_MNGMT_EVENT 3 /* management event callback */
#define CALLBACK_TIMEOUT 5000 /* Wait 5 seconds for callback to */
/* exit in response to terminate fnc */
/* busThread request codes...stored in msg field of OSS_MESSAGE. */
#define BUS_FNC_TERMINATE 0 /* Terminate the bus monitor thread */
#define BUS_FNC_UPDATE_HUB 1 /* update a hub */
#define BUS_TIMEOUT 5000 /* Wait 5 seconds for bus monitor */
/* thread to terminate */
/* general timeout */
#define IO_TIMEOUT 5000 /* 5 seconds */
#define EXCLUSION_TIMEOUT 10000 /* 10 seconds */
/* HUB_STATUS_LEN() returns length of status structure for indicated hub node */
#define HUB_STATUS_LEN(pNode) \
min ((pNode->numPorts + 1 + 7) / 8, (int) MAX_HUB_STATUS_LEN)
/* Constants used by resetDataToggle(). */
#define ANY_CONFIGURATION 0xffff
#define ANY_INTERFACE 0xffff
#define ANY_ENDPOINT 0xffff
/* typedefs */
/* NOTIFICATION
*
* Created by notifyIfMatch() and consumed by client's callback thread.
*/
typedef struct notification
{
USBD_ATTACH_CALLBACK callback; /* client's callback routine */
USBD_NODE_ID nodeId; /* node being attached/removed */
UINT16 attachCode; /* attach code */
UINT16 configuration; /* config matching notify request */
UINT16 interface; /* interface matching notify request */
UINT16 deviceClass; /* device/interface class */
UINT16 deviceSubClass; /* device/interface sub class */
UINT16 deviceProtocol; /* device/interface protcol */
} NOTIFICATION, *pNOTIFICATION;
/* locals */
LOCAL int initCount = 0;
LOCAL MUTEX_HANDLE structMutex = NULL; /* guards USBD structures */
LOCAL LIST_HEAD hcdList = {0}; /* List of attached HCDs */
LOCAL LIST_HEAD clientList = {0}; /* list of registered clients */
LOCAL USBD_CLIENT_HANDLE internalClient = NULL; /* internal client */
/* forward declarations */
LOCAL BOOL initHubIrp
(
pUSBD_NODE pNode
);
LOCAL pUSBD_NODE createNode
(
pUSBD_BUS pBus, /* node's parent bus */
USBD_NODE_ID rootId, /* root id */
USBD_NODE_ID parentHubId, /* parent hub id */
UINT16 parentHubPort, /* parent hub port no */
UINT16 nodeSpeed, /* node speed */
UINT16 topologyDepth /* this node's depth in topology */
);
/* functions */
/***************************************************************************
*
* validateClient - Determines if a client handle is valid
*
* RETURNS: TRUE if client valid, else FALSE
*/
LOCAL BOOL validateClient
(
USBD_CLIENT_HANDLE clientHandle, /* client to be validated */
pUSBD_CLIENT *ppClient /* ptr to USBD_CLIENT if valid */
)
{
if (usbHandleValidate (clientHandle, USBD_CLIENT_SIG, (pVOID *) ppClient)
!= OK)
return FALSE;
return TRUE;
}
/***************************************************************************
*
* validateNode - Determines if a node handle is valid
*
* RETURNS: TRUE if node valid, else FALSE