/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_USB_USBAI_H
#define	_SYS_USB_USBAI_H

#pragma ident	"@(#)usbai.h	1.30	06/02/09 SMI"

#ifdef	__cplusplus
extern "C" {
#endif

/* This header file is for USBA2.0 */
#define	USBA_MAJOR_VER 2
#define	USBA_MINOR_VER 0

/*
 * USBAI: Interfaces Between USBA and Client Driver
 *
 *
 * Universal USB device state management :
 *
 *	PWRED_DWN---<3----4>--ONLINE---<2-----1>-DISCONNECTED
 *	    |			 ^		     |
 *	    |			 6		     |
 *	    |			 |		     |
 *	    |			 5		     |
 *	    |			 v		     |
 *	    +----5>----------SUSPENDED----<5----7>---+
 *
 *	1 = Device Unplug
 *	2 = Original Device reconnected
 *	3 = Device idles for time T & transitions to low power state
 *	4 = Remote wakeup by device OR Application kicking off IO to device
 *	5 = Notification to save state prior to DDI_SUSPEND
 *	6 = Notification to restore state after DDI_RESUME with correct device
 *	7 = Notification to restore state after DDI_RESUME with device
 *	    disconnected or a wrong device
 *
 *	NOTE: device states 0x80 to 0xff are device specific and can be
 *		used by client drivers
 */
#define	USB_DEV_ONLINE		1	/* device is online */
#define	USB_DEV_DISCONNECTED	2	/* indicates disconnect */
#define	USB_DEV_SUSPENDED	3	/* DDI_SUSPEND operation */
#define	USB_DEV_PWRED_DOWN	4	/* indicates power off state */


/*
 * ***************************************************************************
 * USBA error and status definitions
 * ***************************************************************************
 */


/*
 * USBA function return values
 */
#define	USB_SUCCESS		0	/* call success			  */
#define	USB_FAILURE		-1	/* unspecified USBA or HCD error  */
#define	USB_NO_RESOURCES	-2	/* no resources available	  */
#define	USB_NO_BANDWIDTH	-3	/* no bandwidth available	  */
#define	USB_NOT_SUPPORTED	-4	/* function not supported by HCD  */
#define	USB_PIPE_ERROR		-5	/* error occured on the pipe	  */
#define	USB_INVALID_PIPE	-6	/* pipe handle passed is invalid  */
#define	USB_NO_FRAME_NUMBER	-7	/* frame No or ASAP not specified */
#define	USB_INVALID_START_FRAME	-8	/* starting USB frame not valid	  */
#define	USB_HC_HARDWARE_ERROR	-9	/* usb host controller error	  */
#define	USB_INVALID_REQUEST	-10	/* request had invalid values	  */
#define	USB_INVALID_CONTEXT	-11	/* sleep flag in interrupt context */
#define	USB_INVALID_VERSION	-12	/* invalid version specified	  */
#define	USB_INVALID_ARGS	-13	/* invalid func args specified	  */
#define	USB_INVALID_PERM	-14	/* privileged operation		  */
#define	USB_BUSY		-15	/* busy condition		  */


/*
 * USB request completion flags, more than one may be set.
 * The following flags are returned after a recovery action by
 * HCD or USBA (autoclearing) or callbacks from pipe_close,
 * abort, reset, or stop polling.  More than one may be set.
 *
 * For sync requests, the client should check the request structure
 * for this flag to determine what has happened.
 *
 * All callbacks are queued to preserve order.	Note that if a normal callback
 * uses a kernel thread, order is not guaranteed since each callback may use
 * its own thread.  The next request will be submitted to the
 * HCD after the threads exits.
 *
 * Exception callbacks using a kernel thread may do auto clearing and no
 * new request will be started until this thread has completed its work.
 */
typedef enum {
	USB_CB_NO_INFO		= 0x00, /* no exception */
	USB_CB_STALL_CLEARED	= 0x01,	/* func stall cleared */
	USB_CB_FUNCTIONAL_STALL	= 0x02,	/* func stall occurred */
	USB_CB_PROTOCOL_STALL	= 0x04,	/* protocal stall occurred */
	USB_CB_RESET_PIPE	= 0x10, /* pipe was reset */
	USB_CB_ASYNC_REQ_FAILED = 0x80, /* thread couldn't be started */
	USB_CB_NO_RESOURCES	= 0x100, /* no resources */
	USB_CB_SUBMIT_FAILED	= 0x200, /* req was queued then submitted */
					/* to HCD which rejected it */
	USB_CB_INTR_CONTEXT	= 0x400 /* Callback is in interrupt context. */
} usb_cb_flags_t;


/*
 * completion reason
 *
 * Set by HCD; only one can be set.
 */
typedef enum {
	USB_CR_OK		= 0,	/* no errors detected		*/
	USB_CR_CRC		= 1,	/* crc error detected		*/
	USB_CR_BITSTUFFING	= 2,	/* bit stuffing violation	*/
	USB_CR_DATA_TOGGLE_MM	= 3,	/* d/t PID did not match	*/
	USB_CR_STALL		= 4,	/* e/p returned stall PID	*/
	USB_CR_DEV_NOT_RESP	= 5,	/* device not responding	*/
	USB_CR_PID_CHECKFAILURE = 6,	/* check bits on PID failed	*/
	USB_CR_UNEXP_PID	= 7,	/* receive PID was not valid	*/
	USB_CR_DATA_OVERRUN	= 8,	/* data size exceeded		*/
	USB_CR_DATA_UNDERRUN	= 9,	/* less data received		*/
	USB_CR_BUFFER_OVERRUN	= 10,	/* memory write can't keep up	*/
	USB_CR_BUFFER_UNDERRUN	= 11,	/* buffer underrun		*/
	USB_CR_TIMEOUT		= 12,	/* command timed out		*/
	USB_CR_NOT_ACCESSED	= 13,	/* Not accessed by hardware	*/
	USB_CR_NO_RESOURCES	= 14,	/* no resources			*/
	USB_CR_UNSPECIFIED_ERR	= 15,	/* unspecified usba or hcd err	*/
	USB_CR_STOPPED_POLLING	= 16,	/* intr/isoc IN polling stopped	*/
	USB_CR_PIPE_CLOSING	= 17,	/* intr/isoc IN pipe closed	*/
	USB_CR_PIPE_RESET	= 18,	/* intr/isoc IN pipe reset	*/
	USB_CR_NOT_SUPPORTED	= 19,	/* command not supported	*/
	USB_CR_FLUSHED		= 20,	/* this request was flushed	*/
	USB_CR_HC_HARDWARE_ERR	= 21	/* usb host controller error	*/
} usb_cr_t;


/*
 * ***************************************************************************
 * General definitions, used all over
 * ***************************************************************************
 *
 *	A pipe handle is returned by usb_pipe_open() on success for
 *	all pipes except the default pipe which is accessed from
 *	the registration structure.  Placed here as forward referenced by
 *	usb_client_dev_data_t below.
 *
 *	The pipe_handle is opaque to the client driver.
 */
typedef	struct usb_pipe_handle	*usb_pipe_handle_t;

/*
 * General opaque pointer.
 */
typedef struct usb_opaque *usb_opaque_t;


/*
 * USB flags argument to USBA interfaces
 */
typedef enum {
	/* do not block until resources are available */
	USB_FLAGS_NOSLEEP		= 0x0000,
	/* block until resources are available */
	USB_FLAGS_SLEEP			= 0x0100,
	/* reserved */
	USB_FLAGS_RESERVED		= 0xFE00
} usb_flags_t;


/*
 * ***************************************************************************
 * Descriptor definitions (from USB 2.0 specification, chapter 9)
 * ***************************************************************************
 */


/*
 * USB Descriptor Management
 *
 * Standard USB descriptors:
 *
 * USB devices present their configuration information in response to
 * a GET_DESCRIPTOR request in a form which is little-endian and,
 * for multibyte integers, unaligned.  It is also position-dependent,
 * which makes non-sequential access to particular interface or
 * endpoint data inconvenient.
 * A GET_DESCRIPTOR request may yield a chunk of data that contains
 * multiple descriptor types.  For example, a GET_DESCRIPTOR request
 * for a CONFIGURATION descriptor could return the configuration
 * descriptor followed by an interface descriptor and the relevant
 * endpoint descriptors.
 *
 * usb_get_dev_data() interface provides an easy way to get all
 * the descriptors and avoids parsing standard descriptors by each
 * client driver
 *
 * usb_dev_descr:
 *	usb device descriptor, refer to	USB 2.0/9.6.1,
 */
typedef struct usb_dev_descr {
	uint8_t		bLength;	/* descriptor size		*/
	uint8_t		bDescriptorType; /* set to DEVICE		*/
	uint16_t	bcdUSB;		/* USB spec rel. number	in bcd	*/
	uint8_t		bDeviceClass;	/* class code			*/
	uint8_t		bDeviceSubClass; /* sub	class code		*/
	uint8_t		bDeviceProtocol; /* protocol code		*/
	uint8_t		bMaxPacketSize0; /* max	pkt size of e/p	0	*/
	uint16_t	idVendor;	/* vendor ID			*/
	uint16_t	idProduct;	/* product ID			*/
	uint16_t	bcdDevice;	/* device release number in bcd	*/
	uint8_t		iManufacturer;	/* manufacturing string		*/
	uint8_t		iProduct;	/* product string		*/
	uint8_t		iSerialNumber;	/* serial number string index	*/
	uint8_t		bNumConfigurations; /* #configs for device	*/
} usb_dev_descr_t;


/*
 * USB Device Qualifier Descriptor
 *
 * The device_qualifier descriptor describes information about a High
 * speed capable device that would change if the device were operating
 * at other (Full) speed. Example: if the device is currently operating
 * at Full-speed, the device_qualifier returns information about how if
 * would operate at high-speed and vice-versa.
 *
 * usb_dev_qlf_descr:
 *
 *	usb device qualifier descriptor, refer to USB 2.0/9.6.2
 */
typedef struct usb_dev_qlf_descr {
	uint8_t		bLength;	/* descriptor size		*/
	uint8_t		bDescriptorType; /* set to DEVICE		*/
	uint16_t	bcdUSB;		/* USB spec rel. number	in bcd	*/
	uint8_t		bDeviceClass;	/* class code			*/
	uint8_t		bDeviceSubClass; /* sub	class code		*/
	uint8_t		bDeviceProtocol; /* protocol code		*/
	uint8_t		bMaxPacketSize0; /* max	pkt size of e/p	0	*/
	uint8_t		bNumConfigurations; /* #configs for device	*/
	uint8_t		bReserved;	/* reserved field		*/
} usb_dev_qlf_descr_t;


/*
 * usb_cfg_descr:
 *	usb configuration descriptor, refer to USB 2.0/9.6.3
 */
typedef struct usb_cfg_descr {
	uint8_t		bLength;	/* descriptor size		*/
	uint8_t		bDescriptorType; /* set to CONFIGURATION	*/
	uint16_t	wTotalLength;	/* total length of data returned */
	uint8_t		bNumInterfaces;	/* # interfaces	in config	*/
	uint8_t		bConfigurationValue; /* arg for SetConfiguration */
	uint8_t		iConfiguration;	/* configuration string		*/
	uint8_t		bmAttributes;	/* config characteristics	*/
	uint8_t		bMaxPower;	/* max pwr consumption		*/
} usb_cfg_descr_t;

/*
 * Default configuration index setting for devices with multiple
 * configurations. Note the distinction between config index and config
 * number
 */
#define	USB_DEV_DEFAULT_CONFIG_INDEX	0

/*
 * bmAttribute values for Configuration Descriptor
 */
#define	USB_CFG_ATTR_SELFPWR		0x40
#define	USB_CFG_ATTR_REMOTE_WAKEUP	0x20


/*
 * USB Other Speed Configuration Descriptor
 *
 * The other_speed_configuration descriptor describes a configuration of
 * a High speed capable device if it were operating at its other possible
 * (Full) speed and vice-versa.
 *
 * usb_other_speed_cfg_descr:
 *	usb other speed configuration descriptor, refer to USB 2.0/9.6.4
 */
typedef struct usb_other_speed_cfg_descr {
	uint8_t		bLength;	/* descriptor size		*/
	uint8_t		bDescriptorType; /* set to CONFIGURATION	*/
	uint16_t	wTotalLength;	/* total length of data returned */
	uint8_t		bNumInterfaces;	/* # interfaces	in config	*/
	uint8_t		bConfigurationValue; /* arg for SetConfiguration */
	uint8_t		iConfiguration;	/* configuration string		*/
	uint8_t		bmAttributes;	/* config characteristics	*/
	uint8_t		bMaxPower;	/* max pwr consumption		*/
} usb_other_speed_cfg_descr_t;


/*
 * usb_if_descr:
 *	usb interface descriptor, refer	to USB 2.0/9.6.5
 */
typedef  struct usb_if_descr {
	uint8_t		bLength;		/* descriptor size	*/
	uint8_t		bDescriptorType;	/* set to INTERFACE	*/
	uint8_t		bInterfaceNumber;	/* interface number	*/
	uint8_t		bAlternateSetting;	/* alt. interface number */
	uint8_t		bNumEndpoints;		/* # of endpoints	*/
	uint8_t		bInterfaceClass;	/* class code		*/
	uint8_t		bInterfaceSubClass;	/* sub class code	*/
	uint8_t		bInterfaceProtocol;	/* protocol code	*/
	uint8_t		iInterface;		/* description string	*/
} usb_if_descr_t;


/*
 * usb_ep_descr:
 *	usb endpoint descriptor, refer to USB 2.0/9.6.6
 */
typedef struct usb_ep_descr {
	uint8_t		bLength;		/* descriptor size	*/
	uint8_t		bDescriptorType;	/* set to ENDPOINT	*/
	uint8_t		bEndpointAddress;	/* address of this e/p */
	uint8_t		bmAttributes;		/* transfer type	*/
	uint16_t	wMaxPacketSize;		/* maximum packet size	*/
	uint8_t		bInterval;		/* e/p polling interval */
} usb_ep_descr_t;

/*
 * bEndpointAddress masks
 */
#define	USB_EP_NUM_MASK		0x0F		/* endpoint number mask */
#define	USB_EP_DIR_MASK		0x80		/* direction mask */
#define	USB_EP_DIR_OUT		0x00		/* OUT endpoint */
#define	USB_EP_DIR_IN		0x80		/* IN endpoint */

/*
 * bmAttribute transfer types for endpoints
 */
#define	USB_EP_ATTR_MASK	0x03		/* transfer type mask */
#define	USB_EP_ATTR_CONTROL	0x00		/* control transfer */
#define	USB_EP_ATTR_ISOCH	0x01		/* isochronous transfer */
#define	USB_EP_ATTR_BULK	0x02		/* bulk transfer */
#define	USB_EP_ATTR_INTR	0x03		/* interrupt transfer */

/*
 * bmAttribute synchronization types for endpoints (isochronous only)
 */
#define	USB_EP_SYNC_MASK	0x0C		/* synchronization mask */
#define	USB_EP_SYNC_NONE	0x00		/* no synchronization */
#define	USB_EP_SYNC_ASYNC	0x04		/* asynchronous */
#define	USB_EP_SYNC_ADPT	0x08		/* adaptive */
#define	USB_EP_SYNC_SYNC	0x0C		/* synchronous */

/*
 * bmAttribute synchronization feedback types for endpoints (isochronous only)
 */
#define	USB_EP_USAGE_MASK	0x30		/* sync feedback mask */
#define	USB_EP_USAGE_DATA	0x00		/* data endpoint */
#define	USB_EP_USAGE_FEED	0x10		/* feedback endpoint */
#define	USB_EP_USAGE_IMPL	0x20		/* implicit feedback endpoint */

/*
 * wMaxPacketSize values for endpoints (isoch and interrupt, high speed only)
 */
#define	USB_EP_MAX_PKTSZ_MASK	0x03FF		/* Mask for packetsize bits */
#define	USB_EP_MAX_XACTS_MASK	0x0C00		/* Max Transactns/microframe */
#define	USB_EP_MAX_XACTS_SHIFT	10		/* Above is 10 bits from end */

/*
 * Ranges for endpoint parameter values.
 */

/* Min and Max NAK rates for high sped control endpoints. */
#define	USB_EP_MIN_HIGH_CONTROL_INTRVL	0
#define	USB_EP_MAX_HIGH_CONTROL_INTRVL	255

/* Min and Max NAK rates for high speed bulk endpoints. */
#define	USB_EP_MIN_HIGH_BULK_INTRVL	0
#define	USB_EP_MAX_HIGH_BULK_INTRVL	255

/* Min and Max polling intervals for low, full speed interrupt endpoints. */
#define	USB_EP_MIN_LOW_INTR_INTRVL	1
#define	USB_EP_MAX_LOW_INTR_INTRVL	255
#define	USB_EP_MIN_FULL_INTR_INTRVL	1
#define	USB_EP_MAX_FULL_INTR_INTRVL	255

/*
 * Min and Max polling intervals for high speed interrupt endpoints, and for
 * isochronous endpoints.
 * Note that the interval is 2**(value-1).  See Section 9.6.6 of USB 2.0 spec.
 */
#define	USB_EP_MIN_HIGH_INTR_INTRVL	1
#define	USB_EP_MAX_HIGH_INTR_INTRVL	16
#define	USB_EP_MIN_FULL_ISOCH_INTRVL	1
#define	USB_EP_MAX_FULL_ISOCH_INTRVL	16
#define	USB_EP_MIN_HIGH_ISOCH_INTRVL	1
#define	USB_EP_MAX_HIGH_ISOCH_INTRVL	16

/*
 * usb_string_descr:
 *	usb string descriptor, refer to	 USB 2.0/9.6.7
 */
typedef struct usb_string_descr {
	uint8_t		bLength;		/* descr size */
	uint8_t		bDescriptorType;	/* set to STRING */
	uint8_t		bString[1];		/* variable length unicode */
						/* encoded string	*/
} usb_string_descr_t;

#define	USB_MAXSTRINGLEN	255		/* max string descr length */


/*
 * ***************************************************************************
 * Client driver registration with USBA
 * ***************************************************************************
 *
 *	The client registers with USBA during attach in two steps
 *	using usb_client_attach() and usb_get_dev_data(). On completion, the
 *	registration data has been initialized.  Most data items are
 *	straightforward.  Among the items returned in the data is the tree of
 *	parsed descriptors, in dev_cfg;	 the number of configurations parsed,
 *	in dev_n_cfg; a pointer to the current configuration in the tree,
 *	in dev_curr_cfg; the index of the first valid interface in the
 *	tree, in dev_curr_if, and a parse level that accurately reflects what
 *	is in the tree, in dev_parse_level.
 */


/*
 * ***************************************************************************
 * Data structures used in the configuration tree
 * ***************************************************************************
 */

/*
 * Tree data structure for each configuration in the tree
 */
typedef struct usb_cfg_data {
	struct usb_cfg_descr	cfg_descr;	/* parsed config descr */
	struct usb_if_data	*cfg_if;	/* interfaces for this cfg */
						/* indexed by interface num */
	struct usb_cvs_data	*cfg_cvs;	/* class/vendor specific */
						/* descrs mod/extend cfg */
	char			*cfg_str;	/* string descriptor */
	uint_t			cfg_n_if;	/* #elements in cfg_if[] */
	uint_t			cfg_n_cvs;	/* #elements in cfg_cvs[] */
	uint_t			cfg_strsize;	/* size of string descr */
} usb_cfg_data_t;


/*
 * Tree data structure for each alternate interface set
 * in each represented configuration
 */
typedef struct usb_if_data {
	struct usb_alt_if_data	*if_alt;	/* sparse array of alts */
						/* indexed by alt setting */
	uint_t			if_n_alt;	/* #elements in if_alt[] */
} usb_if_data_t;


/*
 * Tree data structure for each alternate of each alternate interface set
 */
typedef struct usb_alt_if_data {
	usb_if_descr_t		altif_descr;	/* parsed alternate if descr */
	struct usb_ep_data	*altif_ep;	/* endpts for alt if */
						/* (not a sparse array */
	struct usb_cvs_data	*altif_cvs;	/* cvs for this alt if */
	char			*altif_str;	/* string descriptor */
	uint_t			altif_n_ep;	/* #elements in altif_ep[] */
	uint_t			altif_n_cvs;	/* #elements in  altif_cvs[] */
	uint_t			altif_strsize;	/* size of string descr */
} usb_alt_if_data_t;


/*
 * Tree data structure for each endpoint of each alternate
 */
typedef struct usb_ep_data {
	usb_ep_descr_t		ep_descr;	/* endpoint descriptor */
	struct usb_cvs_data	*ep_cvs;	/* cv mod/extending this ep */
	uint_t			ep_n_cvs;	/* #elements in ep_cvs[] */
} usb_ep_data_t;


/*
 * Tree data structure for each class/vendor specific descriptor
 */
typedef struct usb_cvs_data {
	uchar_t			*cvs_buf;	/* raw data of cvs descr */
	uint_t			cvs_buf_len;	/* cvs_buf size */
} usb_cvs_data_t;


/*
 *	Parse_level determines the extent to which the tree is built, the amount
 *	of parsing usb_client_attach() is to do.  It has the following values:
 *
 *	USB_PARSE_LVL_NONE - Build no tree.  dev_n_cfg will return 0, dev_cfg
 *			     will return NULL, the dev_curr_xxx fields will be
 *			     invalid.
 *	USB_PARSE_LVL_IF   - Parse configured interface only, if configuration#
 *			     and interface properties are set (as when different
 *			     interfaces are viewed by the OS as different device
 *			     instances). If an OS device instance is set up to
 *			     represent an entire physical device, this works
 *			     like USB_PARSE_LVL_ALL.
 *	USB_PARSE_LVL_CFG  - Parse entire configuration of configured interface
 *			     only.  This is like USB_PARSE_LVL_IF except entire
 *			     configuration is returned.
 *	USB_PARSE_LVL_ALL  - Parse entire device (all configurations), even
 *			     when driver is bound to a single interface of a
 *			     single configuration.
 */
typedef enum {
	USB_PARSE_LVL_NONE		= 0,
	USB_PARSE_LVL_IF		= 1,
	USB_PARSE_LVL_CFG		= 2,
	USB_PARSE_LVL_ALL		= 3
} usb_reg_parse_lvl_t;


/*
 * Registration data returned by usb_get_dev_data().  Configuration tree roots
 * are returned in dev_cfg array.
 */
typedef struct usb_client_dev_data {
	usb_pipe_handle_t	dev_default_ph;	/* default pipe handle */
	ddi_iblock_cookie_t	dev_iblock_cookie; /* for mutex_init's */
	struct usb_dev_descr	*dev_descr;	/* cooked device descriptor */
	char			*dev_mfg;	/* manufacturing ID */
	char			*dev_product;	/* product ID */
	char			*dev_serial;	/* serial number */
	usb_reg_parse_lvl_t	dev_parse_level; /* USB_PARSE_LVL_* flag */
	struct usb_cfg_data	*dev_cfg;	/* configs for this device */
						/* indexed by config index */
	uint_t			dev_n_cfg;	/* #elements in dev_cfg[] */
	struct usb_cfg_data	*dev_curr_cfg;	/* current cfg */
	int			dev_curr_if;	/* current interface number */
} usb_client_dev_data_t;


/*
 * ***************************************************************************
 * Device configuration descriptor tree functions
 * ***************************************************************************
 */

/*
 * usb_get_dev_data:
 *	returns initialized registration data. 	Most data items are clear.
 *	Among the items returned is the tree ofparsed descriptors in dev_cfg;
 *	and the number of configurations parsed in dev_n_cfg.
 *
 * Arguments:
 *	dip		- pointer to devinfo node of the client
 *	dev_data	- return registration data at this address
 *	parse_level	- See above
 *	flags		- None used
 *
 * Return Values:
 *	USB_SUCCESS		- usb_register_client succeeded
 *	USB_INVALID_ARGS	- received null dip or reg argument
 *	USB_INVALID_CONTEXT	- called with sleep from callback context
 *	USB_FAILURE		- bad descriptor info or other internal failure
 *
 * Notes:
 * 	1) The non-standard USB descriptors are returned in RAW format.
 *
 *	2) The registration data is unshared. Each client receives its own copy.
 *	(The default control pipe may be shared, even though its tree
 *	description will be unique per device.)
 *
 */
int usb_get_dev_data(
	dev_info_t			*dip,
	usb_client_dev_data_t		**dev_data,
	usb_reg_parse_lvl_t		parse_level,
	usb_flags_t			flags);

/*
 * usb_free_dev_data:
 * undoes what usb_get_dev_data() set up.  It releases
 * memory for all strings, descriptors, and trees set up by usb_get_dev_data().
 *
 * Arguments:
 *	dip		- pointer to devinfo node of the client
 *	dev_data	- pointer to registration data containing the tree.
 */
void usb_free_dev_data(
	dev_info_t			*dip,
	usb_client_dev_data_t		*dev_data);

/*
 * usb_free_descr_tree:
 *	Take down the configuration tree while leaving the rest	of the
 *	registration intact.  This can be used, for example, after attach has
 *	copied any descriptors it needs from the tree, but the rest of the
 *	registration data needs to remain intact.
 *
 *	The following usb_client_dev_data_t fields will be modified:
 *		dev_cfg will be NULL
 *		dev_n_cfg will be 0
 *		dev_curr_cfg_ndx and dev_curr_if will be invalid
 *		dev_parse_level will be USB_REG_DESCR_NONE
 *
 * Arguments:
 *	dip		- pointer to devinfo node of the client
 *	dev_data	- pointer to registration data containing the tree.
 */
void usb_free_descr_tree(
	dev_info_t			*dip,
	usb_client_dev_data_t		*dev_data);


/*
 * usb_print_descr_tree:
 *	Dump to the screen a descriptor tree as returned by
 *	usbai_register_client.
 *
 * Arguments:
 *	dip		- pointer to devinfo of the client
 *	dev_data	- pointer to registration area containing the tree
 *
 * Returns:
 *	USB_SUCCESS		- tree successfully dumped
 *	USB_INVALID_CONTEXT	- called from callback context
 *	USB_INVALID_ARGS	- bad arguments given
 */
int usb_print_descr_tree(
	dev_info_t		*dip,
	usb_client_dev_data_t	*dev_data);


/*
 * ***************************************************************************
 * Registration and versioning
 * ***************************************************************************
 */


/*
 * USBA client drivers are required to define USBDRV_MAJOR_VER
 * USBDRV_MINOR_VER and pass USBDRV_VERSION as the version
 * number to usb_client_attach
 */
#if !defined(USBA_MAJOR_VER) || !defined(USBA_MINOR_VER)
#error incorrect USBA header
#endif

/*
 * Driver major version must be the same as USBA major version, and
 * driver minor version must be <= USBA minor version
 */
#if !defined(USBA_FRAMEWORK)
#if defined(USBDRV_MAJOR_VER) && defined(USBDRV_MINOR_VER)

#if (USBDRV_MAJOR_VER != USBA_MAJOR_VER)
#error USBA and driver major versions do not match
#endif
#if (USBDRV_MINOR_VER > USBA_MINOR_VER)
#error USBA and driver minor versions do not match
#endif

#endif
#endif

#define	USBA_MAKE_VER(major, minor) ((major) << 8 | (minor))
#define	USBA_GET_MAJOR(ver) ((ver) >> 8)
#define	USBA_GET_MINOR(ver) ((ver) & 0xff)

#define	USBDRV_VERSION	USBA_MAKE_VER(USBDRV_MAJOR_VER, USBDRV_MINOR_VER)


/*
 * usb_client_attach:
 *
 * Arguments:
 *	dip		- pointer to devinfo node of the client
 *	version 	- USBA registration version number
 *	flags		- None used
 *
 * Return Values:
 *	USB_SUCCESS		- attach succeeded
 *	USB_INVALID_ARGS	- received null dip or reg argument
 *	USB_INVALID_CONTEXT	- called with sleep from callback context
 *				  or not at attach time
 *	USB_INVALID_VERSION	- version argument is incorrect.
 *	USB_FAILURE		- other internal failure
 */
int usb_client_attach(
	dev_info_t			*dip,
	uint_t				version,
	usb_flags_t			flags);

/*
 * usb_client_detach:
 *
 * Arguments:
 *	dip		- pointer to devinfo node of the client
 *	dev_data	- pointer to data to free. may be NULL
 */
void usb_client_detach(
	dev_info_t			*dip,
	struct usb_client_dev_data	*dev_data);

/*
 * ***************************************************************************
 * Functions for parsing / retrieving data from the descriptor tree
 * ***************************************************************************
 */

/*
 * Function for unpacking any kind of little endian data, usually desriptors
 *
 * Arguments:
 *	format		- string indicating the format in c, s, w, eg. "2c4ws"
 *			  which describes 2 bytes, 4 int, one short.
 *			  The number prefix parses the number of items of
 *			  the following type.
 *	data		- pointer to the LE data buffer
 *	datalen		- length of the data
 *	structure	- pointer to return structure where the unpacked data
 *			  will be written
 *	structlen	- length of the return structure
 *
 * return value:
 *	total number of bytes of the original data that was unpacked
 *	or USB_PARSE_ERROR
 */
#define	USB_PARSE_ERROR	0

size_t usb_parse_data(
	char			*format,
	uchar_t 		*data,
	size_t			datalen,
	void			*structure,
	size_t			structlen);

/*
 * usb_lookup_ep_data:
 *	Function to get specific endpoint data
 *	This function will not access the device.
 *
 * Arguments:
 *	dip		- pointer to dev info
 *	dev_datap	- pointer to registration data
 *	interface	- requested interface
 *	alternate	- requested alternate
 *	skip		- number of endpoints which match the requested type and
 *			  direction to skip before finding one to retrieve
 *	type		- endpoint type
 *	direction	- endpoint direction: USB_EP_DIR_IN/OUT or none
 *
 * Return Values:
 *	NULL or an endpoint data pointer
 */
usb_ep_data_t *usb_lookup_ep_data(
	dev_info_t		*dip,
	usb_client_dev_data_t	*dev_datap,
	uint_t			interface,
	uint_t			alternate,
	uint_t			skip,
	uint_t			type,
	uint_t			direction);


/* Language ID for string descriptors. */
#define	USB_LANG_ID		0x0409		/* English, US */

/*
 * usb_get_string_descr:
 *	Reads the string descriptor.  This function access the device and
 *	blocks.
 *
 * Arguments:
 *	dip		- pointer to devinfo of the client.
 *	langid		- LANGID to read different LOCALEs.
 *	index		- index to the string.
 *	buf		- user provided buffer for string descriptor.
 *	buflen		- user provided length of the buffer.
 *
 * Return Values:
 *	USB_SUCCESS	- descriptor is valid.
 *	USB_FAILURE	- full descriptor could not be retrieved.
 */
int usb_get_string_descr(
	dev_info_t		*dip,
	uint16_t		langid,
	uint8_t			index,
	char			*buf,
	size_t			buflen);


/*
 * ***************************************************************************
 * Addressing utility functions
 * ***************************************************************************
 */

/*
 * usb_get_addr returns the current usb address, mostly for debugging
 * purposes. The address may change after hotremove/insert.
 * This address will not change on a disconnect/reconnect of open device.
 */
int usb_get_addr(dev_info_t *dip);


/*
 * usb_get_if_number returns USB_COMBINED_NODE or USB_DEVICE_NODE
 * if the driver is responsible for the entire device.
 * Otherwise it returns the interface number.
 */
#define	USB_COMBINED_NODE	-1
#define	USB_DEVICE_NODE		-2

int usb_get_if_number(
	dev_info_t		*dip);

boolean_t usb_owns_device(
	dev_info_t		*dip);


/*
 * ***************************************************************************
 * Pipe	Management definitions and functions
 * ***************************************************************************
 */


/*
 *
 * usb_pipe_state:
 *
 * PIPE_STATE_IDLE:
 *	The pipe's policy is set, but the pipe currently isn't transferring
 *	data.
 *
 * PIPE_STATE_ACTIVE:
 *	The pipe's policy has been set, and the pipe is able to transmit data.
 *	When a control or bulk pipe is opened, the pipe's state is
 *	automatically set to PIPE_STATE_ACTIVE.  For an interrupt or
 *	isochronous pipe, the pipe state becomes PIPE_STATE_ACTIVE once
 *	the polling on the pipe has been initiated.
 *
 * PIPE_STATE_ERROR:
 *	The device has generated a error on the pipe.  The client driver
 *	must call usb_pipe_reset() to clear any leftover state that's associated
 *	with the pipe, clear the data toggle, and reset the state of the pipe.
 *
 *	Calling usb_pipe_reset() on a control or bulk pipe resets the state to
 *	PIPE_STATE_ACTIVE.  Calling usb_pipe_reset() on an interrupt or
 *	isochronous pipe, resets the state to PIPE_STATE_IDLE.
 *
 * State Diagram for Bulk/Control
 *
 *			+-<--normal completion------------------<-------^
 *			|						|
 *			V						|
 * usb_pipe_open-->[PIPE_STATE_IDLE]-usb_pipe_*_xfer->[PIPE_STATE_ACTIVE]
 *			^						|
 *			|						v
 *			- usb_pipe_reset<-[PIPE_STATE_ERROR]<-device error
 *
 * State Diagram for Interrupt/Isochronous IN
 *
 *			+-<--usb_pipe_stop_isoc/intr_polling----<-------^
 *			|						|
 *			V						|
 * usb_pipe_open-->[PIPE_STATE_IDLE]-usb_pipe_*_xfer->[PIPE_STATE_ACTIVE]
 *			^						|
 *			|						v
 *			+ usb_pipe_reset<-[PIPE_STATE_ERROR]<-device error
 *
 * State Diagram for Interrupt/Isochronous OUT
 *
 *			+-<--normal completion------------------<-------^
 *			|						|
 *			V						|
 * usb_pipe_open-->[PIPE_STATE_IDLE]-usb_pipe_*_xfer->[PIPE_STATE_ACTIVE]
 *			^						|
 *			|						v
 *			+ usb_pipe_reset<-[PIPE_STATE_ERROR]<-device error
 *
 *
 * The following table indicates which operations are allowed with each
 * pipe state:
 *
 * -------------------------------------------------------------------------+
 * ctrl/bulk	| idle	| active     | error  | sync closing | async closing|
 * -------------------------------------------------------------------------+
 * pipe xfer	|  OK	|queue (USBA)| reject | reject	     | reject	    |
 * pipe reset	| no-op | OK	     |	OK    | reject	     | reject	    |
 * pipe close	|  OK	| wait&close |	OK    | no-op	     | no-op	    |
 * -------------------------------------------------------------------------+
 *
 * -------------------------------------------------------------------------+
 * intr/isoc IN | idle	| active     | error  | sync closing | async closing|
 * -------------------------------------------------------------------------+
 * pipe xfer	|  OK	| reject     | reject | reject	     | reject	    |
 * pipe stoppoll| no-op | OK	     | no-op  | reject	     | reject	    |
 * pipe reset	| no-op | OK	     |	OK    | reject	     | reject	    |
 * pipe close	|  OK	| wait&close |	OK    | no-op	     | no-op	    |
 * -------------------------------------------------------------------------+
 *
 * -------------------------------------------------------------------------+
 * intr/isoc OUT| idle	| active     | error  | sync closing | async closing|
 * -------------------------------------------------------------------------+
 * pipe xfer	|  OK	|queue (HCD) | reject | reject	     | reject	    |
 * pipe stoppoll| reject| reject     | reject | reject	     | reject	    |
 * pipe reset	| no-op | OK	     |	OK    | reject	     | reject	    |
 * pipe close	|  OK	| wait&close |	OK    | no-op	     | no-op	    |
 * -------------------------------------------------------------------------+
 */
typedef enum {
	USB_PIPE_STATE_CLOSED		= 0,
	USB_PIPE_STATE_IDLE		= 1,
	USB_PIPE_STATE_ACTIVE		= 2,
	USB_PIPE_STATE_ERROR		= 3,
	USB_PIPE_STATE_CLOSING		= 4
} usb_pipe_state_t;


/*
 * pipe state control:
 *
 * return values:
 *	USB_SUCCESS	 - success
 *	USB_FAILURE	 - unspecified failure
 */
int usb_pipe_get_state(
	usb_pipe_handle_t	pipe_handle,
	usb_pipe_state_t	*pipe_state,
	usb_flags_t		flags);


/*
 * usb_pipe_policy
 *
 *	Pipe policy specifies how a pipe to an endpoint	should be used
 *	by the client driver and the HCD.
 */
typedef struct usb_pipe_policy {
	/*
	 * This is a hint indicating how many asynchronous operations
	 * requiring a kernel thread will be concurrently active.
	 * Allow at least one for synch exception callback handling
	 * and another for asynchronous closing of pipes.
	 */
	uchar_t		pp_max_async_reqs;
} usb_pipe_policy_t;


/*
 * usb_pipe_open():
 *
 * Before using any pipe including the default pipe, it must be opened.
 * On success, a pipe handle is returned for use in other usb_pipe_*()
 * functions.
 *
 * The default pipe can only be opened by the hub driver.
 *
 * For isochronous and interrupt pipes, bandwidth has been allocated and
 * guaranteed.
 *
 * Only the default pipe can be shared.  All other control pipes are
 * excusively opened by default.  A pipe policy and endpoint descriptor
 * must always be provided except for default pipe.
 *
 * Arguments:
 *	dip		- devinfo ptr.
 *	ep		- endpoint descriptor pointer.
 *	pipe_policy	- pointer to pipe policy which provides hints on how
 *			  the pipe will be used.
 *	flags		- USB_FLAGS_SLEEP wait for resources to become
 *			  available.
 *	pipe_handle	- a pipe handle pointer.  on a successful open,
 *			  a pipe_handle is returned in this pointer.
 *
 * Return values:
 *	USB_SUCCESS	 - open succeeded.
 *	USB_FAILURE	 - unspecified open failure or pipe is already open.
 *	USB_NO_RESOURCES - no resources were available to complete the open.
 *	USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes).
 *	USB_*		 - refer to list of all possible return values in
 *			   this file
 */
int usb_pipe_open(
	dev_info_t		*dip,
	usb_ep_descr_t		*ep,
	usb_pipe_policy_t	*pipe_policy,
	usb_flags_t		flags,
	usb_pipe_handle_t	*pipe_handle);


/*
 * usb_pipe_close():
 *
 * Closes the pipe, releases resources and frees the pipe_handle.
 * Automatic polling, if active,  will be terminated.
 *
 * Arguments:
 *	dip		- devinfo ptr.
 *	pipe_handle	- pipe handle.
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for resources, pipe
 *				to become free, and all callbacks completed.
 *	cb		- If USB_FLAGS_SLEEP has not been specified, a
 *			  callback will be performed.
 *	cb_arg		- the 2nd argument of the callback. Note that the
 *			  pipehandle will be zeroed and therefore not passed.
 *
 * Notes:
 *
 * Pipe close always succeeds regardless whether USB_FLAGS_SLEEP has been
 * specified or not.  An async close will always succeed if the hint in the
 * pipe policy has been correct about the max number of async requests
 * required.
 * In the unlikely event that no async requests can be queued, this
 * function will continue retrying before returning
 *
 * USBA prevents the client from submitting subsequent requests to a pipe
 * that is being closed.
 * Additional usb_pipe_close() requests on the same pipe causes USBA to
 * wait for the previous close(s) to complete.
 *
 * The pipe will not be destroyed until all activity on the pipe has
 * been drained, including outstanding request callbacks, async requests,
 * and other usb_pipe_*() calls.
 *
 * Calling usb_pipe_close() from a deferred callback (in kernel context)
 * with USB_FLAGS_SLEEP set, will cause deadlock
 */
void usb_pipe_close(
	dev_info_t		*dip,
	usb_pipe_handle_t	pipe_handle,
	usb_flags_t		flags,
	void			(*cb)(
				    usb_pipe_handle_t	ph,
				    usb_opaque_t	arg,	/* cb arg */
				    int			rval,
				    usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);


/*
 * usb_pipe_drain_reqs
 *	this function blocks until there are no more requests
 *	owned by this dip on the pipe
 *
 * Arguments:
 *	dip		- devinfo pointer
 *	pipe_handle	- opaque pipe handle
 *	timeout 	- timeout in seconds
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for completion.
 *	cb		- if USB_FLAGS_SLEEP has not been specified
 *			  this callback function will be called on
 *			  completion. This callback may be NULL
 *			  and no notification of completion will then
 *			  be provided.
 *	cb_arg		- 2nd argument to callback function.
 *
 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
 * been specified
 *
 * Returns:
 *	USB_SUCCESS	- pipe successfully reset or request queued
 *	USB_FAILURE	- timeout
 *	USB_INVALID_PIPE - pipe is invalid or already closed
 *	USB_INVALID_CONTEXT - called from interrupt context
 *	USB_INVALID_ARGS - invalid arguments
 *	USB_*		- refer to return values defines in this file
 */
int usb_pipe_drain_reqs(
	dev_info_t		*dip,
	usb_pipe_handle_t	pipe_handle,
	uint_t			time,
	usb_flags_t		flags,
	void			(*cb)(
				    usb_pipe_handle_t	ph,
				    usb_opaque_t	arg,	/* cb arg */
				    int			rval,
				    usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);


/*
 * Resetting a pipe: Refer to USB 2.0/10.5.2.2
 *	The pipe's requests are retired and the pipe is cleared.  The host state
 *	is moved to active. If the reflected endpoint state needs to be changed,
 *	that must be explicitly requested by the client driver.  The reset
 *	completes after all request callbacks have been completed.
 *
 * Arguments:
 *	dip		- devinfo pointer.
 *	pipe_handle	- pipe handle.
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for completion.
 *	cb		- if USB_FLAGS_SLEEP has not been specified
 *			  this callback function will be called on
 *			  completion. This callback may be NULL
 *			  and no notification of completion will then
 *			  be provided.
 *	cb_arg		- 2nd argument to callback function.
 *
 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
 * been specified
 *
 * Note: Completion notification may be *before* all async request threads
 *	have completed but *after* all immediate callbacks have completed.
 */
void usb_pipe_reset(
	dev_info_t		*dip,
	usb_pipe_handle_t	pipe_handle,
	usb_flags_t		usb_flags,
	void			(*cb)(
					usb_pipe_handle_t ph,
					usb_opaque_t	arg,
					int		rval,
					usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);


/*
 * The client driver can store a private data pointer in the
 * pipe_handle.
 *
 * return values:
 *	USB_SUCCESS	 - success
 *	USB_FAILURE	 - unspecified failure
 */
int usb_pipe_set_private(
	usb_pipe_handle_t	pipe_handle,
	usb_opaque_t		data);


usb_opaque_t usb_pipe_get_private(
	usb_pipe_handle_t	pipe_handle);


/*
 * ***************************************************************************
 * Transfer request definitions and functions
 * ***************************************************************************
 */


/*
 * USB xfer request attributes.
 * Set by the client driver, more than one may be set
 *
 * SHORT_XFER_OK if less data is transferred than specified, no error is
 *		returned.
 * AUTOCLEARING	if there is an exception, the pipe will be reset first
 *		and a functional stall cleared before a callback is done.
 * PIPE_RESET	if there is an exception, the pipe will be reset only
 * ONE_XFER	polling will automatically stop on the first callback.
 * ISOC_START_FRAME use startframe specified.
 * USB_ATTRS_ISOC_XFER_ASAP let the host controller decide on the first
 *		available frame.
 *
 * USB_ATTRS_ISOC_START_FRAME and USB_ATTRS_ISOC_XFER_ASAP are mutually
 * exclusive
 *
 * combinations of flag and attributes:
 *
 * usb_flags	usb_req_attrs			semantics
 * ---------------------------------------------------------
 * SLEEP	USB_ATTRS_SHORT_XFER_OK		legal for IN pipes
 * SLEEP	USB_ATTRS_AUTOCLEARING		legal
 * SLEEP	USB_ATTRS_PIPE_RESET		legal
 * SLEEP	USB_ATTRS_ONE_XFER		legal for interrupt IN pipes
 * SLEEP	USB_ATTRS_ISOC_START_FRAME	illegal
 * SLEEP	USB_ATTRS_ISOC_XFER_ASAP	illegal
 *
 * noSLEEP	USB_ATTRS_SHORT_XFER_OK		legal for all IN pipes
 * noSLEEP	USB_ATTRS_AUTOCLEARING		legal
 * noSLEEP	USB_ATTRS_PIPE_RESET		legal
 * noSLEEP	USB_ATTRS_ONE_XFER		legal
 * noSLEEP	USB_ATTRS_ISOC_START_FRAME	legal
 * noSLEEP	USB_ATTRS_ISOC_XFER_ASAP	legal
 */
typedef enum {
	USB_ATTRS_NONE			= 0,

	/* only ctrl/bulk/intr IN pipes */
	USB_ATTRS_SHORT_XFER_OK		= 0x01,	/* short data xfer is ok */
	USB_ATTRS_PIPE_RESET		= 0x02,	/* reset pipe only on exc */
	USB_ATTRS_AUTOCLEARING		= 0x12, /* autoclear STALLs */

	/* intr pipes only: one poll with data */
	USB_ATTRS_ONE_XFER		= 0x100,

	/* only for isoch pipe */
	USB_ATTRS_ISOC_START_FRAME	= 0x200, /* Starting frame# specified */
	USB_ATTRS_ISOC_XFER_ASAP	= 0x400	/* HCD decides START_FRAME#  */
} usb_req_attrs_t;


/*
 * Note: client drivers are required to provide data buffers (mblks) for most
 * requests
 *			IN		OUT
 * ctlr request		if wLength > 0	if wLength > 0
 * bulk request		yes		yes
 * intr request		no		yes
 * isoc request		no		yes
 */

/*
 * ===========================================================================
 * USB control request management
 * ===========================================================================
 */

/*
 * A client driver allocates and uses the usb_ctrl_req_t for all control
 * pipe requests.
 *
 * Direction of the xfer will be determined based on the bmRequestType.
 *
 * NULL callbacks are permitted, timeout = 0 indicates infinite timeout.
 * All timeouts are in seconds.
 *
 * All fields are initialized by client except for data on IN request
 * in which case the client is responsible for deallocating.
 *
 * Control requests may be reused.  The client driver is responsible
 * for reinitializing some fields, eg data read/write pointers.
 *
 * Control requests can be queued.
 */
typedef struct usb_ctrl_req {
	uint8_t		ctrl_bmRequestType; /* characteristics of request */
	uint8_t		ctrl_bRequest;	/* specific request		*/
	uint16_t	ctrl_wValue;	/* varies according to request	*/
	uint16_t	ctrl_wIndex;	/* index or offset		*/
	uint16_t	ctrl_wLength;	/* number of bytes to xfer	*/

	mblk_t		*ctrl_data;	/* the data for the data phase	*/
					/* IN: allocated by HCD		*/
					/* OUT: allocated by client	*/
	uint_t		ctrl_timeout;	/* how long before HCD retires req */
	usb_opaque_t	ctrl_client_private; /* for client private info	*/
	usb_req_attrs_t ctrl_attributes; /* attributes for this req */

	/*
	 * callback function for control pipe requests
	 *
	 * a normal callback will be done upon:
	 *	- successful completion of a control pipe request
	 *
	 * callback arguments are:
	 *	- the pipe_handle
	 *	- usb_ctrl_req_t pointer
	 */
	void		(*ctrl_cb)(usb_pipe_handle_t ph,
				struct usb_ctrl_req *req);

	/*
	 * exception callback function for control pipe
	 *
	 * a exception callback will be done upon:
	 *	- an exception/error (all types)
	 *	- partial xfer of data unless SHORT_XFER_OK has been set
	 *
	 * callback arguments are:
	 *	- the pipe_handle
	 *	- usb_ctrl_req_t pointer
	 *
	 * if USB_ATTRS_AUTOCLEARING was set, autoclearing will be attempted
	 * and usb_cb_flags_t in usb_ctrl_req may indicate what was done
	 */
	void		(*ctrl_exc_cb)(usb_pipe_handle_t ph,
				struct usb_ctrl_req *req);

	/* set by USBA/HCD on completion */
	usb_cr_t	ctrl_completion_reason;	/* set by HCD */
	usb_cb_flags_t	ctrl_cb_flags;  /* Callback context / handling flgs */
} usb_ctrl_req_t;


/*
 * In the setup packet, the descriptor type is passed in the high byte of the
 * wValue field.
 * descriptor types:
 */
#define	USB_DESCR_TYPE_SETUP_DEV		0x0100
#define	USB_DESCR_TYPE_SETUP_CFG		0x0200
#define	USB_DESCR_TYPE_SETUP_STRING		0x0300
#define	USB_DESCR_TYPE_SETUP_IF			0x0400
#define	USB_DESCR_TYPE_SETUP_EP			0x0500
#define	USB_DESCR_TYPE_SETUP_DEV_QLF		0x0600
#define	USB_DESCR_TYPE_SETUP_OTHER_SPEED_CFG	0x0700
#define	USB_DESCR_TYPE_SETUP_IF_PWR		0x0800

#define	USB_DESCR_TYPE_DEV			0x01
#define	USB_DESCR_TYPE_CFG			0x02
#define	USB_DESCR_TYPE_STRING			0x03
#define	USB_DESCR_TYPE_IF			0x04
#define	USB_DESCR_TYPE_EP			0x05
#define	USB_DESCR_TYPE_DEV_QLF			0x06
#define	USB_DESCR_TYPE_OTHER_SPEED_CFG		0x07
#define	USB_DESCR_TYPE_IF_PWR			0x08

/*
 * device request type
 */
#define	USB_DEV_REQ_HOST_TO_DEV		0x00
#define	USB_DEV_REQ_DEV_TO_HOST		0x80
#define	USB_DEV_REQ_DIR_MASK		0x80

#define	USB_DEV_REQ_TYPE_STANDARD	0x00
#define	USB_DEV_REQ_TYPE_CLASS		0x20
#define	USB_DEV_REQ_TYPE_VENDOR		0x40
#define	USB_DEV_REQ_TYPE_MASK		0x60

#define	USB_DEV_REQ_RCPT_DEV		0x00
#define	USB_DEV_REQ_RCPT_IF		0x01
#define	USB_DEV_REQ_RCPT_EP		0x02
#define	USB_DEV_REQ_RCPT_OTHER		0x03
#define	USB_DEV_REQ_RCPT_MASK		0x03

/*
 * device request
 */
#define	USB_REQ_GET_STATUS		0x00
#define	USB_REQ_CLEAR_FEATURE		0x01
#define	USB_REQ_SET_FEATURE		0x03
#define	USB_REQ_SET_ADDRESS		0x05
#define	USB_REQ_GET_DESCR		0x06
#define	USB_REQ_SET_DESCR		0x07
#define	USB_REQ_GET_CFG			0x08
#define	USB_REQ_SET_CFG			0x09
#define	USB_REQ_GET_IF			0x0a
#define	USB_REQ_SET_IF			0x0b
#define	USB_REQ_SYNC_FRAME		0x0c

/* language ID for string descriptors */
#define	USB_LANG_ID			0x0409

/*
 * Standard Feature Selectors
 */
#define	USB_EP_HALT			0x0000
#define	USB_DEV_REMOTE_WAKEUP		0x0001
#define	USB_DEV_TEST_MODE		0x0002


/*
 * Allocate usb control request
 *
 * Arguments:
 *	dip	- dev_info pointer of the client driver
 *	len	- length of "data" for this control request.
 *		  if 0, no mblk is alloc'ed
 *	flags	- USB_FLAGS_SLEEP: Sleep if resources are not available
 *
 * Return Values:
 *	usb_ctrl_req_t pointer on success, NULL on failure
 *
 * Implementation NOTE: the dip allows checking on detach for memory leaks
 */
usb_ctrl_req_t *usb_alloc_ctrl_req(
	dev_info_t		*dip,
	size_t			len,
	usb_flags_t		flags);


/*
 * free USB control request
 */
void usb_free_ctrl_req(
	usb_ctrl_req_t	*reqp);


/*
 * usb_pipe_ctrl_xfer();
 *	Client driver calls this function to issue the control
 *	request to the USBA which will queue or transport it to the device
 *
 * Arguments:
 *	pipe_handle	- control pipe pipehandle (obtained via usb_pipe_open()
 *	reqp		- pointer to control request
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for the request to complete
 *
 * Return values:
 *	USB_SUCCESS	- successfully queued (no sleep) or successfully
 *			  completed (with sleep specified)
 *	USB_FAILURE	- failure
 *	USB_NO_RESOURCES - no resources
 */
int usb_pipe_ctrl_xfer(usb_pipe_handle_t pipe_handle,
	usb_ctrl_req_t	*reqp,
	usb_flags_t		flags);


/*
 * ---------------------------------------------------------------------------
 * Wrapper function which allocates and deallocates a request structure, and
 * performs a control transfer.
 * ---------------------------------------------------------------------------
 */

/*
 * Setup arguments for usb_pipe_ctrl_xfer_wait:
 *
 *	bmRequestType	- characteristics of request
 *	bRequest	- specific request
 *	wValue		- varies according to request
 *	wIndex		- index or offset
 *	wLength		- number of bytes to xfer
 *	attrs		- required request attributes
 *	data		- pointer to pointer to data
 *				IN: HCD will allocate data
 *				OUT: clients driver allocates data
 */
typedef struct usb_ctrl_setup {
	uchar_t		bmRequestType;
	uchar_t		bRequest;
	uint16_t	wValue;
	uint16_t	wIndex;
	uint16_t	wLength;
	usb_req_attrs_t	attrs;
} usb_ctrl_setup_t;


/*
 * usb_pipe_ctrl_xfer_wait():
 *	for simple synchronous control transactions this wrapper function
 *	will perform the allocation, xfer, and deallocation.
 *	USB_ATTRS_AUTOCLEARING will be enabled
 *
 * Arguments:
 *	pipe_handle	- control pipe pipehandle (obtained via usb_pipe_open())
 *	setup		- contains pointer to client's devinfo,
 *			  setup descriptor params, attributes and data
 *	completion_reason - completion status.
 *	cb_flags	- request completions flags.
 *	flags		- none.
 *
 * Return Values:
 *	USB_SUCCESS	- request successfully executed.
 *	USB_FAILURE	- request failed.
 *	USB_*		- refer to list of all possible return values in
 *			  this file
 *
 * NOTES:
 * - in the case of failure, the client should check completion_reason and
 *   and cb_flags and determine further recovery action
 * - the client should check data and if non-zero, free the data on
 *   completion
 */
int usb_pipe_ctrl_xfer_wait(
	usb_pipe_handle_t	pipe_handle,
	usb_ctrl_setup_t	*setup,
	mblk_t			**data,
	usb_cr_t		*completion_reason,
	usb_cb_flags_t		*cb_flags,
	usb_flags_t		flags);


/*
 * ---------------------------------------------------------------------------
 * Some utility defines and wrapper functions for standard control requests.
 * ---------------------------------------------------------------------------
 */

/*
 *
 * Status bits returned by a usb_get_status().
 */
#define	USB_DEV_SLF_PWRD_STATUS	1	/* Supports Self Power	 */
#define	USB_DEV_RWAKEUP_STATUS	2	/* Remote Wakeup Enabled */
#define	USB_EP_HALT_STATUS	1	/* Endpoint is Halted	 */
#define	USB_IF_STATUS		0	/* Interface Status is 0 */

/* length of data returned by USB_REQ_GET_STATUS */
#define	USB_GET_STATUS_LEN		2

/*
 * wrapper function returning status of device, interface, or endpoint
 *
 * Arguments:
 *	dip		- devinfo pointer.
 *	ph		- pipe handle
 *	type		- bmRequestType to be used
 *	what		- 0 for device, otherwise interface or ep number
 *	status		- pointer to returned status.
 *	flags		- USB_FLAGS_SLEEP (mandatory)
 *
 * Return Values:
 *	valid usb_status_t	or USB_FAILURE
 *
 */
int usb_get_status(
	dev_info_t		*dip,
	usb_pipe_handle_t	ph,
	uint_t			type,	/* bmRequestType */
	uint_t			what,	/* 0, interface, endpoint number */
	uint16_t		*status,
	usb_flags_t		flags);


/*
 * function for clearing feature of device, interface, or endpoint
 *
 * Arguments:
 *	dip		- devinfo pointer.
 *	type		- bmRequestType to be used
 *	feature		- feature to be cleared
 *	what		- 0 for device, otherwise interface or ep number
 *	flags		- USB_FLAGS_SLEEP (mandatory)
 *	cb		- if USB_FLAGS_SLEEP has not been specified
 *			  this callback function will be called on
 *			  completion. This callback may be NULL
 *			  and no notification of completion will then
 *			  be provided.
 *	cb_arg		- 2nd argument to callback function.
 *
 * Return Values:
 *	USB_SUCCESS	clearing feature succeeded
 *	USB_FAILURE	clearing feature failed
 *	USB_*		refer to list of all possible return values in
 *			this file
 */
int usb_clr_feature(
	dev_info_t		*dip,
	uint_t			type,	/* bmRequestType */
	uint_t			feature,
	uint_t			what,	/* 0, interface, endpoint number */
	usb_flags_t		flags,
	void			(*cb)(
					usb_pipe_handle_t ph,
					usb_opaque_t	arg,
					int		rval,
					usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);


/*
 * usb_set_cfg():
 *	Sets the configuration.  Use this function with caution as
 *	the framework is normally responsible for configuration changes.
 *	Changing configuration will fail if pipes are still open or
 *	when invoked from a driver bound to an interface on a composite
 *	device. This function access the device and blocks.
 *
 * Arguments:
 *	dip		- devinfo pointer.
 *	cfg_index	- Index of configuration to set.  Corresponds to
 *			  index in the usb_client_dev_data_t tree of
 *			  configurations.  See usb_client_dev_data_t(9F).
 *	usb_flags	- USB_FLAGS_SLEEP:
 *				wait for completion.
 *	cb		- if USB_FLAGS_SLEEP has not been specified
 *			  this callback function will be called on
 *			  completion. This callback may be NULL
 *			  and no notification of completion will then
 *			  be provided.
 *	cb_arg		- 2nd argument to callback function.
 *
 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
 * been specified
 *
 * Return Values:
 *	USB_SUCCESS:	new configuration was set or async request
 *			submitted successfully.
 *	USB_FAILURE:	new configuration could not be set because
 *			it may been illegal configuration or this
 *			caller was not allowed to change configs or
 *			pipes were still open or async request
 *			could not be submitted.
 *	USB_*		refer to list of all possible return values in
 *			this file
 *
 * the pipe handle argument in the callback will be the default pipe handle
 */
int usb_set_cfg(
	dev_info_t		*dip,
	uint_t			cfg_index,
	usb_flags_t		usb_flags,
	void			(*cb)(
					usb_pipe_handle_t ph,
					usb_opaque_t	arg,
					int		rval,
					usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);


/*
 * usb_get_cfg:
 *	dip		- pointer to devinfo node
 *	cfgval		- pointer to cfgval
 *	usb_flags	- none, will always block
 *
 * return values:
 *	USB_SUCCESS	- current cfg value is returned to cfgval
 *	USB_*		- refer to list of all possible return values in
 *			  this file
 */
int usb_get_cfg(
	dev_info_t		*dip,
	uint_t			*cfgval,
	usb_flags_t		usb_flags);


/*
 * The following functions set or get the alternate interface
 * setting.
 *
 * usb_set_alt_if:
 *	dip		- pointer to devinfo node
 *	interface	- interface
 *	alt_number	- alternate to set to
 *	usb_flags	- USB_FLAGS_SLEEP:
 *				wait for completion.
 *	cb		- if USB_FLAGS_SLEEP has not been specified
 *			  this callback function will be called on
 *			  completion. This callback may be NULL
 *			  and no notification of completion will then
 *			  be provided.
 *	cb_arg		- 2nd argument to callback function.
 *
 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
 * been specified
 *
 * the pipe handle argument in the callback will be the default pipe handle
 *
 * return values:
 *	USB_SUCCESS:	alternate was set or async request was
 *			submitted.
 *	USB_FAILURE:	alternate could not be set because pipes
 *			were still open or some access error occurred
 *			or an invalid alt if value was passed or
 *			async request could not be submitted
 *	USB_INVALID_PERM the driver does not own the device or the interface
 *	USB_*		refer to list of all possible return values in
 *			this file
 */
int usb_set_alt_if(
	dev_info_t		*dip,
	uint_t			interface,
	uint_t			alt_number,
	usb_flags_t		usb_flags,
	void			(*cb)(
					usb_pipe_handle_t ph,
					usb_opaque_t	arg,
					int		rval,
					usb_cb_flags_t	flags),
	usb_opaque_t		cb_arg);



/* flags must be USB_FLAGS_SLEEP, and this function will block */
int usb_get_alt_if(
	dev_info_t		*dip,
	uint_t			if_number,
	uint_t			*alt_number,
	usb_flags_t		flags);


/*
 * ===========================================================================
 * USB bulk request management
 * ===========================================================================
 */

/*
 * A client driver allocates/uses the usb_bulk_req_t for bulk pipe xfers.
 *
 * NOTES:
 * - bulk pipe sharing is not supported
 * - semantics of combinations of flag and attributes:
 *
 * flags     Type  attributes	data	timeout semantics
 * ----------------------------------------------------------------
 *  x	      x    x		== NULL    x	   illegal
 *
 * no sleep  IN    x		!= NULL    0	   fill buffer, no timeout
 *						   callback when xfer-len has
 *						   been xferred
 * no sleep  IN    x		!= NULL    > 0	   fill buffer, with timeout
 *						   callback when xfer-len has
 *						   been xferred
 *
 * sleep     IN    x		!= NULL    0	   fill buffer, no timeout
 *						   unblock when xfer-len has
 *						   been xferred
 *						   no callback
 * sleep     IN    x		!= NULL    > 0	   fill buffer, with timeout
 *						   unblock when xfer-len has
 *						   been xferred or timeout
 *						   no callback
 *
 *  X	     OUT SHORT_XFER_OK	  x	   x	   illegal
 *
 * no sleep  OUT   x		!= NULL    0	   empty buffer, no timeout
 *						   callback when xfer-len has
 *						   been xferred
 * no sleep  OUT   x		!= NULL    > 0	   empty buffer, with timeout
 *						   callback when xfer-len has
 *						   been xferred or timeout
 *
 * sleep     OUT   x		!= NULL    0	   empty buffer, no timeout
 *						   unblock when xfer-len has
 *						   been xferred
 *						   no callback
 * sleep     OUT   x		!= NULL    > 0	   empty buffer, with timeout
 *						   unblock when xfer-len has
 *						   been xferred or timeout
 *						   no callback
 *
 * - bulk_len and bulk_data must be > 0.  SHORT_XFER_OK is not applicable.
 *
 * - multiple bulk requests can be queued
 *
 * - Splitting large Bulk xfer:
 * The HCD driver, due to internal constraints, can only do a limited size bulk
 * data xfer per request.  The current limitations are 32K for UHCI and 128K
 * for OHCI.  So, a client driver may first determine this limitation (by
 * calling the USBA interface usb_pipe_bulk_transfer_size()); and restrict
 * itself to doing xfers in multiples of this fixed size.  This forces a client
 * driver to do data xfers in a loop for a large request, splitting it into
 * multiple chunks of fixed size.
 */
typedef struct usb_bulk_req {
	uint_t		bulk_len;	/* number of bytes to xfer	*/
	mblk_t		*bulk_data;	/* the data for the data phase	*/
					/* IN: allocated by HCD		*/
					/* OUT: allocated by client	*/
	uint_t		bulk_timeout;	/* xfer timeout value in secs	*/
	usb_opaque_t	bulk_client_private; /* Client specific information */
	usb_req_attrs_t bulk_attributes; /* xfer-attributes	*/

	/* Normal Callback function (For synch xfers) */
	void		(*bulk_cb)(usb_pipe_handle_t ph,
				struct usb_bulk_req *req);

	/* Exception Callback function (For asynch xfers) */
	void		(*bulk_exc_cb)(usb_pipe_handle_t ph,
				struct usb_bulk_req *req);

	/* set by USBA/HCD on completion */
	usb_cr_t	bulk_completion_reason;	/* set by HCD		*/
	usb_cb_flags_t	bulk_cb_flags;  /* Callback context / handling flgs */
} usb_bulk_req_t;


/*
 * Allocate/free usb bulk request
 *
 * Arguments:
 *	dip		- pointer to dev_info_t of the client driver
 *	len		- 0 or length of mblk to be allocated
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for resources
 *
 * Return Values:
 *	usb_bulk_req_t on success, NULL on failure
 */
usb_bulk_req_t *usb_alloc_bulk_req(
	dev_info_t		*dip,
	size_t			len,
	usb_flags_t		flags);


void usb_free_bulk_req(
	usb_bulk_req_t	*reqp);


/*
 * usb_pipe_bulk_xfer():
 *
 * Client drivers call this function to issue the bulk xfer to the USBA
 * which will queue or transfer it to the device
 *
 * Arguments:
 *	pipe_handle	- bulk pipe handle (obtained via usb_pipe_open()
 *	reqp		- pointer to bulk data xfer request (IN or OUT)
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for the request to complete
 *
 * Return Values:
 *	USB_SUCCESS	- success
 *	USB_FAILURE	- unspecified failure
 *	USB_NO_RESOURCES - no resources
 *
 */
int usb_pipe_bulk_xfer(
	usb_pipe_handle_t	pipe_handle,
	usb_bulk_req_t		*reqp,
	usb_flags_t		flags);

/* Get maximum bulk transfer size */
int usb_pipe_get_max_bulk_transfer_size(
	dev_info_t		*dip,
	size_t			*size);


/*
 * ===========================================================================
 * USB interrupt pipe request management
 * ===========================================================================
 */

/*
 * A client driver allocates and uses the usb_intr_req_t for
 * all interrupt pipe transfers.
 *
 * USB_FLAGS_SLEEP indicates here just to wait for resources except
 * for ONE_XFER where we also wait for completion
 *
 * semantics flags and attribute combinations:
 *
 * Notes:
 * none attributes indicates neither ONE_XFER nor SHORT_XFER_OK
 *
 * flags     Type  attributes	   data    timeout semantics
 * ----------------------------------------------------------------
 *  x	     IN      x		   != NULL  x	    illegal
 *  x	     IN   ONE_XFER=0	   x	   !=0	    illegal
 *
 *  x	     IN   ONE_XFER=0	   NULL     0	   continuous polling,
 *						   many callbacks
 *						   request is returned on
 *						   stop polling
 *
 * no sleep  IN   ONE_XFER	   NULL     0	   one time poll, no timeout,
 *						   one callback
 * no sleep  IN   ONE_XFER	   NULL    !=0	   one time poll, with
 *						   timeout, one callback
 *
 * sleep     IN   ONE_XFER	   NULL     0	   one time poll, no timeout,
 *						   no callback,
 *						   block for completion
 * sleep     IN   ONE_XFER	   NULL    !=0	   one time poll, with timeout,
 *						   no callback
 *						   block for completion
 *
 *  x	     OUT     x		   NULL    x	   illegal
 *  x	     OUT  ONE_XFER	   x	   x	   illegal
 *  x	     OUT  SHORT_XFER_OK    x	   x	   illegal
 *
 *  x	     OUT   none		   != NULL 0	   xfer until data exhausted,
 *						   no timeout,	one callback
 *  x	     OUT   none		   != NULL !=0	   xfer until data exhausted,
 *						   with timeout, one callback
 *
 * - Reads (IN):
 *
 * The client driver does *not* provide a data buffer.
 * By default, a READ request would mean continuous polling for data IN. The
 * HCD typically reads "wMaxPacketSize" amount of 'periodic data'. A client
 * driver may force the HCD to read instead intr_len
 * amount of 'periodic data' (See section 1).
 *
 * The HCD issues a callback to the client after each polling interval if
 * it has read in some data. Note that the amount of data read IN is either
 * intr_len or 'wMaxPacketSize' in length.
 *
 * Normally, the HCD keeps polling interrupt pipe forever even if there is
 * no data to be read IN.  A client driver may stop this polling by
 * calling usb_pipe_stop_intr_polling().
 *
 * If a client driver chooses to pass USB_ATTRS_ONE_XFER as
 * 'xfer_attributes' the HCD will poll for data until some data is received.
 * HCD reads in the data and does a callback and stops polling for any more
 * data.  In this case, the client driver need not explicitly call
 * usb_pipe_stop_intr_polling().
 *
 * When continuous polling is stopped, the original request is returned with
 * USB_CR_STOPPED_POLLING.
 *
 * - Writes (OUT):
 *
 * A client driver provides the data buffer, and data, needed for intr write.
 * There is no continuous write mode, a la  read (See previous section).
 * The USB_ATTRS_ONE_XFER attribute is illegal.
 * By default USBA keeps writing intr data until the provided data buffer
 * has been written out. The HCD does ONE callback to the client driver.
 * Queueing is supported.
 * Max size is 8k
 */
typedef struct usb_intr_req {
	uint_t		intr_len;	/* OUT: size of total xfer */
					/* IN : packet size */
	mblk_t		*intr_data;	/* the data for the data phase	*/
					/* IN: allocated by HCD		*/
					/* OUT: allocated by client	*/
	usb_opaque_t	intr_client_private; /* Client specific information  */
	uint_t		intr_timeout;	/* only with ONE TIME POLL, in secs */
	usb_req_attrs_t	intr_attributes;

	/* Normal callback function (For synch transfers) */
	void		(*intr_cb)(usb_pipe_handle_t ph,
				struct usb_intr_req *req);

	/* Exception callback function (For asynch transfers) */
	void		(*intr_exc_cb)(usb_pipe_handle_t ph,
				struct usb_intr_req *req);

	/* set by USBA/HCD on completion */
	usb_cr_t	intr_completion_reason;	/* set by HCD */
	usb_cb_flags_t	intr_cb_flags;  /* Callback context / handling flgs */
} usb_intr_req_t;


/*
 * Allocate/free usb interrupt pipe request
 *
 * Arguments:
 *	dip		- pointer to dev_info_t of the client driver
 *	reqp		- pointer to request structure
 *	len		- 0 or length of mblk for this interrupt request
 *	flags		- USB_FLAGS_SLEEP:
 *				Sleep if resources are not available
 *
 * Return Values:
 *	usb_intr_req_t on success, NULL on failure
 */
usb_intr_req_t *usb_alloc_intr_req(
	dev_info_t		*dip,
	size_t			len,
	usb_flags_t		flags);


void usb_free_intr_req(
	usb_intr_req_t	*reqp);


/*
 * usb_pipe_intr_xfer():
 *
 * Client drivers call this function to issue the intr xfer to USBA/HCD
 * which starts polling the device
 *
 * Arguments:
 *	pipe_handle	- interrupt pipe handle (obtained via usb_pipe_open()
 *	reqp		- pointer tothe interrupt pipe xfer request (IN or OUT)
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for resources to be available
 *
 * return values:
 *	USB_SUCCESS	- success
 *	USB_FAILURE	- unspecified failure
 *	USB_NO_RESOURCES  - no resources
 *
 * NOTE: start polling on an IN pipe that is already being polled is a NOP.
 *	 We don't queue requests on OUT pipe
 */
int usb_pipe_intr_xfer(
	usb_pipe_handle_t	pipe_handle,
	usb_intr_req_t		*req,
	usb_flags_t		flags);


/*
 * usb_pipe_stop_intr_polling():
 *
 * Client drivers call this function to stop the automatic data-in/out transfers
 * without closing the pipe.
 *
 * If USB_FLAGS_SLEEP  has been specified then this function will block until
 * polling has been stopped and all callbacks completed. If USB_FLAGS_SLEEP
 * has NOT been specified then polling is terminated when the original
 * request that started the polling has been returned with
 * USB_CR_STOPPED_POLLING
 *
 * Stop polling should never fail.
 *
 * Args:-
 *	pipe_handle	- interrupt pipe handle (obtained via usb_pipe_open()).
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for the resources to be available.
 */
void usb_pipe_stop_intr_polling(
	usb_pipe_handle_t	pipe_handle,
	usb_flags_t		flags);


/*
 * ===========================================================================
 * USB isochronous xfer management
 * ===========================================================================
 */

/*
 * The usb frame number is an absolute number since boot and incremented
 * every 1 ms.
 */
typedef	uint64_t	usb_frame_number_t;

/*
 * USB ischronous packet descriptor
 *
 * An array of structures of type usb_isoc_pkt_descr_t must be allocated and
 * initialized by the client driver using usb_alloc_isoc_req(). The client
 * driver must set isoc_pkt_length in each packet descriptor before submitting
 * the request.
 */
typedef struct usb_isoc_pkt_descr {
	/*
	 * Set by the client driver, for all isochronous requests, to the
	 * number of bytes to transfer in a frame.
	 */
	ushort_t	isoc_pkt_length;

	/*
	 * Set by HCD to actual number of bytes sent/received in frame.
	 */
	ushort_t	isoc_pkt_actual_length;

	/*
	 * Per frame status set by HCD both for the isochronous IN and OUT
	 * requests.  If any status is non-zero then isoc_error_count in the
	 * isoc_req will be non-zero.
	 */
	usb_cr_t	isoc_pkt_status;
} usb_isoc_pkt_descr_t;


/*
 * USB isochronous request
 *
 * The client driver allocates the usb_isoc_req_t before sending an
 * isochronous requests.
 *
 * USB_FLAGS_SLEEP indicates here just to wait for resources but not
 * to wait for completion
 *
 * Semantics of various combinations for data xfers:
 *
 * Note: attributes considered in this table are ONE_XFER, START_FRAME,
 *	XFER_ASAP, SHORT_XFER
 *
 *
 * flags     Type  attributes		   data    semantics
 * ---------------------------------------------------------------------
 * x	     x	   x			NULL	   illegal
 *
 * x	     x	   ONE_XFER		 x	   illegal
 *
 * x	     IN    x			!=NULL	   continuous polling,
 *						   many callbacks
 *
 * x	     IN    ISOC_START_FRAME	!=NULL	   invalid if Current_frame# >
 *						   "isoc_frame_no"
 * x	     IN    ISOC_XFER_ASAP	!=NULL	   "isoc_frame_no" ignored.
 *						   HCD determines when to
 *						   insert xfer
 *
 * x	     OUT   ONE_XFER		x	   illegal
 * x	     OUT   SHORT_XFER_OK	x	   illegal
 *
 * x	     OUT   ISOC_START_FRAME	!=NULL	   invalid if Current_frame# >
 *						   "isoc_frame_no"
 * x	     OUT   ISOC_XFER_ASAP	!=NULL	   "isoc_frame_no" ignored.
 *						    HCD determines when to
 *						   insert xfer
 */
typedef struct usb_isoc_req {
	/*
	 * Starting frame number will be set by the client driver in which
	 * to begin this request. This frame number is used to synchronize
	 * requests queued to different isochronous pipes. The frame number
	 * is optional and client driver can skip starting frame number by
	 * setting USB_ISOC_ATTRS_ASAP. In this case, HCD will decide starting
	 * frame number for this isochronous request.  If this field is 0,
	 * then this indicates an invalid frame number.
	 */
	usb_frame_number_t	isoc_frame_no;

	/*
	 * Number and length of isochronous data packets.
	 * The first field is set by client  driver and may not exceed
	 * the maximum number of entries in the usb isochronous packet
	 * descriptors.
	 */
	ushort_t		isoc_pkts_count;
	ushort_t		isoc_pkts_length;

	/*
	 * This field will be set by HCD and this field indicates the number
	 * of packets that completed with errors.
	 */
	ushort_t		isoc_error_count;

	/*
	 * Attributes specific to particular usb isochronous request.
	 * Supported values are: USB_ATTRS_ISOC_START_FRAME,
	 * USB_ATTRS_ISOC_XFER_ASAP.
	 */
	usb_req_attrs_t 	isoc_attributes;

	/*
	 * Isochronous OUT:
	 *	allocated and set by client driver, freed and zeroed by HCD
	 *	on successful completion
	 * Isochronous IN:
	 *	allocated and set by HCD, freed by client driver
	 */
	mblk_t			*isoc_data;

	/*
	 * The client driver specific private information.
	 */
	usb_opaque_t		isoc_client_private;

	/*
	 * Isochronous OUT:
	 *	must be allocated & initialized by client driver
	 * Isochronous IN:
	 *	must be allocated by client driver
	 */
	struct usb_isoc_pkt_descr *isoc_pkt_descr;

	/* Normal callback function (For synch transfers) */
	void			(*isoc_cb)(usb_pipe_handle_t ph,
					struct usb_isoc_req *req);

	/* Exception callback function (For asynch transfers) */
	void			(*isoc_exc_cb)(usb_pipe_handle_t ph,
					struct usb_isoc_req *req);

	/* set by USBA/HCD on completion */
	usb_cr_t		isoc_completion_reason;	/* set by HCD */
					/* Callback context / handling flgs */
	usb_cb_flags_t		isoc_cb_flags;
} usb_isoc_req_t;


/*
 * Allocate/free usb isochronous resources
 *
 * isoc_pkts_count must be > 0
 *
 * Arguments:
 *	dip		- client driver's devinfo pointer
 *	isoc_pkts_count - number of pkts required
 *	len		- 0 or size of mblk to allocate
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for resources
 *
 * Return Values:
 *	usb_isoc_req pointer or NULL
 */
usb_isoc_req_t *usb_alloc_isoc_req(
	dev_info_t		*dip,
	uint_t			isoc_pkts_count,
	size_t			len,
	usb_flags_t		flags);

void	usb_free_isoc_req(
	usb_isoc_req_t		*usb_isoc_req);

/*
 * Returns current usb frame number.
 */
usb_frame_number_t usb_get_current_frame_number(
	dev_info_t		*dip);

/*
 * Get maximum isochronous packets per usb isochronous request
 */
uint_t usb_get_max_pkts_per_isoc_request(
	dev_info_t		*dip);

/*
 * usb_pipe_isoc_xfer()
 *
 * Client drivers call this to issue the isoch xfer (IN and OUT) to the USBA
 * which starts polling the device.
 *
 * Arguments:
 *	pipe_handle	- isoc pipe handle (obtained via usb_pipe_open().
 *	reqp		- pointer to the isochronous pipe IN xfer request
 *			  allocated by the client driver.
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for the resources to be available.
 *
 * return values:
 *	USB_SUCCESS	- success.
 *	USB_FAILURE	- unspecified failure.
 *	USB_NO_RESOURCES  - no resources.
 *	USB_NO_FRAME_NUMBER - START_FRAME, ASAP flags not specified.
 *	USB_INVALID_START_FRAME	- Starting USB frame number invalid.
 *
 * Notes:
 * - usb_pipe_isoc_xfer on an IN pipe that is already being polled is a NOP.
 * - requests can be queued on an OUT pipe.
 */
int usb_pipe_isoc_xfer(
	usb_pipe_handle_t	pipe_handle,
	usb_isoc_req_t		*reqp,
	usb_flags_t		flags);

/*
 * usb_pipe_stop_isoc_polling():
 *
 * Client drivers call this function to stop the automatic data-in/out
 * transfers without closing the isoc pipe.
 *
 * If USB_FLAGS_SLEEP  has been specified then this function will block until
 * polling has been stopped and all callbacks completed. If USB_FLAGS_SLEEP
 * has NOT been specified then polling is terminated when the original
 * request that started the polling has been returned with
 * USB_CR_STOPPED_POLLING
 *
 * Stop polling should never fail.
 *
 * Arguments:
 *	pipe_handle	- isoc pipe handle (obtained via usb_pipe_open().
 *	flags		- USB_FLAGS_SLEEP:
 *				wait for polling to be stopped and all
 *				callbacks completed.
 */
void usb_pipe_stop_isoc_polling(
	usb_pipe_handle_t	pipe_handle,
	usb_flags_t		flags);

/*
 * ***************************************************************************
 * USB device power management:
 * ***************************************************************************
 */

/*
 *
 * As any usb device will have a max of 4 possible power states
 * the #define	for them are provided below with mapping to the
 * corresponding OS power levels.
 */
#define	USB_DEV_PWR_D0		USB_DEV_OS_FULL_PWR
#define	USB_DEV_PWR_D1		5
#define	USB_DEV_PWR_D2		6
#define	USB_DEV_PWR_D3		USB_DEV_OS_PWR_OFF

#define	USB_DEV_OS_PWR_0	0
#define	USB_DEV_OS_PWR_1	1
#define	USB_DEV_OS_PWR_2	2
#define	USB_DEV_OS_PWR_3	3
#define	USB_DEV_OS_PWR_OFF	USB_DEV_OS_PWR_0
#define	USB_DEV_OS_FULL_PWR	USB_DEV_OS_PWR_3

/* Bit Masks for Power States */
#define	USB_DEV_OS_PWRMASK_D0	1
#define	USB_DEV_OS_PWRMASK_D1	2
#define	USB_DEV_OS_PWRMASK_D2	4
#define	USB_DEV_OS_PWRMASK_D3	8

/* conversion for OS to Dx levels */
#define	USB_DEV_OS_PWR2USB_PWR(l)	(USB_DEV_OS_FULL_PWR - (l))

/* from OS level to Dx mask */
#define	USB_DEV_PWRMASK(l)	(1 << (USB_DEV_OS_FULL_PWR - (l)))

/* Macro to check valid power level */
#define	USB_DEV_PWRSTATE_OK(state, level) \
		(((state) & USB_DEV_PWRMASK((level))) == 0)

int usb_handle_remote_wakeup(
	dev_info_t	*dip,
	int		cmd);

/* argument to usb_handle_remote wakeup function */
#define	USB_REMOTE_WAKEUP_ENABLE	1
#define	USB_REMOTE_WAKEUP_DISABLE	2

int usb_create_pm_components(
	dev_info_t	*dip,
	uint_t		*pwrstates);

/*
 * ***************************************************************************
 * System event registration
 * ***************************************************************************
 */

/* Functions for registering hotplug callback functions. */

int usb_register_hotplug_cbs(
	dev_info_t	*dip,
	int		(*disconnect_event_handler)(dev_info_t *dip),
	int		(*reconnect_event_handler)(dev_info_t *dip));

void usb_unregister_hotplug_cbs(dev_info_t *dip);


/*
 * ***************************************************************************
 * USB Device and interface class, subclass and protocol codes
 * ***************************************************************************
 */

/*
 * Available device and interface class codes.
 * Those which are device class codes are noted.
 */

#define	USB_CLASS_AUDIO		1
#define	USB_CLASS_COMM		2	/* Communication device class and */
#define	USB_CLASS_CDC_CTRL	2	/* CDC-control iface class, also 2 */
#define	USB_CLASS_HID		3
#define	USB_CLASS_PHYSICAL	5
#define	USB_CLASS_PRINTER	7
#define	USB_CLASS_MASS_STORAGE	8
#define	USB_CLASS_HUB		9	/* Device class */
#define	USB_CLASS_CDC_DATA	10
#define	USB_CLASS_CCID		11
#define	USB_CLASS_SECURITY	13
#define	USB_CLASS_DIAG		220	/* Device class */
#define	USB_CLASS_WIRELESS	224	/* Device class */
#define	USB_CLASS_MISC		239	/* Device class */
#define	USB_CLASS_APP		254
#define	USB_CLASS_VENDOR_SPEC	255	/* Device class */

#define	USB_CLASS_PER_INTERFACE	0	/* Class info is at interface level */

/* Audio subclass. */
#define	USB_SUBCLS_AUD_CONTROL		0x01
#define	USB_SUBCLS_AUD_STREAMING	0x02
#define	USB_SUBCLS_AUD_MIDI_STREAMING	0x03

/* Comms  subclass. */
#define	USB_SUBCLS_CDCC_DIRECT_LINE	0x01
#define	USB_SUBCLS_CDCC_ABSTRCT_CTRL	0x02
#define	USB_SUBCLS_CDCC_PHONE_CTRL	0x03
#define	USB_SUBCLS_CDCC_MULTCNL_ISDN	0x04
#define	USB_SUBCLS_CDCC_ISDN		0x05
#define	USB_SUBCLS_CDCC_ETHERNET	0x06
#define	USB_SUBCLS_CDCC_ATM_NETWORK	0x07

/* HID subclass and protocols. */
#define	USB_SUBCLS_HID_1		1

#define	USB_PROTO_HID_KEYBOARD		0x01	/* legacy keyboard */
#define	USB_PROTO_HID_MOUSE		0x02	/* legacy mouse */

/* Printer subclass and protocols. */
#define	USB_SUBCLS_PRINTER_1		1

#define	USB_PROTO_PRINTER_UNI		0x01	/* Unidirectional interface */
#define	USB_PROTO_PRINTER_BI		0x02	/* Bidirectional interface */

/* Mass storage subclasses and protocols. */
#define	USB_SUBCLS_MS_RBC_T10		0x1	/* flash */
#define	USB_SUBCLS_MS_SFF8020I		0x2	/* CD-ROM */
#define	USB_SUBCLS_MS_QIC_157		0x3	/* tape */
#define	USB_SUBCLS_MS_UFI		0x4	/* USB Floppy Disk Drive   */
#define	USB_SUBCLS_MS_SFF8070I		0x5	/* floppy */
#define	USB_SUBCLS_MS_SCSI		0x6	/* transparent scsi */

#define	USB_PROTO_MS_CBI_WC		0x00	/* USB CBI Proto w/cmp intr */
#define	USB_PROTO_MS_CBI		0x01    /* USB CBI Protocol */
#define	USB_PROTO_MS_ISD_1999_SILICN	0x02    /* ZIP Protocol */
#define	USB_PROTO_MS_BULK_ONLY		0x50    /* USB Bulk Only Protocol */

/* Application subclasses. */
#define	USB_SUBCLS_APP_FIRMWARE		0x01	/* app spec f/w subclass */
#define	USB_SUBCLS_APP_IRDA		0x02	/* app spec IrDa subclass */
#define	USB_SUBCLS_APP_TEST		0x03	/* app spec test subclass */



#ifdef __cplusplus
}
#endif

#endif /* _SYS_USB_USBAI_H */
