mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 19:33:23 +00:00
[FORMATTING]
svn path=/trunk/; revision=23616
This commit is contained in:
parent
4e7aa7365f
commit
f448f3bae0
12 changed files with 18078 additions and 20290 deletions
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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( ¶m, 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(¶m, 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:
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue