[FORMATTING]

svn path=/trunk/; revision=23616
This commit is contained in:
Aleksey Bragin 2006-08-20 14:01:17 +00:00
parent 4e7aa7365f
commit f448f3bae0
12 changed files with 18078 additions and 20290 deletions

File diff suppressed because it is too large Load diff

View file

@ -23,187 +23,143 @@
#include "debug.h"
#include "umss.h"
VOID
umss_cbi_send_adsc_complete(
PURB purb,
PVOID context
);
VOID umss_cbi_send_adsc_complete(PURB purb, PVOID context);
VOID
umss_cbi_transfer_data(
PUMSS_DEVICE_EXTENSION pdev_ext
);
VOID umss_cbi_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext);
VOID
umss_cbi_get_status(
PUMSS_DEVICE_EXTENSION pdev_ext
);
VOID umss_cbi_get_status(PUMSS_DEVICE_EXTENSION pdev_ext);
VOID
umss_cbi_transfer_data_complete(
PURB purb,
PVOID context
);
VOID umss_cbi_transfer_data_complete(PURB purb, PVOID context);
VOID
umss_cbi_get_status_complete(
PURB purb,
PVOID context
);
VOID umss_cbi_get_status_complete(PURB purb, PVOID context);
NTSTATUS
umss_class_specific_request(
IN PUMSS_DEVICE_EXTENSION pdev_ext,
IN UCHAR request,
IN UCHAR dir,
IN PVOID buffer,
IN ULONG buffer_length,
IN PURBCOMPLETION completion
)
umss_class_specific_request(IN PUMSS_DEVICE_EXTENSION pdev_ext,
IN UCHAR request,
IN UCHAR dir,
IN PVOID buffer,
IN ULONG buffer_length,
IN PURBCOMPLETION completion)
{
PURB purb;
NTSTATUS status;
NTSTATUS status;
purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
// Build URB for the ADSC command
UsbBuildVendorRequest(
purb,
pdev_ext->dev_handle | 0xffff,
buffer,
buffer_length,
0x21,
request,
0,
pdev_ext->pif_desc->bInterfaceNumber,
completion,
pdev_ext,
0 );
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
// Build URB for the ADSC command
UsbBuildVendorRequest(purb,
pdev_ext->dev_handle | 0xffff,
buffer,
buffer_length,
0x21, request, 0, pdev_ext->pif_desc->bInterfaceNumber, completion, pdev_ext, 0);
status = usb_submit_urb( pdev_ext->dev_mgr, purb );
if( status != STATUS_PENDING )
{
usb_free_mem( purb );
purb = NULL;
return status;
}
dev_mgr_register_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb );
return status;
status = usb_submit_urb(pdev_ext->dev_mgr, purb);
if (status != STATUS_PENDING)
{
usb_free_mem(purb);
purb = NULL;
return status;
}
dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb);
return status;
}
NTSTATUS
umss_cbi_startio(
IN PUMSS_DEVICE_EXTENSION pdev_ext,
IN PIO_PACKET io_packet
)
umss_cbi_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext, IN PIO_PACKET io_packet)
{
NTSTATUS status;
NTSTATUS status;
status = STATUS_NOT_SUPPORTED;
return status;
status = STATUS_NOT_SUPPORTED;
return status;
RtlCopyMemory( &pdev_ext->io_packet, io_packet, sizeof( pdev_ext->io_packet ) );
RtlCopyMemory(&pdev_ext->io_packet, io_packet, sizeof(pdev_ext->io_packet));
// Send the ADSC request to the device
// Calls UMSS_CbiSendADSCComplete when transfer completes
status = umss_class_specific_request(
pdev_ext,
ACCEPT_DEVICE_SPECIFIC_COMMAND,
USB_DIR_OUT ,
io_packet->cdb,
io_packet->cdb_length,
umss_cbi_send_adsc_complete
);
status = umss_class_specific_request(pdev_ext,
ACCEPT_DEVICE_SPECIFIC_COMMAND,
USB_DIR_OUT,
io_packet->cdb, io_packet->cdb_length, umss_cbi_send_adsc_complete);
return status;
return status;
}
VOID
umss_cbi_send_adsc_complete(
PURB purb,
PVOID context
)
umss_cbi_send_adsc_complete(PURB purb, PVOID context)
{
NTSTATUS status;
PIO_STACK_LOCATION irpStack;
PUMSS_DEVICE_EXTENSION pdev_ext;
PIO_PACKET io_packet;
ULONG bytes_to_transfer;
PUCHAR buf;
ULONG bytes_to_transfer;
PUCHAR buf;
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
io_packet = &pdev_ext->io_packet;
status = purb->status;
status = purb->status;
dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
if (!usb_success( status ) )
if (!usb_success(status))
{
usb_dbg_print( DBGLVL_MINIMUM,("umss_cbi_send_adsc_complete(): Command Block Failure!!!\n"));
usb_dbg_print(DBGLVL_MINIMUM, ("umss_cbi_send_adsc_complete(): Command Block Failure!!!\n"));
// BUGBUG - Should reset device here?
// Device failed Command Block, complete with error
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
}
else if ( io_packet->data_length )
else if (io_packet->data_length)
{
usb_dbg_print( DBGLVL_HIGH,("umss_cbi_send_adsc_complete(): Queuing Data Transfer DPC\n"));
umss_cbi_transfer_data( pdev_ext );
usb_dbg_print(DBGLVL_HIGH, ("umss_cbi_send_adsc_complete(): Queuing Data Transfer DPC\n"));
umss_cbi_transfer_data(pdev_ext);
}
else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
{
// Device supports interrupt pipe, so get status
umss_cbi_get_status( pdev_ext );
umss_cbi_get_status(pdev_ext);
}
else
{
// Device does not report status, so complete request
umss_complete_request( pdev_ext, STATUS_SUCCESS );
umss_complete_request(pdev_ext, STATUS_SUCCESS);
}
usb_free_mem( purb );
purb = NULL;
usb_free_mem(purb);
purb = NULL;
}
VOID
umss_cbi_reset_pipe(
IN PVOID reference
)
umss_cbi_reset_pipe(IN PVOID reference)
{
PUMSS_DEVICE_EXTENSION pdev_ext;
pdev_ext = (PUMSS_DEVICE_EXTENSION) reference;
// Reset the appropriate pipe, based on data direction
umss_reset_pipe(
pdev_ext,
( pdev_ext->io_packet.flags & USB_DIR_IN ) ?
usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->in_endp_idx ):
usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->out_endp_idx )
);
umss_reset_pipe(pdev_ext,
(pdev_ext->io_packet.flags & USB_DIR_IN) ?
usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx) :
usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx));
// Device stalled endpoint, so complete I/O operation with error.
// BUGBUG is this correct? Check spec...
umss_complete_request( pdev_ext, USB_STATUS_STALL_PID );
umss_complete_request(pdev_ext, USB_STATUS_STALL_PID);
}
VOID
umss_cbi_transfer_data(
PUMSS_DEVICE_EXTENSION pdev_ext
)
VOID
umss_cbi_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext)
{
PVOID buffer;
ULONG buffer_length;
// Get next data buffer element, if any.
buffer = umss_get_buffer( pdev_ext, &buffer_length );
buffer = umss_get_buffer(pdev_ext, &buffer_length);
if (NULL == buffer)
{
//Done with data phase, so move to status phase if (supported)
@ -222,101 +178,87 @@ PUMSS_DEVICE_EXTENSION pdev_ext
else
{
// Transfer next element of the data phase
umss_bulk_transfer(
pdev_ext,
(UCHAR)((pdev_ext->io_packet.flags & USB_DIR_IN ) ? USB_DIR_IN : USB_DIR_OUT ),
buffer,
buffer_length,
umss_cbi_transfer_data_complete
);
umss_bulk_transfer(pdev_ext,
(UCHAR) ((pdev_ext->io_packet.flags & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT),
buffer, buffer_length, umss_cbi_transfer_data_complete);
}
}
VOID
umss_cbi_transfer_data_complete(
PURB purb,
PVOID context
)
umss_cbi_transfer_data_complete(PURB purb, PVOID context)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
status = purb->status;
usb_free_mem( purb );
purb = NULL;
if ( !usb_success( status ) )
usb_free_mem(purb);
purb = NULL;
if (!usb_success(status))
{
// Device failed Data Transfer
// Check if we need to clear stalled pipe
if ( usb_halted( status ) )
if (usb_halted(status))
{
// Reset pipe can only be done at passive level, so we need
// to schedule a work item to do it.
if ( !umss_schedule_workitem( ( PVOID )pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
if (!umss_schedule_workitem
((PVOID) pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle))
{
usb_dbg_print( DBGLVL_MINIMUM,("umss_cbi_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
usb_dbg_print(DBGLVL_MINIMUM,
("umss_cbi_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
TRAP();
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
}
}
else
{
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
}
return;
}
// Transfer succeeded
// umss_cbi_transfer_data( pdev_ext );
umss_complete_request( pdev_ext, STATUS_SUCCESS );
return;
}
VOID
umss_cbi_get_status(
PUMSS_DEVICE_EXTENSION pdev_ext
)
{
PURB purb;
NTSTATUS status;
purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
if( purb == NULL )
return;
// Build a URB for our interrupt transfer
UsbBuildInterruptOrBulkTransferRequest(
purb,
usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->int_endp_idx ),
( PUCHAR )&pdev_ext->idb,
sizeof( INTERRUPT_DATA_BLOCK ),
umss_cbi_get_status_complete,
pdev_ext,
0
);
// Call USB driver stack
status = usb_submit_urb( pdev_ext->dev_mgr, purb );
if( status != STATUS_PENDING )
{
usb_free_mem( purb );
purb = NULL;
return;
}
dev_mgr_register_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb );
return;
umss_complete_request(pdev_ext, STATUS_SUCCESS);
return;
}
VOID
umss_cbi_get_status_complete(
PURB purb,
PVOID context
)
umss_cbi_get_status(PUMSS_DEVICE_EXTENSION pdev_ext)
{
PURB purb;
NTSTATUS status;
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb == NULL)
return;
// Build a URB for our interrupt transfer
UsbBuildInterruptOrBulkTransferRequest(purb,
usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx,
pdev_ext->int_endp_idx), (PUCHAR) & pdev_ext->idb,
sizeof(INTERRUPT_DATA_BLOCK), umss_cbi_get_status_complete,
pdev_ext, 0);
// Call USB driver stack
status = usb_submit_urb(pdev_ext->dev_mgr, purb);
if (status != STATUS_PENDING)
{
usb_free_mem(purb);
purb = NULL;
return;
}
dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb);
return;
}
VOID
umss_cbi_get_status_complete(PURB purb, PVOID context)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
@ -325,39 +267,41 @@ PVOID context
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
status = purb->status;
dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
usb_free_mem( purb );
purb = NULL;
usb_free_mem(purb);
purb = NULL;
if ( !usb_success( status ) )
if (!usb_success(status))
{
// Device failed Data Transfer
// Check if we need to clear stalled pipe
if ( usb_halted( status ) )
if (usb_halted(status))
{
if ( !umss_schedule_workitem( (PVOID)pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
if (!umss_schedule_workitem
((PVOID) pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle))
{
usb_dbg_print( DBGLVL_MINIMUM,("umss_cbi_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
usb_dbg_print(DBGLVL_MINIMUM,
("umss_cbi_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
TRAP();
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
return;
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
return;
}
}
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
return;
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
return;
}
// Interrupt transfer succeeded
idb = &(pdev_ext->idb);
// Check for an error in the status block
if ( ( 0 != idb->bType ) || ( 0 != ( idb->bValue & 0x3 ) ) )
if ((0 != idb->bType) || (0 != (idb->bValue & 0x3)))
{
umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
}
else
{
umss_complete_request( pdev_ext, STATUS_SUCCESS );
umss_complete_request(pdev_ext, STATUS_SUCCESS);
}
}

View file

@ -28,530 +28,481 @@
#include "hub.h"
#include "debug.h"
VOID
compdev_set_cfg_completion(
PURB purb,
PVOID context
);
VOID compdev_set_cfg_completion(PURB purb, PVOID context);
VOID
compdev_select_driver(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
);
VOID compdev_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
BOOL compdev_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle);
BOOL compdev_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
BOOL compdev_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
BOOL
compdev_connect(
PCONNECT_DATA param,
DEV_HANDLE dev_handle
);
BOOL
compdev_stop(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
);
BOOL
compdev_disconnect(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
);
BOOL
compdev_driver_init(
PUSB_DEV_MANAGER dev_mgr,
PUSB_DRIVER pdriver
)
compdev_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
if( dev_mgr == NULL || pdriver == NULL )
return FALSE;
if (dev_mgr == NULL || pdriver == NULL)
return FALSE;
pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID
pdriver->driver_desc.product_id = 0xffff; // USB Product ID.
pdriver->driver_desc.release_num = 0x100; // Release Number of Device
pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID
pdriver->driver_desc.product_id = 0xffff; // USB Product ID.
pdriver->driver_desc.release_num = 0x100; // Release Number of Device
pdriver->driver_desc.config_val = 0; // Configuration Value
pdriver->driver_desc.if_num = 0; // Interface Number
pdriver->driver_desc.if_class = 0; // Interface Class
pdriver->driver_desc.if_sub_class = 0; // Interface SubClass
pdriver->driver_desc.if_protocol = 0; // Interface Protocol
pdriver->driver_desc.config_val = 0; // Configuration Value
pdriver->driver_desc.if_num = 0; // Interface Number
pdriver->driver_desc.if_class = 0; // Interface Class
pdriver->driver_desc.if_sub_class = 0; // Interface SubClass
pdriver->driver_desc.if_protocol = 0; // Interface Protocol
pdriver->driver_desc.driver_name = "USB composit dev driver"; // Driver name for Name Registry
pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE;
pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
pdriver->driver_desc.driver_name = "USB composit dev driver"; // Driver name for Name Registry
pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE;
pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
//we have no extra data sturcture currently
pdriver->driver_ext = NULL;
pdriver->driver_ext_size = 0;
//we have no extra data sturcture currently
pdriver->driver_ext = NULL;
pdriver->driver_ext_size = 0;
pdriver->disp_tbl.version = 1;
pdriver->disp_tbl.dev_connect = compdev_connect;
pdriver->disp_tbl.dev_disconnect = compdev_disconnect;
pdriver->disp_tbl.dev_stop = compdev_stop;
pdriver->disp_tbl.dev_reserved = NULL;
pdriver->disp_tbl.version = 1;
pdriver->disp_tbl.dev_connect = compdev_connect;
pdriver->disp_tbl.dev_disconnect = compdev_disconnect;
pdriver->disp_tbl.dev_stop = compdev_stop;
pdriver->disp_tbl.dev_reserved = NULL;
return TRUE;
return TRUE;
}
BOOL
compdev_driver_destroy(
PUSB_DEV_MANAGER dev_mgr,
PUSB_DRIVER pdriver
)
compdev_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
return TRUE;
return TRUE;
}
BOOL
compdev_connect(
PCONNECT_DATA param,
DEV_HANDLE dev_handle
)
compdev_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle)
{
PURB purb;
PUSB_CTRL_SETUP_PACKET psetup;
NTSTATUS status;
PUCHAR buf;
LONG credit, i, j, match;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_INTERFACE_DESC pif_desc;
PUSB_DEV_MANAGER dev_mgr;
PURB purb;
PUSB_CTRL_SETUP_PACKET psetup;
NTSTATUS status;
PUCHAR buf;
LONG credit, i, j, match;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_INTERFACE_DESC pif_desc;
PUSB_DEV_MANAGER dev_mgr;
if( param == NULL || dev_handle == 0 )
return FALSE;
if (param == NULL || dev_handle == 0)
return FALSE;
dev_mgr = param->dev_mgr;
dev_mgr = param->dev_mgr;
// let's set the configuration
purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
if( purb == NULL )
return FALSE;
// let's set the configuration
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb == NULL)
return FALSE;
buf = usb_alloc_mem( NonPagedPool, 512 );
if( buf == NULL )
{
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_connect(): can not alloc buf\n" ) );
usb_free_mem( purb );
return FALSE;
}
buf = usb_alloc_mem(NonPagedPool, 512);
if (buf == NULL)
{
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): can not alloc buf\n"));
usb_free_mem(purb);
return FALSE;
}
// before we set the configuration, let's search to find if there
// exist interfaces we supported
psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
urb_init( ( purb ) );
purb->endp_handle = dev_handle | 0xffff;
purb->data_buffer = buf;
purb->data_length = 512;
purb->completion = NULL; // this is an immediate request, no completion required
purb->context = NULL;
purb->reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
// before we set the configuration, let's search to find if there
// exist interfaces we supported
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
urb_init((purb));
purb->endp_handle = dev_handle | 0xffff;
purb->data_buffer = buf;
purb->data_length = 512;
purb->completion = NULL; // this is an immediate request, no completion required
purb->context = NULL;
purb->reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
status = usb_submit_urb( dev_mgr, purb );
if( status == STATUS_PENDING )
{
TRAP();
usb_free_mem( buf );
usb_free_mem( purb );
return FALSE;
}
status = usb_submit_urb(dev_mgr, purb);
if (status == STATUS_PENDING)
{
TRAP();
usb_free_mem(buf);
usb_free_mem(purb);
return FALSE;
}
// let's scan the interfacs for those we recognize
pconfig_desc = ( PUSB_CONFIGURATION_DESC )buf;
if( pconfig_desc->wTotalLength > 512 )
{
usb_free_mem( buf );
usb_free_mem( purb );
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_connect(): error, bad configuration desc\n" ) );
return FALSE;
}
// let's scan the interfacs for those we recognize
pconfig_desc = (PUSB_CONFIGURATION_DESC) buf;
if (pconfig_desc->wTotalLength > 512)
{
usb_free_mem(buf);
usb_free_mem(purb);
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): error, bad configuration desc\n"));
return FALSE;
}
pif_desc = ( PUSB_INTERFACE_DESC )&pconfig_desc[ 1 ];
for( i = 0, credit = 0; i < ( LONG )pconfig_desc->bNumInterfaces; i++ )
{
for( j = 0; j < DEVMGR_MAX_DRIVERS; j++ )
{
credit = dev_mgr_score_driver_for_if( dev_mgr, &dev_mgr->driver_list[ j ], pif_desc );
if( credit )
break;
}
if( credit )
break;
pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1];
for(i = 0, credit = 0; i < (LONG) pconfig_desc->bNumInterfaces; i++)
{
for(j = 0; j < DEVMGR_MAX_DRIVERS; j++)
{
credit = dev_mgr_score_driver_for_if(dev_mgr, &dev_mgr->driver_list[j], pif_desc);
if (credit)
break;
}
if (credit)
break;
if( usb_skip_if_and_altif( ( PUCHAR* )&pif_desc ) )
break;
}
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc))
break;
}
i = pconfig_desc->bConfigurationValue;
usb_free_mem( buf );
buf = NULL;
if( credit == 0 )
{
usb_free_mem( purb );
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_connect(): oops..., no supported interface found\n" ) );
return FALSE;
}
i = pconfig_desc->bConfigurationValue;
usb_free_mem(buf);
buf = NULL;
if (credit == 0)
{
usb_free_mem(purb);
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): oops..., no supported interface found\n"));
return FALSE;
}
//set the configuration
urb_init( purb );
purb->endp_handle = dev_handle | 0xffff;
purb->data_buffer = NULL;
purb->data_length = 0;
purb->completion = compdev_set_cfg_completion;
purb->context = dev_mgr;
purb->reference = ( ULONG )param->pdriver;
psetup->bmRequestType = 0;
psetup->bRequest = USB_REQ_SET_CONFIGURATION;
psetup->wValue = ( USHORT ) i;
psetup->wIndex = 0;
psetup->wLength = 0;
//set the configuration
urb_init(purb);
purb->endp_handle = dev_handle | 0xffff;
purb->data_buffer = NULL;
purb->data_length = 0;
purb->completion = compdev_set_cfg_completion;
purb->context = dev_mgr;
purb->reference = (ULONG) param->pdriver;
psetup->bmRequestType = 0;
psetup->bRequest = USB_REQ_SET_CONFIGURATION;
psetup->wValue = (USHORT) i;
psetup->wIndex = 0;
psetup->wLength = 0;
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_connect(): start config the device, cfgval=%d\n", i ) );
status = usb_submit_urb( dev_mgr, purb );
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): start config the device, cfgval=%d\n", i));
status = usb_submit_urb(dev_mgr, purb);
if( status != STATUS_PENDING )
{
usb_free_mem( purb );
if (status != STATUS_PENDING)
{
usb_free_mem(purb);
if( status == STATUS_SUCCESS )
return TRUE;
if (status == STATUS_SUCCESS)
return TRUE;
return FALSE;
}
return FALSE;
}
return TRUE;
return TRUE;
}
VOID
compdev_event_select_if_driver(
PUSB_DEV pdev,
ULONG event,
ULONG context,
ULONG param
)
compdev_event_select_if_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param)
{
PUSB_DEV_MANAGER dev_mgr;
DEV_HANDLE dev_handle;
PUMSS_CREATE_DATA cd;
PUSB_DEV_MANAGER dev_mgr;
DEV_HANDLE dev_handle;
PUMSS_CREATE_DATA cd;
if( pdev == NULL )
return;
if (pdev == NULL)
return;
//
// RtlZeroMemory( &cd, sizeof( cd ) );
//
dev_mgr = dev_mgr_from_dev( pdev );
dev_handle = usb_make_handle( pdev->dev_id, 0, 0 );
compdev_select_driver( dev_mgr, dev_handle );
return;
//
// RtlZeroMemory( &cd, sizeof( cd ) );
//
dev_mgr = dev_mgr_from_dev(pdev);
dev_handle = usb_make_handle(pdev->dev_id, 0, 0);
compdev_select_driver(dev_mgr, dev_handle);
return;
}
BOOL
compdev_post_event_select_driver(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
)
compdev_post_event_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
PUSB_EVENT pevent;
BOOL bret;
PUSB_DEV pdev;
PUSB_EVENT pevent;
BOOL bret;
PUSB_DEV pdev;
USE_IRQL;
USE_IRQL;
if( dev_mgr == NULL || dev_handle == 0 )
return FALSE;
if (dev_mgr == NULL || dev_handle == 0)
return FALSE;
if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) != STATUS_SUCCESS )
return FALSE;
if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
return FALSE;
KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
lock_dev( pdev, TRUE );
KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
lock_dev(pdev, TRUE);
if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
{
bret = FALSE;
goto LBL_OUT;
}
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
bret = FALSE;
goto LBL_OUT;
}
pevent = alloc_event( &dev_mgr->event_pool, 1 );
if( pevent == NULL )
{
bret = FALSE;
goto LBL_OUT;
}
pevent->flags = USB_EVENT_FLAG_ACTIVE;
pevent->event = USB_EVENT_DEFAULT;
pevent->pdev = pdev;
pevent->context = 0;
pevent->param = 0;
pevent->pnext = 0; //vertical queue for serialized operation
pevent->process_event = compdev_event_select_if_driver;
pevent->process_queue = event_list_default_process_queue;
pevent = alloc_event(&dev_mgr->event_pool, 1);
if (pevent == NULL)
{
bret = FALSE;
goto LBL_OUT;
}
pevent->flags = USB_EVENT_FLAG_ACTIVE;
pevent->event = USB_EVENT_DEFAULT;
pevent->pdev = pdev;
pevent->context = 0;
pevent->param = 0;
pevent->pnext = 0; //vertical queue for serialized operation
pevent->process_event = compdev_event_select_if_driver;
pevent->process_queue = event_list_default_process_queue;
InsertTailList( &dev_mgr->event_list, &pevent->event_link );
KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE ); // wake up the dev_mgr_thread
bret = TRUE;
InsertTailList(&dev_mgr->event_list, &pevent->event_link);
KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); // wake up the dev_mgr_thread
bret = TRUE;
LBL_OUT:
LBL_OUT:
unlock_dev( pdev, TRUE );
KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
usb_unlock_dev( pdev );
return bret;
unlock_dev(pdev, TRUE);
KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
usb_unlock_dev(pdev);
return bret;
}
VOID
compdev_set_cfg_completion(
PURB purb,
PVOID context
)
compdev_set_cfg_completion(PURB purb, PVOID context)
{
DEV_HANDLE dev_handle;
PUSB_DEV_MANAGER dev_mgr;
PWORK_QUEUE_ITEM pwork_item;
PUSB_DRIVER pdriver;
NTSTATUS status;
PUSB_DEV pdev;
DEV_HANDLE dev_handle;
PUSB_DEV_MANAGER dev_mgr;
PWORK_QUEUE_ITEM pwork_item;
PUSB_DRIVER pdriver;
NTSTATUS status;
PUSB_DEV pdev;
USE_IRQL;
USE_IRQL;
if( purb == NULL || context == NULL )
return;
if (purb == NULL || context == NULL)
return;
dev_handle = purb->endp_handle & ~0xffff;
dev_mgr = ( PUSB_DEV_MANAGER ) context;
pdriver = ( PUSB_DRIVER )purb->reference;
dev_handle = purb->endp_handle & ~0xffff;
dev_mgr = (PUSB_DEV_MANAGER) context;
pdriver = (PUSB_DRIVER) purb->reference;
if( purb->status != STATUS_SUCCESS )
{
usb_free_mem( purb );
return;
}
if (purb->status != STATUS_SUCCESS)
{
usb_free_mem(purb);
return;
}
usb_free_mem( purb );
purb = NULL;
usb_free_mem(purb);
purb = NULL;
// set the dev state
status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
if( status != STATUS_SUCCESS )
{
usb_unlock_dev( pdev );
return;
}
// safe to release the pdev ref since we are in urb completion
usb_unlock_dev( pdev );
// set the dev state
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (status != STATUS_SUCCESS)
{
usb_unlock_dev(pdev);
return;
}
// safe to release the pdev ref since we are in urb completion
usb_unlock_dev(pdev);
lock_dev( pdev, TRUE );
if( dev_state( pdev ) >= USB_DEV_STATE_BEFORE_ZOMB )
{
unlock_dev( pdev, TRUE );
return;
}
lock_dev(pdev, TRUE);
if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB)
{
unlock_dev(pdev, TRUE);
return;
}
if( dev_mgr_set_driver( dev_mgr, dev_handle, pdriver, pdev ) == FALSE )
return;
if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
return;
//transit the state to configured
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
unlock_dev( pdev, TRUE );
//transit the state to configured
pdev->flags &= ~USB_DEV_STATE_MASK;
pdev->flags |= USB_DEV_STATE_CONFIGURED;
unlock_dev(pdev, TRUE);
//
// we change to use our thread for driver choosing. it will reduce
// the race condition when different pnp event comes simultaneously
//
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_set_cfg_completion(): start select driver for the dev\n" ) );
compdev_post_event_select_driver( dev_mgr, dev_handle );
//
// we change to use our thread for driver choosing. it will reduce
// the race condition when different pnp event comes simultaneously
//
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_set_cfg_completion(): start select driver for the dev\n"));
compdev_post_event_select_driver(dev_mgr, dev_handle);
return;
return;
}
VOID
compdev_select_driver(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
)
compdev_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
URB urb;
LONG i, j, k, credit;
ULONG dev_id;
PUCHAR buf;
NTSTATUS status;
PUSB_DRIVER pcand, ptemp_drv;
URB urb;
LONG i, j, k, credit;
ULONG dev_id;
PUCHAR buf;
NTSTATUS status;
PUSB_DRIVER pcand, ptemp_drv;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_INTERFACE_DESC pif_desc;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_DEV pdev;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_INTERFACE_DESC pif_desc;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_DEV pdev;
USE_IRQL;
USE_IRQL;
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_select_driver(): entering...\n" ) );
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): entering...\n"));
dev_id = dev_handle >> 16;
dev_id = dev_handle >> 16;
buf = usb_alloc_mem( NonPagedPool, 512 );
buf = usb_alloc_mem(NonPagedPool, 512);
if( buf == NULL )
return;
if (buf == NULL)
return;
// now let's get the descs, one configuration
urb_init( &urb );
psetup = ( PUSB_CTRL_SETUP_PACKET )urb.setup_packet;
urb.endp_handle = dev_handle | 0xffff;
urb.data_buffer = buf;
urb.data_length = 512;
urb.completion = NULL; // this is an immediate request, no completion required
urb.context = NULL;
urb.reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
// now let's get the descs, one configuration
urb_init(&urb);
psetup = (PUSB_CTRL_SETUP_PACKET) urb.setup_packet;
urb.endp_handle = dev_handle | 0xffff;
urb.data_buffer = buf;
urb.data_length = 512;
urb.completion = NULL; // this is an immediate request, no completion required
urb.context = NULL;
urb.reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
status = usb_submit_urb( dev_mgr, &urb );
if( status == STATUS_PENDING )
{
TRAP();
}
status = usb_submit_urb(dev_mgr, &urb);
if (status == STATUS_PENDING)
{
TRAP();
}
// let's scan the interfacs for those we recognize
pconfig_desc = ( PUSB_CONFIGURATION_DESC )buf;
if( pconfig_desc->wTotalLength > 512 )
{
usb_free_mem( buf );
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_select_driver(): error, bad configuration desc\n" ) );
return;
}
pif_desc = ( PUSB_INTERFACE_DESC )&pconfig_desc[ 1 ];
// let's scan the interfacs for those we recognize
pconfig_desc = (PUSB_CONFIGURATION_DESC) buf;
if (pconfig_desc->wTotalLength > 512)
{
usb_free_mem(buf);
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): error, bad configuration desc\n"));
return;
}
pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1];
if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) != STATUS_SUCCESS )
{
usb_free_mem( buf );
usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_select_driver(): error, dev does not exist\n" ) );
return;
}
if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
{
usb_free_mem(buf);
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): error, dev does not exist\n"));
return;
}
for( i = 0; i < ( LONG )pconfig_desc->bNumInterfaces; i++ )
{
for( j = 0, credit = 0, pcand = NULL; j < DEVMGR_MAX_DRIVERS; j++ )
{
ptemp_drv = &dev_mgr->driver_list[ j ];
k = dev_mgr_score_driver_for_if( dev_mgr, ptemp_drv, pif_desc );
if( k > credit )
credit = k, pcand = ptemp_drv;
}
for(i = 0; i < (LONG) pconfig_desc->bNumInterfaces; i++)
{
for(j = 0, credit = 0, pcand = NULL; j < DEVMGR_MAX_DRIVERS; j++)
{
ptemp_drv = &dev_mgr->driver_list[j];
k = dev_mgr_score_driver_for_if(dev_mgr, ptemp_drv, pif_desc);
if (k > credit)
credit = k, pcand = ptemp_drv;
}
if( credit )
{
// ok, we find one
CONNECT_DATA param;
if (credit)
{
// ok, we find one
CONNECT_DATA param;
if( pcand->disp_tbl.dev_connect )
{
param.dev_mgr = dev_mgr;
param.pdriver = pcand;
param.dev_handle = 0;
pcand->disp_tbl.dev_connect( &param, usb_make_handle( dev_id, i, 0 ) );
}
}
if( usb_skip_if_and_altif( ( PUCHAR* )&pif_desc ) == FALSE )
{
break;
}
}
usb_unlock_dev( pdev );
if (pcand->disp_tbl.dev_connect)
{
param.dev_mgr = dev_mgr;
param.pdriver = pcand;
param.dev_handle = 0;
pcand->disp_tbl.dev_connect(&param, usb_make_handle(dev_id, i, 0));
}
}
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
{
break;
}
}
usb_unlock_dev(pdev);
if( buf )
{
usb_free_mem( buf );
buf = NULL;
}
return;
if (buf)
{
usb_free_mem(buf);
buf = NULL;
}
return;
}
BOOL
compdev_stop(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
)
compdev_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
PUSB_DEV pdev;
LONG i;
ULONG dev_id;
PUSB_DRIVER pdrv;
NTSTATUS status;
PUSB_DEV pdev;
LONG i;
ULONG dev_id;
PUSB_DRIVER pdrv;
NTSTATUS status;
if( dev_mgr == NULL || dev_handle == 0 )
return FALSE;
if (dev_mgr == NULL || dev_handle == 0)
return FALSE;
pdev = NULL;
dev_id = dev_handle >> 16;
status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
if( pdev )
{
if( pdev->usb_config )
{
for( i = 0; i < pdev->usb_config->if_count; i++ )
{
if( pdrv = pdev->usb_config->interf[ i ].pif_drv )
{
pdrv->disp_tbl.dev_stop( dev_mgr, usb_make_handle( dev_id, i, 0 ) );
}
}
}
}
if( status == STATUS_SUCCESS )
{
usb_unlock_dev( pdev );
}
return TRUE;
pdev = NULL;
dev_id = dev_handle >> 16;
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (pdev)
{
if (pdev->usb_config)
{
for(i = 0; i < pdev->usb_config->if_count; i++)
{
if (pdrv = pdev->usb_config->interf[i].pif_drv)
{
pdrv->disp_tbl.dev_stop(dev_mgr, usb_make_handle(dev_id, i, 0));
}
}
}
}
if (status == STATUS_SUCCESS)
{
usb_unlock_dev(pdev);
}
return TRUE;
}
BOOL
compdev_disconnect(
PUSB_DEV_MANAGER dev_mgr,
DEV_HANDLE dev_handle
)
compdev_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
PUSB_DEV pdev;
LONG i;
ULONG dev_id;
PUSB_DRIVER pdrv;
NTSTATUS status;
PUSB_DEV pdev;
LONG i;
ULONG dev_id;
PUSB_DRIVER pdrv;
NTSTATUS status;
if( dev_mgr == NULL || dev_handle == 0 )
return FALSE;
if (dev_mgr == NULL || dev_handle == 0)
return FALSE;
pdev = NULL;
dev_id = dev_handle >> 16;
status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
if( pdev )
{
if( pdev->usb_config )
{
for( i = 0; i < pdev->usb_config->if_count; i++ )
{
if( pdrv = pdev->usb_config->interf[ i ].pif_drv )
{
pdrv->disp_tbl.dev_disconnect( dev_mgr, usb_make_handle( dev_id, i, 0 ) );
}
}
}
}
if( status == STATUS_SUCCESS )
{
usb_unlock_dev( pdev );
}
return TRUE;
pdev = NULL;
dev_id = dev_handle >> 16;
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
if (pdev)
{
if (pdev->usb_config)
{
for(i = 0; i < pdev->usb_config->if_count; i++)
{
if (pdrv = pdev->usb_config->interf[i].pif_drv)
{
pdrv->disp_tbl.dev_disconnect(dev_mgr, usb_make_handle(dev_id, i, 0));
}
}
}
}
if (status == STATUS_SUCCESS)
{
usb_unlock_dev(pdev);
}
return TRUE;
}
// note:

View file

@ -26,494 +26,485 @@
#include "hub.h"
VOID
disp_urb_completion(
PURB purb,
PVOID context
)
disp_urb_completion(PURB purb, PVOID context)
{
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_DEV_MANAGER dev_mgr;
ULONG ctrl_code;
NTSTATUS status;
PDEVEXT_HEADER dev_hdr;
PUSB_CTRL_SETUP_PACKET psetup;
PUSB_DEV_MANAGER dev_mgr;
ULONG ctrl_code;
NTSTATUS status;
PDEVEXT_HEADER dev_hdr;
if( purb == NULL )
return;
if (purb == NULL)
return;
ctrl_code = ( ULONG )purb->reference;
dev_mgr = ( PUSB_DEV_MANAGER )purb->context;
// at this stage, the irp can not be canceled since the urb
// won't be found in any queue and the irp is not in any queue.
// see line 4685 in hub.c
// Sometimes, it may be very fast to enter this routine before
// the dev_mgr_register_irp to be called in dispatch routine in
// usb2.0 environment as
// we did in usb1.1 driver. We can not simply add a loop to wait
// for the dispatch thread to add the irp to the list, because
// here we are at DPC level higher than the dispatch thread
// running level. And the solution is to register the irp
// before the urb is scheduled instead of registering it after
// urb is scheduled.
if( purb->pirp )
{
PIO_STACK_LOCATION irp_stack;
dev_mgr_remove_irp( dev_mgr, purb->pirp );
ctrl_code = (ULONG) purb->reference;
dev_mgr = (PUSB_DEV_MANAGER) purb->context;
status = purb->status;
irp_stack = IoGetCurrentIrpStackLocation( purb->pirp );
// at this stage, the irp can not be canceled since the urb
// won't be found in any queue and the irp is not in any queue.
// see line 4685 in hub.c
// Sometimes, it may be very fast to enter this routine before
// the dev_mgr_register_irp to be called in dispatch routine in
// usb2.0 environment as
// we did in usb1.1 driver. We can not simply add a loop to wait
// for the dispatch thread to add the irp to the list, because
// here we are at DPC level higher than the dispatch thread
// running level. And the solution is to register the irp
// before the urb is scheduled instead of registering it after
// urb is scheduled.
if (purb->pirp)
{
PIO_STACK_LOCATION irp_stack;
dev_mgr_remove_irp(dev_mgr, purb->pirp);
if( purb->status != STATUS_SUCCESS )
{
purb->pirp->IoStatus.Information = 0;
}
else
{
// currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
// are allowed. And we do not need to set information
// for IRP_MJ_INTERNAL_DEVICE_CONTROL
if( irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
purb->pirp->IoStatus.Information = purb->data_length;
}
purb->pirp->IoStatus.Status = status;
if( irp_stack )
{
dev_hdr = irp_stack->DeviceObject->DeviceExtension;
if( dev_hdr->start_io )
{
IoStartNextPacket( irp_stack->DeviceObject, TRUE );
}
}
IoCompleteRequest( purb->pirp, IO_NO_INCREMENT );
}
return;
status = purb->status;
irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);
if (purb->status != STATUS_SUCCESS)
{
purb->pirp->IoStatus.Information = 0;
}
else
{
// currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
// are allowed. And we do not need to set information
// for IRP_MJ_INTERNAL_DEVICE_CONTROL
if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
purb->pirp->IoStatus.Information = purb->data_length;
}
purb->pirp->IoStatus.Status = status;
if (irp_stack)
{
dev_hdr = irp_stack->DeviceObject->DeviceExtension;
if (dev_hdr->start_io)
{
IoStartNextPacket(irp_stack->DeviceObject, TRUE);
}
}
IoCompleteRequest(purb->pirp, IO_NO_INCREMENT);
}
return;
}
VOID
disp_noio_urb_completion(
PURB purb,
PVOID context
)
disp_noio_urb_completion(PURB purb, PVOID context)
{
PUSB_CTRL_SETUP_PACKET psetup;
PURB purb2;
PUSB_DEV_MANAGER dev_mgr;
NTSTATUS status;
PIO_STACK_LOCATION irp_stack;
PDEVEXT_HEADER dev_hdr;
PUSB_CTRL_SETUP_PACKET psetup;
PURB purb2;
PUSB_DEV_MANAGER dev_mgr;
NTSTATUS status;
PIO_STACK_LOCATION irp_stack;
PDEVEXT_HEADER dev_hdr;
if( purb == NULL )
return;
if (purb == NULL)
return;
psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
if( psetup->bmRequestType == 0x2
&& psetup->bRequest == USB_REQ_CLEAR_FEATURE
&& psetup->wIndex == 0 ) //reset pipe
purb2 = ( PURB )context;
else
purb2 = purb;
psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
if( purb2->pirp == NULL )
return;
if ((psetup->bmRequestType == 0x2) &&
(psetup->bRequest == USB_REQ_CLEAR_FEATURE) &&
(psetup->wIndex == 0)) //reset pipe
{
purb2 = (PURB) context;
}
else
{
purb2 = purb;
}
dev_mgr = ( PUSB_DEV_MANAGER )purb2->context;
if (purb2->pirp == NULL)
return;
dev_mgr_remove_irp( dev_mgr, purb2->pirp );
dev_mgr = (PUSB_DEV_MANAGER) purb2->context;
if( purb->status != STATUS_SUCCESS )
status = STATUS_IO_DEVICE_ERROR;
purb2->pirp->IoStatus.Information = 0;
purb2->pirp->IoStatus.Status = status;
irp_stack = IoGetCurrentIrpStackLocation( purb->pirp );
if( irp_stack )
{
dev_hdr = irp_stack->DeviceObject->DeviceExtension;
if( dev_hdr->start_io )
{
IoStartNextPacket( irp_stack->DeviceObject, TRUE );
}
}
IoCompleteRequest( purb2->pirp, IO_NO_INCREMENT );
return;
dev_mgr_remove_irp(dev_mgr, purb2->pirp);
if (purb->status != STATUS_SUCCESS)
status = STATUS_IO_DEVICE_ERROR;
purb2->pirp->IoStatus.Information = 0;
purb2->pirp->IoStatus.Status = status;
irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);
if (irp_stack)
{
dev_hdr = irp_stack->DeviceObject->DeviceExtension;
if (dev_hdr->start_io)
{
IoStartNextPacket(irp_stack->DeviceObject, TRUE);
}
}
IoCompleteRequest(purb2->pirp, IO_NO_INCREMENT);
return;
}
NTSTATUS
dev_mgr_dispatch(
IN PUSB_DEV_MANAGER dev_mgr,
IN PIRP irp
)
//this function is called by the hcd's
//dispatch when they have done their job.
NTSTATUS
dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr, IN PIRP irp)
{
PIO_STACK_LOCATION irp_stack;
NTSTATUS status;
ULONG ctrl_code;
USE_IRQL;
PIO_STACK_LOCATION irp_stack;
NTSTATUS status;
ULONG ctrl_code;
USE_IRQL;
if( dev_mgr == NULL || irp == NULL )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
status = STATUS_SUCCESS;
irp_stack = IoGetCurrentIrpStackLocation (irp);
ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
if (dev_mgr == NULL || irp == NULL)
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
switch ( irp_stack->MajorFunction )
{
case IRP_MJ_CREATE:
{
InterlockedIncrement( &dev_mgr->open_count );
EXIT_DISPATCH( STATUS_SUCCESS, irp );
}
case IRP_MJ_CLOSE:
{
InterlockedDecrement( &dev_mgr->open_count );
EXIT_DISPATCH( STATUS_SUCCESS, irp );
}
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
case IRP_MJ_DEVICE_CONTROL:
{
switch( ctrl_code )
{
case IOCTL_GET_DEV_COUNT:
{
LONG dev_count;
status = STATUS_SUCCESS;
irp_stack = IoGetCurrentIrpStackLocation(irp);
ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
irp->IoStatus.Information = 0;
if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( LONG ) )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
switch (irp_stack->MajorFunction)
{
case IRP_MJ_CREATE:
{
InterlockedIncrement(&dev_mgr->open_count);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IRP_MJ_CLOSE:
{
InterlockedDecrement(&dev_mgr->open_count);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
case IRP_MJ_DEVICE_CONTROL:
{
switch (ctrl_code)
{
case IOCTL_GET_DEV_COUNT:
{
LONG dev_count;
KeAcquireSpinLock( &dev_mgr->dev_list_lock, &old_irql );
dev_count = usb_count_list( &dev_mgr->dev_list );
KeReleaseSpinLock( &dev_mgr->dev_list_lock, old_irql );
*( ( PLONG )irp->AssociatedIrp.SystemBuffer ) = dev_count;
irp->IoStatus.Information = sizeof( LONG );
EXIT_DISPATCH( STATUS_SUCCESS, irp );
}
case IOCTL_ENUM_DEVICES:
{
PLIST_ENTRY pthis, pnext;
LONG dev_count, array_size, i, j;
PUSB_DEV pdev;
PENUM_DEV_ARRAY peda;
irp->IoStatus.Information = 0;
if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
irp->IoStatus.Information = 0;
if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( LONG ) )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ENUM_DEV_ARRAY ) )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
array_size = *( ( PULONG )irp->AssociatedIrp.SystemBuffer );
KeAcquireSpinLock( &dev_mgr->dev_list_lock, &old_irql );
dev_count = usb_count_list( &dev_mgr->dev_list );
dev_count = dev_count > array_size ? array_size : dev_count;
peda = ( PENUM_DEV_ARRAY )irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory( peda, sizeof( ENUM_DEV_ARRAY ) + ( dev_count - 1 ) * sizeof( ENUM_DEV_ELEMENT ) );
if( dev_count )
{
ListFirst( &dev_mgr->dev_list, pthis );
for( i = 0, j = 0; i < dev_count; i++ )
{
pdev = struct_ptr( pthis, USB_DEV, dev_link );
ListNext( &dev_mgr->dev_list, pthis, pnext );
pthis = pnext;
lock_dev( pdev, FALSE );
if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
{
unlock_dev( pdev, FALSE );
continue;
}
if( dev_state( pdev ) < USB_DEV_STATE_ADDRESSED )
{
unlock_dev( pdev, FALSE );
continue;
}
peda->dev_arr[ i ].dev_handle = ( pdev->dev_id << 16 );
//may not get the desc yet
if( pdev->pusb_dev_desc )
{
peda->dev_arr[ i ].product_id = pdev->pusb_dev_desc->idProduct;
peda->dev_arr[ i ].vendor_id = pdev->pusb_dev_desc->idVendor;
}
else
{
peda->dev_arr[ i ].product_id = 0xffff;
peda->dev_arr[ i ].vendor_id = 0xffff;
}
peda->dev_arr[ i ].dev_addr = pdev->dev_addr;
unlock_dev( pdev, FALSE );
j++;
}
}
peda->dev_count = dev_count ? j : 0;
KeReleaseSpinLock( &dev_mgr->dev_list_lock, old_irql );
KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
dev_count = usb_count_list(&dev_mgr->dev_list);
KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
irp->IoStatus.Information = sizeof( ENUM_DEV_ARRAY ) + ( dev_count - 1 ) * sizeof( ENUM_DEV_ELEMENT );
EXIT_DISPATCH( STATUS_SUCCESS, irp );
}
case IOCTL_GET_DEV_DESC:
{
GET_DEV_DESC_REQ gddr;
PUSB_DESC_HEADER pusb_desc_header;
KIRQL old_irql;
PUSB_DEV pdev;
LONG buf_size;
if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( GET_DEV_DESC_REQ ) )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
*((PLONG) irp->AssociatedIrp.SystemBuffer) = dev_count;
irp->IoStatus.Information = sizeof(LONG);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IOCTL_ENUM_DEVICES:
{
PLIST_ENTRY pthis, pnext;
LONG dev_count, array_size, i, j;
PUSB_DEV pdev;
PENUM_DEV_ARRAY peda;
if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8 )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
status = STATUS_SUCCESS;
buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
RtlCopyMemory( &gddr, irp->AssociatedIrp.SystemBuffer, sizeof( GET_DEV_DESC_REQ ) );
pusb_desc_header = irp->AssociatedIrp.SystemBuffer;
if( gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE )
{
EXIT_DISPATCH( STATUS_INVALID_DEVICE_REQUEST, irp );
}
if( usb_query_and_lock_dev( dev_mgr, gddr.dev_handle, &pdev ) != STATUS_SUCCESS )
{
EXIT_DISPATCH( STATUS_IO_DEVICE_ERROR, irp );
}
irp->IoStatus.Information = 0;
if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LONG))
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ENUM_DEV_ARRAY))
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
array_size = *((PULONG) irp->AssociatedIrp.SystemBuffer);
lock_dev( pdev, FALSE );
if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT;
}
if( dev_state( pdev ) != USB_DEV_STATE_ADDRESSED && \
dev_state( pdev ) != USB_DEV_STATE_CONFIGURED )
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
dev_count = usb_count_list(&dev_mgr->dev_list);
dev_count = dev_count > array_size ? array_size : dev_count;
peda = (PENUM_DEV_ARRAY) irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(peda, sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT));
if( pdev->pusb_dev_desc == NULL )
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
if( gddr.desc_type == USB_DT_DEVICE )
{
RtlCopyMemory(
pusb_desc_header,
pdev->pusb_dev_desc,
buf_size > sizeof( USB_DEVICE_DESC )
? sizeof( USB_DEVICE_DESC ) : buf_size );
if (dev_count)
{
ListFirst(&dev_mgr->dev_list, pthis);
for(i = 0, j = 0; i < dev_count; i++)
{
pdev = struct_ptr(pthis, USB_DEV, dev_link);
ListNext(&dev_mgr->dev_list, pthis, pnext);
pthis = pnext;
irp->IoStatus.Information =
buf_size >= sizeof( USB_DEVICE_DESC )
? sizeof( USB_DEVICE_DESC ): buf_size ;
}
else if( gddr.desc_type == USB_DT_CONFIG )
{
PUSB_CONFIGURATION_DESC pusb_config_desc;
if( pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx )
{
status = STATUS_INVALID_PARAMETER;
goto ERROR_OUT;
}
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
unlock_dev(pdev, FALSE);
continue;
}
pusb_config_desc = usb_find_config_desc_by_idx(
( PUCHAR )&pdev->pusb_dev_desc[ 1 ],
gddr.desc_idx,
pdev->pusb_dev_desc->bNumConfigurations );
if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
{
unlock_dev(pdev, FALSE);
continue;
}
if( pusb_config_desc == NULL )
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
RtlCopyMemory(
pusb_desc_header,
pusb_config_desc,
buf_size >= pusb_config_desc->wTotalLength
? pusb_config_desc->wTotalLength : buf_size );
peda->dev_arr[i].dev_handle = (pdev->dev_id << 16);
//may not get the desc yet
if (pdev->pusb_dev_desc)
{
peda->dev_arr[i].product_id = pdev->pusb_dev_desc->idProduct;
peda->dev_arr[i].vendor_id = pdev->pusb_dev_desc->idVendor;
}
else
{
peda->dev_arr[i].product_id = 0xffff;
peda->dev_arr[i].vendor_id = 0xffff;
}
peda->dev_arr[i].dev_addr = pdev->dev_addr;
unlock_dev(pdev, FALSE);
j++;
}
}
peda->dev_count = dev_count ? j : 0;
KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
irp->IoStatus.Information =
buf_size >= pusb_config_desc->wTotalLength
? pusb_config_desc->wTotalLength : buf_size;
}
ERROR_OUT:
unlock_dev( pdev, FALSE );
usb_unlock_dev( pdev );
EXIT_DISPATCH( status, irp );
}
case IOCTL_SUBMIT_URB_RD:
case IOCTL_SUBMIT_URB_WR:
case IOCTL_SUBMIT_URB_NOIO:
{
LONG buf_size;
PURB purb;
KIRQL old_irql;
ULONG endp_idx, if_idx, user_buffer_length;
PUCHAR user_buffer;
PUSB_DEV pdev;
DEV_HANDLE endp_handle;
PUSB_ENDPOINT pendp;
PUSB_CTRL_SETUP_PACKET psetup;
irp->IoStatus.Information =
sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IOCTL_GET_DEV_DESC:
{
GET_DEV_DESC_REQ gddr;
PUSB_DESC_HEADER pusb_desc_header;
KIRQL old_irql;
PUSB_DEV pdev;
LONG buf_size;
if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( URB ) )
{
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
}
if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
purb = ( PURB )irp->AssociatedIrp.SystemBuffer;
endp_handle = purb->endp_handle;
if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8)
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
if( ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR )
{
if( irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
{
user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
if( user_buffer_length == 0 )
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
user_buffer = MmGetSystemAddressForMdl( irp->MdlAddress );
}
else
{
if( purb->data_buffer == NULL || purb->data_length == 0 )
EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
user_buffer_length = purb->data_length;
user_buffer = purb->data_buffer;
}
}
if( usb_query_and_lock_dev( dev_mgr, endp_handle & ~0xffff, &pdev ) != STATUS_SUCCESS )
{
EXIT_DISPATCH( STATUS_IO_DEVICE_ERROR, irp );
}
lock_dev( pdev, FALSE );
if( dev_state( pdev ) == USB_DEV_STATE_ZOMB \
|| ( dev_state( pdev ) < USB_DEV_STATE_ADDRESSED ) )
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT1;
}
if( dev_state( pdev ) == USB_DEV_STATE_ADDRESSED
&& !default_endp_handle( endp_handle ) )
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT1;
}
status = STATUS_SUCCESS;
buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
RtlCopyMemory(&gddr, irp->AssociatedIrp.SystemBuffer, sizeof(GET_DEV_DESC_REQ));
pusb_desc_header = irp->AssociatedIrp.SystemBuffer;
if_idx = if_idx_from_handle( endp_handle );
endp_idx = endp_idx_from_handle( endp_handle );
if (gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE)
{
EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
//if_idx exceeds the upper limit
if( pdev->usb_config )
{
if( if_idx >= pdev->usb_config->if_count
|| endp_idx >= pdev->usb_config->interf[ if_idx ].endp_count )
{
if( !default_endp_handle( endp_handle ) )
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT1;
}
}
}
endp_from_handle( pdev, endp_handle, pendp );
// FIXME: don't know what evil will let loose
if( endp_type( pendp ) != USB_ENDPOINT_XFER_CONTROL )
{
if( user_buffer_length > 0x100000 )
{
status = STATUS_INVALID_PARAMETER;
goto ERROR_OUT1;
}
}
purb->pirp = irp;
purb->context = dev_mgr;
purb->reference = ctrl_code;
if (usb_query_and_lock_dev(dev_mgr, gddr.dev_handle, &pdev) != STATUS_SUCCESS)
{
EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
}
if( ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR )
{
if( ctrl_code == IOCTL_SUBMIT_URB_RD )
KeFlushIoBuffers( irp->MdlAddress, TRUE, TRUE );
else
KeFlushIoBuffers( irp->MdlAddress, FALSE, TRUE );
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT;
}
if (dev_state(pdev) != USB_DEV_STATE_ADDRESSED &&
dev_state(pdev) != USB_DEV_STATE_CONFIGURED)
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
purb->data_buffer = user_buffer;
purb->data_length = user_buffer_length;
purb->completion = disp_urb_completion;
}
else
{
purb->completion = disp_noio_urb_completion;
}
if (pdev->pusb_dev_desc == NULL)
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
unlock_dev( pdev, FALSE );
if (gddr.desc_type == USB_DT_DEVICE)
{
RtlCopyMemory(pusb_desc_header,
pdev->pusb_dev_desc,
buf_size > sizeof(USB_DEVICE_DESC)
? sizeof(USB_DEVICE_DESC) : buf_size);
// we have to mark irp before the urb is scheduled to
// avoid race condition
IoMarkIrpPending( irp );
ASSERT( dev_mgr_register_irp( dev_mgr, irp, purb ) );
status = usb_submit_urb( dev_mgr, purb );
if( status != STATUS_PENDING )
{
IoGetCurrentIrpStackLocation( (irp) )->Control &= ~SL_PENDING_RETURNED;
dev_mgr_remove_irp( dev_mgr, irp );
}
usb_unlock_dev( pdev );
if( status != STATUS_PENDING)
{
irp->IoStatus.Status = status;
IoCompleteRequest( irp, IO_NO_INCREMENT);
}
return status;
ERROR_OUT1:
unlock_dev( pdev, FALSE );
usb_unlock_dev( pdev );
irp->IoStatus.Information = 0;
EXIT_DISPATCH( status, irp );
}
default:
{
irp->IoStatus.Information = 0;
EXIT_DISPATCH( STATUS_NOT_IMPLEMENTED, irp );
}
}
}
default:
{
irp->IoStatus.Information = 0;
break;
}
}
EXIT_DISPATCH( STATUS_INVALID_DEVICE_REQUEST, irp );
irp->IoStatus.Information =
buf_size >= sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : buf_size;
}
else if (gddr.desc_type == USB_DT_CONFIG)
{
PUSB_CONFIGURATION_DESC pusb_config_desc;
if (pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx)
{
status = STATUS_INVALID_PARAMETER;
goto ERROR_OUT;
}
pusb_config_desc = usb_find_config_desc_by_idx((PUCHAR) & pdev->pusb_dev_desc[1],
gddr.desc_idx,
pdev->pusb_dev_desc->
bNumConfigurations);
if (pusb_config_desc == NULL)
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT;
}
RtlCopyMemory(pusb_desc_header,
pusb_config_desc,
buf_size >= pusb_config_desc->wTotalLength
? pusb_config_desc->wTotalLength : buf_size);
irp->IoStatus.Information =
buf_size >= pusb_config_desc->wTotalLength
? pusb_config_desc->wTotalLength : buf_size;
}
ERROR_OUT:
unlock_dev(pdev, FALSE);
usb_unlock_dev(pdev);
EXIT_DISPATCH(status, irp);
}
case IOCTL_SUBMIT_URB_RD:
case IOCTL_SUBMIT_URB_WR:
case IOCTL_SUBMIT_URB_NOIO:
{
LONG buf_size;
PURB purb;
KIRQL old_irql;
ULONG endp_idx, if_idx, user_buffer_length;
PUCHAR user_buffer;
PUSB_DEV pdev;
DEV_HANDLE endp_handle;
PUSB_ENDPOINT pendp;
PUSB_CTRL_SETUP_PACKET psetup;
if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
{
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
}
purb = (PURB) irp->AssociatedIrp.SystemBuffer;
endp_handle = purb->endp_handle;
if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
{
if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
{
user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
if (user_buffer_length == 0)
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
}
else
{
if (purb->data_buffer == NULL || purb->data_length == 0)
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
user_buffer_length = purb->data_length;
user_buffer = purb->data_buffer;
}
}
if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
{
EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
}
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED))
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT1;
}
if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle))
{
status = STATUS_DEVICE_NOT_READY;
goto ERROR_OUT1;
}
if_idx = if_idx_from_handle(endp_handle);
endp_idx = endp_idx_from_handle(endp_handle);
//if_idx exceeds the upper limit
if (pdev->usb_config)
{
if (if_idx >= pdev->usb_config->if_count
|| endp_idx >= pdev->usb_config->interf[if_idx].endp_count)
{
if (!default_endp_handle(endp_handle))
{
status = STATUS_INVALID_DEVICE_STATE;
goto ERROR_OUT1;
}
}
}
endp_from_handle(pdev, endp_handle, pendp);
// FIXME: don't know what evil will let loose
if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
{
if (user_buffer_length > 0x100000)
{
status = STATUS_INVALID_PARAMETER;
goto ERROR_OUT1;
}
}
purb->pirp = irp;
purb->context = dev_mgr;
purb->reference = ctrl_code;
if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
{
if (ctrl_code == IOCTL_SUBMIT_URB_RD)
KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
else
KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
purb->data_buffer = user_buffer;
purb->data_length = user_buffer_length;
purb->completion = disp_urb_completion;
}
else
{
purb->completion = disp_noio_urb_completion;
}
unlock_dev(pdev, FALSE);
// we have to mark irp before the urb is scheduled to
// avoid race condition
IoMarkIrpPending(irp);
ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
status = usb_submit_urb(dev_mgr, purb);
if (status != STATUS_PENDING)
{
IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED;
dev_mgr_remove_irp(dev_mgr, irp);
}
usb_unlock_dev(pdev);
if (status != STATUS_PENDING)
{
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
return status;
ERROR_OUT1:
unlock_dev(pdev, FALSE);
usb_unlock_dev(pdev);
irp->IoStatus.Information = 0;
EXIT_DISPATCH(status, irp);
}
default:
{
irp->IoStatus.Information = 0;
EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED, irp);
}
}
}
default:
{
irp->IoStatus.Information = 0;
break;
}
}
EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
/*#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS )

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff