mirror of
https://github.com/reactos/reactos.git
synced 2024-11-11 01:04:11 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
1072 lines
31 KiB
C
1072 lines
31 KiB
C
#ifndef __USBD_H__
|
|
#define __USBD_H__
|
|
/*
|
|
* Some USB bandwidth allocation constants.
|
|
*/
|
|
|
|
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
|
#define BW_HOST_DELAY 1000L /* nanoseconds */
|
|
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
|
|
/* 4 full-speed bit times (est.) */
|
|
|
|
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
|
|
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
|
|
#define FRAME_TIME_USECS 1000L
|
|
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
|
|
|
#define bit_time(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
|
|
/* Trying not to use worst-case bit-stuffing
|
|
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
|
|
/* bytecount = data payload byte count */
|
|
|
|
#define ns_to_us(ns) ((ns + 500L) / 1000L)
|
|
/* convert & round nanoseconds to microseconds */
|
|
|
|
#define usb_make_handle( dev_Id, if_iDx, endp_iDx) \
|
|
( ( DEV_HANDLE )( ( ( ( ( ULONG )dev_Id ) << 16 ) | ( ( ( ULONG )if_iDx ) << 8 ) ) | ( ( ULONG ) endp_iDx ) ) )
|
|
|
|
#define usb_make_ref( poinTER ) \
|
|
( poinTER ^ 0xffffffff )
|
|
|
|
#define ptr_from_ref uhci_make_ref
|
|
|
|
#define dev_id_from_handle( hanDLE ) ( ( ( ULONG ) ( hanDLE ) ) >> 16 )
|
|
#define if_idx_from_handle( hanDLE ) ( ( ( ( ULONG ) ( hanDLE ) ) << 16 ) >> 24 )
|
|
#define endp_idx_from_handle( hanDLE ) ( ( ( ULONG ) ( hanDLE ) ) & 0xff )
|
|
|
|
#define endp_from_handle( pDEV, hanDLE, peNDP ) \
|
|
{\
|
|
LONG if_idx, endp_idx;\
|
|
BOOLEAN def_endp; \
|
|
endp_idx = endp_idx_from_handle( hanDLE );\
|
|
if_idx = if_idx_from_handle( hanDLE );\
|
|
def_endp = ( ( hanDLE & 0xffff ) == 0xffff ); \
|
|
if( def_endp ) \
|
|
peNDP = &pdev->default_endp; \
|
|
else \
|
|
{ \
|
|
if( if_idx >= pdev->usb_config->if_count ) \
|
|
peNDP = NULL; \
|
|
else if( endp_idx >= pdev->usb_config->interf[ if_idx ].endp_count ) \
|
|
peNDP = NULL; \
|
|
else \
|
|
peNDP = &( pDEV )->usb_config->interf[ if_idx ].endp[ endp_idx ]; \
|
|
} \
|
|
}
|
|
|
|
#define endp_type( enDP ) \
|
|
( ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP ) \
|
|
? USB_ENDPOINT_XFER_CONTROL\
|
|
: ( ( enDP )->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) )
|
|
|
|
|
|
//init work data for urb
|
|
#define urb_init( uRb ) \
|
|
{\
|
|
RtlZeroMemory( ( uRb ), sizeof( URB ) ); \
|
|
InitializeListHead( &( uRb )->trasac_list ); \
|
|
}
|
|
|
|
#define UsbBuildInterruptOrBulkTransferRequest(uRb, \
|
|
endp_hanDle, \
|
|
data_Buf, \
|
|
data_sIze, \
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = endp_hanDle;\
|
|
( uRb )->data_buffer = data_Buf;\
|
|
( uRb )->data_length = data_sIze;\
|
|
( uRb )->completion = completIon;\
|
|
( uRb )->context = contExt; \
|
|
( uRb )->reference = refereNce; \
|
|
}
|
|
|
|
|
|
|
|
#define UsbBuildGetDescriptorRequest(uRb, \
|
|
endp_hAndle, \
|
|
descriPtorType, \
|
|
descriPtorIndex, \
|
|
languaGeId, \
|
|
data_bUffer, \
|
|
data_sIze, \
|
|
compleTion, \
|
|
contexT, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup;\
|
|
pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hAndle );\
|
|
( uRb )->data_length = ( data_sIze ); \
|
|
( uRb )->data_buffer = ( ( PUCHAR )data_bUffer ); \
|
|
( uRb )->completion = ( compleTion );\
|
|
( uRb )->context = ( ( PVOID )contexT ); \
|
|
( uRb )->reference = ( ULONG )refereNce; \
|
|
pseTup->wValue = ( ( descriPtorType ) << 8 )| ( descriPtorIndex ); \
|
|
pseTup->wLength = ( data_sIze ); \
|
|
pseTup->wIndex = ( languaGeId );\
|
|
pseTup->bRequest = USB_REQ_GET_DESCRIPTOR;\
|
|
pseTup->bmRequestType = 0x80;\
|
|
}
|
|
|
|
|
|
|
|
#define UsbBuildGetStatusRequest(uRb, \
|
|
endp_hanDle, \
|
|
recipiEnt, \
|
|
inDex, \
|
|
transferBufFer, \
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hanDle ); \
|
|
( uRb )->data_buffer = ( transferBufFer ); \
|
|
( uRb )->data_length = sizeof(USHORT); \
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt );\
|
|
( uRb )->reference = ( refereNce );\
|
|
pseTup->bmRequestType = ( 0x80 | recipiEnt );\
|
|
pseTup->bRequest = USB_REQ_GET_STATUS;\
|
|
pseTup->wIndex = ( inDex ); \
|
|
pseTup->wValue = 0;\
|
|
pseTup->wLength = sizeof( USHORT );\
|
|
}
|
|
|
|
|
|
#define UsbBuildFeatureRequest(uRb, \
|
|
endp_hanDle,\
|
|
recipiEnt, \
|
|
featureSelecTor, \
|
|
inDex, \
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hanDle ); \
|
|
( uRb )->data_buffer = NULL;\
|
|
( uRb )->data_length = ( 0 );\
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt ); \
|
|
( uRb )->reference = ( refereNce ); \
|
|
pseTup->bmRequestType = recipiEnt; \
|
|
pseTup->bRequest = USB_REQ_SET_FEATURE;\
|
|
pseTup->wValue = ( featureSelecTor );\
|
|
pseTup->wIndex = ( inDex );\
|
|
pseTup->wLength = 0;\
|
|
}
|
|
|
|
#define UsbBuildSelectConfigurationRequest(uRb, \
|
|
endp_hanDle,\
|
|
config_Val,\
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hanDle ); \
|
|
( uRb )->data_buffer = NULL;\
|
|
( uRb )->data_length = 0;\
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt ); \
|
|
( uRb )->reference = ( refereNce ); \
|
|
pseTup->bmRequestType = 0;\
|
|
pseTup->bRequest = USB_REQ_SET_CONFIGURATION;\
|
|
pseTup->wValue = ( config_Val );\
|
|
pseTup->wIndex = 0;\
|
|
pseTup->wLength = 0;\
|
|
}
|
|
|
|
#define UsbBuildSelectInterfaceRequest(uRb, \
|
|
endp_hanDle,\
|
|
if_Num, \
|
|
alt_Num,\
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hanDle ); \
|
|
( uRb )->data_buffer = NULL;\
|
|
( uRb )->data_length = 0;\
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt ); \
|
|
( uRb )->reference = ( refereNce ); \
|
|
pseTup->bmRequestType = 1;\
|
|
pseTup->bRequest = USB_REQ_SET_INERFACE;\
|
|
pseTup->wValue = ( alt_Num );\
|
|
pseTup->wIndex = ( if_Num );\
|
|
pseTup->wLength = 0;\
|
|
}
|
|
|
|
|
|
#define UsbBuildVendorRequest(uRb, \
|
|
endp_hanDle,\
|
|
data_bufFer, \
|
|
data_sIze, \
|
|
request_tYpe, \
|
|
requEst, \
|
|
vaLue, \
|
|
inDex, \
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{ \
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( endp_hanDle ); \
|
|
( uRb )->data_buffer = data_bufFer;\
|
|
( uRb )->data_length = data_sIze;\
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt ); \
|
|
( uRb )->reference = ( refereNce ); \
|
|
pseTup->bmRequestType = request_tYpe;\
|
|
pseTup->bRequest = requEst;\
|
|
pseTup->wValue = vaLue;\
|
|
pseTup->wIndex = inDex;\
|
|
pseTup->wLength = ( USHORT )data_sIze;\
|
|
}
|
|
|
|
#define UsbBuildResetPipeRequest(uRb, \
|
|
dev_hanDle, \
|
|
endp_aDdr, \
|
|
completIon, \
|
|
contExt, \
|
|
refereNce ) \
|
|
{\
|
|
PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\
|
|
urb_init( ( uRb ) );\
|
|
( uRb )->endp_handle = ( dev_hanDle | 0xffff ); \
|
|
( uRb )->completion = ( completIon );\
|
|
( uRb )->context = ( contExt ); \
|
|
( uRb )->reference = ( refereNce ); \
|
|
pseTup->bmRequestType = 0x02;\
|
|
pseTup->bRequest = USB_REQ_CLEAR_FEATURE;\
|
|
pseTup->wIndex = endp_aDdr;\
|
|
}
|
|
|
|
// Forward structs declarations
|
|
struct _URB;
|
|
struct _HCD;
|
|
struct _USB_DEV_MANAGER;
|
|
struct _USB_DEV;
|
|
struct _USB_ENDPOINT;
|
|
struct _USB_EVENT;
|
|
struct _USB_EVENT_POOL;
|
|
struct _USB_DRIVER;
|
|
|
|
/* USB constants */
|
|
|
|
#define USB_SPEED_FULL 0x00
|
|
#define USB_SPEED_LOW 0x01
|
|
#define USB_SPEED_HIGH 0x02
|
|
|
|
/*
|
|
* Device and/or Interface Class codes
|
|
*/
|
|
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
|
#define USB_CLASS_AUDIO 1
|
|
#define USB_CLASS_COMM 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
|
|
#define USB_CLASS_DATA 10
|
|
#define USB_CLASS_APP_SPEC 0xfe
|
|
#define USB_CLASS_VENDOR_SPEC 0xff
|
|
|
|
/*
|
|
* USB types
|
|
*/
|
|
#define USB_TYPE_MASK (0x03 << 5)
|
|
#define USB_TYPE_STANDARD (0x00 << 5)
|
|
#define USB_TYPE_CLASS (0x01 << 5)
|
|
#define USB_TYPE_VENDOR (0x02 << 5)
|
|
#define USB_TYPE_RESERVED (0x03 << 5)
|
|
|
|
/*
|
|
* USB recipients
|
|
*/
|
|
#define USB_RECIP_MASK 0x1f
|
|
#define USB_RECIP_DEVICE 0x00
|
|
#define USB_RECIP_INTERFACE 0x01
|
|
#define USB_RECIP_ENDPOINT 0x02
|
|
#define USB_RECIP_OTHER 0x03
|
|
|
|
/*
|
|
* USB directions
|
|
*/
|
|
#define USB_DIR_OUT 0
|
|
#define USB_DIR_IN 0x80
|
|
|
|
/*
|
|
* Descriptor types
|
|
*/
|
|
#define USB_DT_DEVICE 0x01
|
|
#define USB_DT_CONFIG 0x02
|
|
#define USB_DT_STRING 0x03
|
|
#define USB_DT_INTERFACE 0x04
|
|
#define USB_DT_ENDPOINT 0x05
|
|
|
|
#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
|
|
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
|
|
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
|
|
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
|
|
|
/*
|
|
* Descriptor sizes per descriptor type
|
|
*/
|
|
#define USB_DT_DEVICE_SIZE 18
|
|
#define USB_DT_CONFIG_SIZE 9
|
|
#define USB_DT_INTERFACE_SIZE 9
|
|
#define USB_DT_ENDPOINT_SIZE 7
|
|
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
|
#define USB_DT_HUB_NONVAR_SIZE 7
|
|
#define USB_DT_HID_SIZE 9
|
|
|
|
/*
|
|
* Endpoints
|
|
*/
|
|
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
|
#define USB_ENDPOINT_DIR_MASK 0x80
|
|
|
|
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
|
#define USB_ENDPOINT_XFER_CONTROL 0
|
|
#define USB_ENDPOINT_XFER_ISOC 1
|
|
#define USB_ENDPOINT_XFER_BULK 2
|
|
#define USB_ENDPOINT_XFER_INT 3
|
|
|
|
/*
|
|
* USB Packet IDs (PIDs)
|
|
*/
|
|
#define USB_PID_UNDEF_0 0xf0
|
|
#define USB_PID_OUT 0xe1
|
|
#define USB_PID_ACK 0xd2
|
|
#define USB_PID_DATA0 0xc3
|
|
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
|
#define USB_PID_SOF 0xa5
|
|
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
|
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
|
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
|
#define USB_PID_IN 0x69
|
|
#define USB_PID_NAK 0x5a
|
|
#define USB_PID_DATA1 0x4b
|
|
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
|
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
|
#define USB_PID_SETUP 0x2d
|
|
#define USB_PID_STALL 0x1e
|
|
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
|
|
|
/*
|
|
* Standard requests
|
|
*/
|
|
#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_DESCRIPTOR 0x06
|
|
#define USB_REQ_SET_DESCRIPTOR 0x07
|
|
#define USB_REQ_GET_CONFIGURATION 0x08
|
|
#define USB_REQ_SET_CONFIGURATION 0x09
|
|
#define USB_REQ_GET_INTERFACE 0x0A
|
|
#define USB_REQ_SET_INTERFACE 0x0B
|
|
#define USB_REQ_SYNCH_FRAME 0x0C
|
|
|
|
/*
|
|
* HID requests
|
|
*/
|
|
#define USB_REQ_GET_REPORT 0x01
|
|
#define USB_REQ_GET_IDLE 0x02
|
|
#define USB_REQ_GET_PROTOCOL 0x03
|
|
#define USB_REQ_SET_REPORT 0x09
|
|
#define USB_REQ_SET_IDLE 0x0A
|
|
#define USB_REQ_SET_PROTOCOL 0x0B
|
|
|
|
// HUB request
|
|
#define HUB_REQ_GET_STATE 0x02
|
|
|
|
// usb2.0 hub
|
|
#define HUB_REQ_CLEAR_TT_BUFFER 0x08
|
|
|
|
|
|
typedef LONG USBD_STATUS;
|
|
|
|
//
|
|
// USBD status codes
|
|
//
|
|
// Status values are 32 bit values layed out as follows:
|
|
//
|
|
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
|
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
|
// +---+---------------------------+-------------------------------+
|
|
// | S | Status Code |
|
|
// +---+---------------------------+-------------------------------+
|
|
//
|
|
// where
|
|
//
|
|
// S - is the state code
|
|
//
|
|
// 00 - completed with success
|
|
// 01 - request is pending
|
|
// 10 - completed with error, endpoint not stalled
|
|
// 11 - completed with error, endpoint stalled
|
|
//
|
|
//
|
|
// Code - is the status code
|
|
//
|
|
|
|
//
|
|
// Generic test for success on any status value (non-negative numbers
|
|
// indicate success).
|
|
//
|
|
|
|
#define usb_success(Status) ((USBD_STATUS)(Status) >= 0)
|
|
|
|
//
|
|
// Generic test for pending status value.
|
|
//
|
|
|
|
#define usb_pending(Status) ((ULONG)(Status) >> 30 == 1)
|
|
|
|
//
|
|
// Generic test for error on any status value.
|
|
//
|
|
|
|
#define usb_error(Status) ((USBD_STATUS)(Status) < 0)
|
|
|
|
//
|
|
// Generic test for stall on any status value.
|
|
//
|
|
|
|
#define usb_halted(Status) ((ULONG)(Status) >> 30 == 3)
|
|
|
|
//
|
|
// Macro to check the status code only
|
|
//
|
|
|
|
#define usb_status(Status) ((ULONG)(Status) & 0x0FFFFFFFL)
|
|
|
|
|
|
#define USB_STATUS_SUCCESS ((USBD_STATUS)0x00000000L)
|
|
#define USB_STATUS_PENDING ((USBD_STATUS)0x40000000L)
|
|
#define USB_STATUS_HALTED ((USBD_STATUS)0xC0000000L)
|
|
#define USB_STATUS_ERROR ((USBD_STATUS)0x80000000L)
|
|
|
|
//
|
|
// HC status codes
|
|
// Note: these status codes have both the error and the stall bit set.
|
|
//
|
|
#define USB_STATUS_CRC ((USBD_STATUS)0xC0000401L)
|
|
#define USB_STATUS_BTSTUFF ((USBD_STATUS)0xC0000402L)
|
|
#define USB_STATUS_DATA_TOGGLE_MISMATCH ((USBD_STATUS)0xC0000403L)
|
|
#define USB_STATUS_STALL_PID ((USBD_STATUS)0xC0000404L)
|
|
#define USB_STATUS_DEV_NOT_RESPONDING ((USBD_STATUS)0xC0000405L)
|
|
#define USB_STATUS_PID_CHECK_FAILURE ((USBD_STATUS)0xC0000406L)
|
|
#define USB_STATUS_UNEXPECTED_PID ((USBD_STATUS)0xC0000407L)
|
|
#define USB_STATUS_DATA_OVERRUN ((USBD_STATUS)0xC0000408L)
|
|
#define USB_STATUS_DATA_UNDERRUN ((USBD_STATUS)0xC0000409L)
|
|
#define USB_STATUS_RESERVED1 ((USBD_STATUS)0xC000040AL)
|
|
#define USB_STATUS_RESERVED2 ((USBD_STATUS)0xC000040BL)
|
|
#define USB_STATUS_BUFFER_OVERRUN ((USBD_STATUS)0xC000040CL)
|
|
#define USB_STATUS_BUFFER_UNDERRUN ((USBD_STATUS)0xC000040DL)
|
|
#define USB_STATUS_NOT_ACCESSED ((USBD_STATUS)0xC000040FL)
|
|
#define USB_STATUS_FIFO ((USBD_STATUS)0xC0000410L)
|
|
#define USB_STATUS_BABBLE_DETECTED ((USBD_STATUS)0xC0000408L)
|
|
|
|
//
|
|
// returned by HCD if a transfer is submitted to an endpoint that is
|
|
// stalled
|
|
//
|
|
#define USB_STATUS_ENDPOINT_HALTED ((USBD_STATUS)0xC0000430L)
|
|
|
|
//
|
|
// Software status codes
|
|
// Note: the following status codes have only the error bit set
|
|
//
|
|
#define USB_STATUS_NO_MEMORY ((USBD_STATUS)0x80000100L)
|
|
#define USB_STATUS_INVALID_URB_FUNCTION ((USBD_STATUS)0x80000200L)
|
|
#define USB_STATUS_INVALID_PARAMETER ((USBD_STATUS)0x80000300L)
|
|
|
|
//
|
|
// returned if client driver attempts to close an endpoint/interface
|
|
// or configuration with outstanding transfers.
|
|
//
|
|
#define USB_STATUS_ERROR_BUSY ((USBD_STATUS)0x80000400L)
|
|
//
|
|
// returned by USBD if it cannot complete a URB request, typically this
|
|
// will be returned in the URB status field when the Irp is completed
|
|
// with a more specific NT error code in the irp.status field.
|
|
//
|
|
#define USB_STATUS_REQUEST_FAILED ((USBD_STATUS)0x80000500L)
|
|
|
|
#define USB_STATUS_INVALID_PIPE_HANDLE ((USBD_STATUS)0x80000600L)
|
|
|
|
// returned when there is not enough bandwidth avialable
|
|
// to open a requested endpoint
|
|
#define USB_STATUS_NO_BANDWIDTH ((USBD_STATUS)0x80000700L)
|
|
//
|
|
// generic HC error
|
|
//
|
|
#define USB_STATUS_INTERNAL_HC_ERROR ((USBD_STATUS)0x80000800L)
|
|
//
|
|
// returned when a short packet terminates the transfer
|
|
// ie USBD_SHORT_TRANSFER_OK bit not set
|
|
//
|
|
#define USB_STATUS_ERROR_SHORT_TRANSFER ((USBD_STATUS)0x80000900L)
|
|
//
|
|
// returned if the requested start frame is not within
|
|
// USBD_ISO_START_FRAME_RANGE of the current USB frame,
|
|
// note that the stall bit is set
|
|
//
|
|
#define USB_STATUS_BAD_START_FRAME ((USBD_STATUS)0xC0000A00L)
|
|
//
|
|
// returned by HCD if all packets in an iso transfer complete with an error
|
|
//
|
|
#define USB_STATUS_ISOCH_REQUEST_FAILED ((USBD_STATUS)0xC0000B00L)
|
|
//
|
|
// returned by USBD if the frame length control for a given
|
|
// HC is already taken by anothe driver
|
|
//
|
|
#define USB_STATUS_FRAME_CONTROL_OWNED ((USBD_STATUS)0xC0000C00L)
|
|
//
|
|
// returned by USBD if the caller does not own frame length control and
|
|
// attempts to release or modify the HC frame length
|
|
//
|
|
#define USB_STATUS_FRAME_CONTROL_NOT_OWNED ((USBD_STATUS)0xC0000D00L)
|
|
|
|
//
|
|
// set when a transfers is completed due to an AbortPipe request from
|
|
// the client driver
|
|
//
|
|
// Note: no error or stall bit is set for these status codes
|
|
//
|
|
#define USB_STATUS_CANCELED ((USBD_STATUS)0x00010000L)
|
|
|
|
#define USB_STATUS_CANCELING ((USBD_STATUS)0x00020000L)
|
|
|
|
// Device type -- in the "User Defined" range."
|
|
#define FILE_HCD_DEV_TYPE 45000
|
|
#define FILE_UHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 1 )
|
|
#define FILE_OHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 2 )
|
|
#define FILE_EHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 3 )
|
|
#define FILE_USB_DEV_TYPE ( FILE_HCD_DEV_TYPE + 8 )
|
|
|
|
#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
|
//input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the
|
|
//dev count, output_buffer_length must be no less than sizeof( unsigned long ).
|
|
|
|
#define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
|
//input_buffer is a dword value to indicate the count of elements in the array
|
|
//input_buffer_length is sizeof( unsigned long ), output_buffer is to receive a
|
|
//structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array.
|
|
|
|
#define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
|
//input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is
|
|
//no less than sizeof( input_buffer ), output_buffer is a buffer to receive the
|
|
//requested dev's desc, and output_buffer_length specifies the length of the
|
|
//buffer
|
|
|
|
#define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
|
|
#define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
|
|
// if the major_function is IRP_MJ_DEVICE_CONTROL
|
|
// input_buffer is a URB, and input_buffer_length is equal to or greater than
|
|
// sizeof( URB ); the output_buffer is a buffer to receive data from or send data
|
|
// to device. only the following urb fields can be accessed, others must be zeroed.
|
|
// DEV_HANDLE endp_handle;
|
|
// UCHAR setup_packet[8]; // for control pipe
|
|
// the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined
|
|
// by the current URB, for example, a request string from device will use XXX_RD,
|
|
// and a write to the bulk endpoint will use XXX_WR
|
|
// if the major_function is IRP_MJ_INTERNAL_DEVICE_CONTROL
|
|
// input_buffer is a URB, and input_buffer_length is equal to or greater than
|
|
// sizeof( URB );
|
|
// only the following urb fields can be accessed, others must be zeroed.
|
|
// DEV_HANDLE endp_handle;
|
|
// UCHAR setup_packet[8]; // for control pipe, or zeroed
|
|
// PUCHAR data_buffer; // buffer for READ/WRITE
|
|
// ULONG data_length; // buffer size in bytes
|
|
|
|
#define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
|
// input_buffer is a URB, and input_buffer_length is equal to or greater than
|
|
// sizeof( URB ); the output_buffer is null and no output_buffer_length,
|
|
// only the following fields in urb can be accessed, others must be zeroed.
|
|
// DEV_HANDLE endp_handle;
|
|
// UCHAR setup_packet[8]; //for control pipe
|
|
// there is no difference between IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
|
|
#define IOCTL_GET_DEV_HANDLE CTL_CODE( FILE_HCD_DEV_TYPE, 4099, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
|
// input_buffer is null ,and input_buffer_length is zero.
|
|
// output_buffer will hold the handle to this dev, output_buffer_length is 4
|
|
// or bigger
|
|
|
|
typedef ULONG DEV_HANDLE, ENDP_HANDLE, IF_HANDLE;
|
|
|
|
struct URB;
|
|
#pragma pack( push, usb_align, 1 )
|
|
|
|
//structures for DeviceIoControl
|
|
typedef struct _ENUM_DEV_ELEMENT
|
|
{
|
|
DEV_HANDLE dev_handle;
|
|
USHORT product_id;
|
|
USHORT vendor_id;
|
|
UCHAR dev_addr;
|
|
|
|
} ENUM_DEV_ELEMENT, *PENUM_DEV_ELEMENT;
|
|
|
|
typedef struct _ENUM_DEV_ARRAY
|
|
{
|
|
UCHAR dev_count;
|
|
ENUM_DEV_ELEMENT dev_arr[ 1 ];
|
|
|
|
} ENUM_DEV_ARRAY, *PENUM_DEV_ARRAY;
|
|
|
|
typedef struct _GET_DEV_DESC_REQ
|
|
{
|
|
DEV_HANDLE dev_handle;
|
|
UCHAR desc_type;
|
|
UCHAR desc_idx;
|
|
|
|
} GET_DEV_DESC_REQ, *PGET_DEV_DESC_REQ;
|
|
|
|
//usb definitions
|
|
typedef struct _USB_CTRL_SETUP_PACKET
|
|
{
|
|
UCHAR bmRequestType;
|
|
UCHAR bRequest;
|
|
USHORT wValue;
|
|
USHORT wIndex;
|
|
USHORT wLength;
|
|
|
|
}USB_CTRL_SETUP_PACKET, *PUSB_CTRL_SETUP_PACKET;
|
|
|
|
typedef struct _USB_STRING_DESCRIPTOR
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
USHORT wData[1];
|
|
|
|
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
|
|
|
|
typedef struct _USB_DESC_HEADER
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
|
|
} USB_DESC_HEADER, *PUSB_DESC_HEADER;
|
|
|
|
typedef struct _USB_ENDPOINT_DESC
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
UCHAR bEndpointAddress;
|
|
UCHAR bmAttributes;
|
|
USHORT wMaxPacketSize;
|
|
UCHAR bInterval;
|
|
|
|
} USB_ENDPOINT_DESC, *PUSB_ENDPOINT_DESC;
|
|
|
|
typedef struct _USB_INTERFACE_DESC
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
UCHAR bInterfaceNumber;
|
|
UCHAR bAlternateSetting;
|
|
UCHAR bNumEndpoints;
|
|
UCHAR bInterfaceClass;
|
|
UCHAR bInterfaceSubClass;
|
|
UCHAR bInterfaceProtocol;
|
|
UCHAR iInterface;
|
|
|
|
} USB_INTERFACE_DESC, *PUSB_INTERFACE_DESC;
|
|
|
|
typedef struct _USB_CONFIGURATION_DESC
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
USHORT wTotalLength;
|
|
UCHAR bNumInterfaces;
|
|
UCHAR bConfigurationValue;
|
|
UCHAR iConfiguration;
|
|
UCHAR bmAttributes;
|
|
UCHAR MaxPower;
|
|
|
|
} USB_CONFIGURATION_DESC, *PUSB_CONFIGURATION_DESC;
|
|
|
|
typedef struct _USB_DEVICE_DESC
|
|
{
|
|
UCHAR bLength;
|
|
UCHAR bDescriptorType;
|
|
USHORT bcdUSB;
|
|
UCHAR bDeviceClass;
|
|
UCHAR bDeviceSubClass;
|
|
UCHAR bDeviceProtocol;
|
|
UCHAR bMaxPacketSize0;
|
|
USHORT idVendor;
|
|
USHORT idProduct;
|
|
USHORT bcdDevice;
|
|
UCHAR iManufacturer;
|
|
UCHAR iProduct;
|
|
UCHAR iSerialNumber;
|
|
UCHAR bNumConfigurations;
|
|
|
|
} USB_DEVICE_DESC, *PUSB_DEVICE_DESC;
|
|
|
|
|
|
#define URB_FLAG_STATE_MASK 0x0f
|
|
#define URB_FLAG_STATE_PENDING 0x00
|
|
#define URB_FLAG_STATE_IN_PROCESS 0x01
|
|
#define URB_FLAG_STATE_FINISHED 0x02
|
|
|
|
// USB2.0 state
|
|
#define URB_FLAG_STATE_DOORBELL 0x03 // for async request removal
|
|
#define URB_FLAG_STATE_WAIT_FRAME 0x04 // for sync request removal( for cancel only )
|
|
#define URB_FLAG_STATE_ERROR 0x05
|
|
|
|
#define URB_FLAG_IN_SCHEDULE 0x10
|
|
#define URB_FLAG_FORCE_CANCEL 0x20
|
|
#define URB_FLAG_SHORT_PACKET 0x80000000
|
|
|
|
typedef struct _SPLIT_ISO_BUS_TIME
|
|
{
|
|
USHORT bus_time;
|
|
USHORT start_uframe;
|
|
|
|
} SPLIT_ISO_BUS_TIME, *PSPLIT_ISO_BUS_TIME;
|
|
|
|
typedef struct _ISO_PACKET_DESC
|
|
{
|
|
LONG offset;
|
|
LONG length; // expected length
|
|
LONG actual_length;
|
|
LONG status;
|
|
union
|
|
{
|
|
LONG bus_time; //opaque for client request of split iso, the bus_time is the start_uframe for each transaction
|
|
SPLIT_ISO_BUS_TIME params;
|
|
};
|
|
|
|
} ISO_PACKET_DESC, *PISO_PACKET_DESC;
|
|
|
|
#define CTRL_PARENT_URB_VALID 1
|
|
|
|
typedef void ( *PURBCOMPLETION )( struct _URB *purb, PVOID pcontext);
|
|
|
|
typedef struct _CTRL_REQ_STACK
|
|
{
|
|
PURBCOMPLETION urb_completion; // the last step of the urb_completion is to call the
|
|
// the prevoius stack's callback if has, and the last
|
|
// one is purb->completion
|
|
PVOID context;
|
|
ULONG params[ 3 ];
|
|
|
|
} CTRL_REQ_STACK, *PCTRL_REQ_STACK;
|
|
|
|
#pragma pack( pop, usb_align )
|
|
|
|
typedef struct _URB_HS_PIPE_CONTENT
|
|
{
|
|
ULONG trans_type : 2; // bit 0-1
|
|
ULONG mult_count : 2; // bit 2-3, used in high speed int and iso requests
|
|
ULONG reserved : 1; // bit 1
|
|
ULONG speed_high : 1; // bit 5
|
|
ULONG speed_low : 1; // bit 6
|
|
ULONG trans_dir : 1; // bit 7
|
|
ULONG dev_addr : 7; // bit 8-14
|
|
ULONG endp_addr : 4; // bit 15-18
|
|
ULONG data_toggle : 1; // bit 19
|
|
ULONG max_packet_size : 4; // bit 20-23 log( max_packet_size )
|
|
ULONG interval : 4; // bit 24-27 the same definition in USB2.0, for high or full/low speed
|
|
ULONG start_uframe : 3; // bit 28-30
|
|
ULONG reserved1 : 1; //
|
|
|
|
} URB_HS_PIPE_CONTENT, *PURB_HS_PIPE_CONTENT;
|
|
|
|
typedef struct _URB_HS_CONTEXT_CONTENT
|
|
{
|
|
ULONG hub_addr : 7; // high speed hub addr for split transfer
|
|
ULONG port_idx : 7;
|
|
ULONG reserved : 18;
|
|
|
|
} URB_HS_CONTEXT_CONTENT, *PURB_HS_CONTEXT_CONTENT;
|
|
|
|
typedef struct _URB
|
|
{
|
|
LIST_ENTRY urb_link;
|
|
ULONG flags;
|
|
DEV_HANDLE endp_handle;
|
|
LONG status;
|
|
//record info for isr use, similar to td.status
|
|
//int pipe has different content in the 8 msb
|
|
//the eight bits contain interrupt interval.
|
|
//and max packet length is encoded in 3 bits from 23-21
|
|
//that means 2^(x) bytes in the packet.
|
|
ULONG pipe; // bit0-1: endp type, bit 6: ls or fs. bit 7: dir
|
|
|
|
union
|
|
{
|
|
UCHAR setup_packet[8]; // for control
|
|
LONG params[ 2 ]; // params[ 0 ] is used in iso transfer as max_packet_size
|
|
};
|
|
|
|
PUCHAR data_buffer; //user data
|
|
LONG data_length; //user data length
|
|
|
|
struct _USB_DEV *pdev;
|
|
struct _USB_ENDPOINT *pendp; //pipe for current transfer
|
|
|
|
PURBCOMPLETION completion;
|
|
PVOID context; //parameter of completion
|
|
|
|
PVOID urb_ext; //for high speed hcd use
|
|
ULONG hs_context; //for high speed hcd use
|
|
|
|
PIRP pirp; //irp from client driver
|
|
LONG reference; //for caller private use
|
|
|
|
LONG td_count; //for any kinds of transfer
|
|
LONG rest_bytes; //for split bulk transfer involving more than 1024 tds
|
|
LONG bytes_to_transfer;
|
|
LONG bytes_transfered; //( bulk transfer )accumulate one split-transfer by xfered bytes of the executed transactions
|
|
PLIST_ENTRY last_finished_td; //last inactive td useful for large amount transfer
|
|
LIST_ENTRY trasac_list; //list of tds or qhs
|
|
|
|
union
|
|
{
|
|
LONG iso_start_frame; // for high speed endp, this is uframe index, and not used for full/low speed endp, instead,
|
|
// iso_packet_desc.param.start_uframe is used.
|
|
LONG int_start_frame; // frame( ms ) index for high/full/low speed endp
|
|
struct
|
|
{
|
|
UCHAR ctrl_req_flags;
|
|
UCHAR ctrl_stack_count;
|
|
UCHAR ctrl_cur_stack; // the receiver uses this by increment the stack pointer first. if the requester
|
|
UCHAR ctrl_reserved; // send it down with ctrl_stack_count zero, that means the stack is not initialized,
|
|
// and can be initialized by receiver to 1 and only 1.
|
|
// If the initializer found the stack size won't meet the number down the drivers, it must
|
|
// reallocate one urb with the required stack size. and store the previous urb in
|
|
// ctrl_parent_urb
|
|
} ctrl_req_context;
|
|
};
|
|
|
|
union
|
|
{
|
|
LONG iso_frame_count; // uframe for high speed and frame for full/low speed
|
|
struct _URB* ctrl_parent_urb;
|
|
};
|
|
|
|
union
|
|
{
|
|
ISO_PACKET_DESC iso_packet_desc[ 1 ]; //used to build up trasac_list for iso transfer and claim bandwidth
|
|
CTRL_REQ_STACK ctrl_req_stack[ 1 ];
|
|
};
|
|
|
|
} URB, *PURB;
|
|
|
|
|
|
NTSTATUS
|
|
usb_set_dev_ext(
|
|
ULONG dev_ref,
|
|
PVOID dev_ext,
|
|
LONG size
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_set_if_ext(
|
|
ULONG dev_ref,
|
|
ULONG if_ref,
|
|
PVOID if_ext,
|
|
LONG size
|
|
);
|
|
|
|
PVOID
|
|
usb_get_dev_ext(
|
|
ULONG dev_ref
|
|
);
|
|
|
|
PVOID
|
|
usb_get_if_ext(
|
|
ULONG dev_ref,
|
|
ULONG if_ref
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_claim_interface(
|
|
ULONG dev_ref,
|
|
ULONG if_ref,
|
|
struct _USB_DRIVER *usb_drvr
|
|
);
|
|
|
|
//return reference to the endp
|
|
ULONG
|
|
usb_get_endp(
|
|
ULONG dev_ref,
|
|
LONG endp_addr
|
|
);
|
|
|
|
//return reference to the interface
|
|
ULONG
|
|
usb_get_interface(
|
|
ULONG dev_ref,
|
|
LONG if_idx
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_set_configuration(
|
|
ULONG dev_ref,
|
|
LONG config_value
|
|
);
|
|
|
|
// each call will return full size of the config desc and
|
|
// its if, endp descs.
|
|
// return value is the bytes actually returned.
|
|
// if the return value is equal to wTotalLength, all the descs of the
|
|
// configuration returned.
|
|
NTSTATUS
|
|
usb_get_config_desc(
|
|
ULONG dev_ref,
|
|
LONG config_idx,
|
|
PCHAR buffer,
|
|
PLONG psize
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_submit_urb(
|
|
struct _USB_DEV_MANAGER* dev_mgr,
|
|
PURB purb
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_cancel_urb(
|
|
ULONG dev_ref,
|
|
ULONG endp_ref,
|
|
PURB purb
|
|
);
|
|
|
|
void usb_fill_int_urb(PURB urb,
|
|
struct _USB_DEV *dev,
|
|
ULONG pipe,
|
|
PVOID transfer_buffer,
|
|
LONG buffer_length,
|
|
PURBCOMPLETION complete,
|
|
PVOID context,
|
|
int interval);
|
|
|
|
LONG
|
|
usb_calc_bus_time(
|
|
LONG low_speed,
|
|
LONG input_dir,
|
|
LONG isoc,
|
|
LONG bytecount
|
|
);
|
|
|
|
//increment the dev->ref_count to lock the dev
|
|
NTSTATUS
|
|
usb_query_and_lock_dev(
|
|
struct _USB_DEV_MANAGER* dev_mgr,
|
|
DEV_HANDLE dev_handle,
|
|
struct _USB_DEV** ppdev
|
|
);
|
|
|
|
//decrement the dev->ref_count
|
|
NTSTATUS
|
|
usb_unlock_dev(
|
|
struct _USB_DEV *dev
|
|
);
|
|
|
|
NTSTATUS
|
|
usb_reset_pipe(
|
|
struct _USB_DEV *pdev,
|
|
struct _USB_ENDPOINT *pendp,
|
|
PURBCOMPLETION client_completion,
|
|
PVOID param //parameter for client_completion
|
|
);
|
|
|
|
VOID
|
|
usb_reset_pipe_completion(
|
|
PURB purb,
|
|
PVOID pcontext
|
|
);
|
|
|
|
PVOID
|
|
usb_alloc_mem(
|
|
POOL_TYPE pool_type,
|
|
LONG size
|
|
);
|
|
|
|
VOID
|
|
usb_free_mem(
|
|
PVOID pbuf
|
|
);
|
|
|
|
PUSB_CONFIGURATION_DESC
|
|
usb_find_config_desc_by_val(
|
|
PUCHAR pbuf,
|
|
LONG val,
|
|
LONG cfg_count
|
|
);
|
|
|
|
PUSB_CONFIGURATION_DESC
|
|
usb_find_config_desc_by_idx(
|
|
PUCHAR pbuf,
|
|
LONG idx,
|
|
LONG cfg_count
|
|
);
|
|
|
|
BOOLEAN
|
|
usb_skip_if_and_altif(
|
|
PUCHAR* pdesc_BUF
|
|
);
|
|
|
|
BOOLEAN
|
|
usb_skip_one_config(
|
|
PUCHAR* pconfig_desc_BUF
|
|
);
|
|
|
|
VOID
|
|
usb_wait_ms_dpc(
|
|
ULONG ms
|
|
);
|
|
|
|
VOID
|
|
usb_wait_us_dpc(
|
|
ULONG us
|
|
);
|
|
|
|
BOOLEAN
|
|
usb_query_clicks(
|
|
PLARGE_INTEGER clicks
|
|
);
|
|
|
|
VOID
|
|
usb_cal_cpu_freq();
|
|
|
|
NTSTATUS
|
|
usb_reset_pipe_ex(
|
|
struct _USB_DEV_MANAGER *dev_mgr,
|
|
DEV_HANDLE endp_handle,
|
|
PURBCOMPLETION reset_completion,
|
|
PVOID param
|
|
);
|
|
|
|
VOID
|
|
usb_call_ctrl_completion(
|
|
PURB purb
|
|
);
|
|
|
|
BOOLEAN
|
|
is_header_match(
|
|
PUCHAR pbuf,
|
|
ULONG type
|
|
); //used to check descriptor validity
|
|
#endif
|