#define OLYMPUS_CSW( pdev_EXT, staTUS ) \
( ( ( pdev_EXT )->flags & UMSS_DEV_FLAG_OLYMPUS_DEV ) ? ( ( staTUS ) == CSW_OLYMPUS_SIGNATURE ) : FALSE )
-BOOL
-umss_clear_pass_through_length(
-PIO_PACKET io_packet
-);
+BOOL umss_clear_pass_through_length(PIO_PACKET io_packet);
-NTSTATUS
-umss_bulkonly_send_sense_req(
-PUMSS_DEVICE_EXTENSION pdev_ext
-);
+NTSTATUS umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext);
-VOID
-umss_bulkonly_send_cbw_completion(
-IN PURB purb,
-IN PVOID context
-);
+VOID umss_bulkonly_send_cbw_completion(IN PURB purb, IN PVOID context);
-VOID
-umss_bulkonly_transfer_data(
-PUMSS_DEVICE_EXTENSION pdev_ext
-);
+VOID umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext);
-VOID
-umss_sync_submit_urb_completion(
-PURB purb,
-PVOID context
-);
+VOID umss_sync_submit_urb_completion(PURB purb, PVOID context);
-NTSTATUS
-umss_sync_submit_urb(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-PURB purb
-);
+NTSTATUS umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext, PURB purb);
-VOID
-umss_bulkonly_get_status(
-PUMSS_DEVICE_EXTENSION pdev_ext
-);
+VOID umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext);
-VOID
-umss_bulkonly_transfer_data_complete(
-PURB purb,
-PVOID reference
-);
+VOID umss_bulkonly_transfer_data_complete(PURB purb, PVOID reference);
-VOID
-umss_bulkonly_reset_pipe_and_get_status(
-IN PVOID reference
-);
+VOID umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference);
-VOID
-umss_bulkonly_reset_recovery(
-IN PVOID reference
-);
+VOID umss_bulkonly_reset_recovery(IN PVOID reference);
-VOID
-umss_bulkonly_get_status_complete(
-IN PURB purb,
-IN PVOID context
-);
+VOID umss_bulkonly_get_status_complete(IN PURB purb, IN PVOID context);
-NTSTATUS
-umss_bulkonly_startio(
-IN PUMSS_DEVICE_EXTENSION pdev_ext,
-IN PIO_PACKET io_packet
-)
/*++
Routine Description:
NONE
--*/
-
+NTSTATUS
+umss_bulkonly_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext, IN PIO_PACKET io_packet)
{
PCOMMAND_BLOCK_WRAPPER cbw;
- NTSTATUS status;
+ NTSTATUS status;
- if( pdev_ext == NULL || io_packet == NULL || io_packet->pirp == NULL )
- return STATUS_INVALID_PARAMETER;
+ if (pdev_ext == NULL || io_packet == NULL || io_packet->pirp == NULL)
+ return STATUS_INVALID_PARAMETER;
pdev_ext->retry = TRUE;
- RtlCopyMemory( &pdev_ext->io_packet, io_packet, sizeof( pdev_ext->io_packet ) );
+ RtlCopyMemory(&pdev_ext->io_packet, io_packet, sizeof(pdev_ext->io_packet));
- // Setup the command block wrapper for this request
+ // Setup the command block wrapper for this request
cbw = &pdev_ext->cbw;
cbw->dCBWSignature = CBW_SIGNATURE;
cbw->dCBWTag = 0;
cbw->dCBWDataTransferLength = io_packet->data_length;
- cbw->bmCBWFlags = ( io_packet->flags & USB_DIR_IN ) ? 0x80 : 0;
+ cbw->bmCBWFlags = (io_packet->flags & USB_DIR_IN) ? 0x80 : 0;
cbw->bCBWLun = io_packet->lun;
cbw->bCBWLength = io_packet->cdb_length;
- RtlCopyMemory( cbw->CBWCB, io_packet->cdb, sizeof( cbw->CBWCB ) );
+ RtlCopyMemory(cbw->CBWCB, io_packet->cdb, sizeof(cbw->CBWCB));
- RtlZeroMemory( &pdev_ext->csw, sizeof( pdev_ext->csw ) );
+ RtlZeroMemory(&pdev_ext->csw, sizeof(pdev_ext->csw));
// Send the command block wrapper to the device.
// Calls UMSS_BulkOnlySendCBWComplete when transfer completes.
- status = umss_bulk_transfer(
- pdev_ext,
- USB_DIR_OUT,
- cbw,
- sizeof( COMMAND_BLOCK_WRAPPER ),
- umss_bulkonly_send_cbw_completion
- );
-
- return status;
+ status = umss_bulk_transfer(pdev_ext,
+ USB_DIR_OUT,
+ cbw, sizeof(COMMAND_BLOCK_WRAPPER), umss_bulkonly_send_cbw_completion);
+
+ return status;
}
NTSTATUS
-umss_bulk_transfer(
-IN PUMSS_DEVICE_EXTENSION pdev_ext,
-IN UCHAR trans_dir,
-IN PVOID buf,
-IN ULONG buf_length,
-IN PURBCOMPLETION completion
-)
+umss_bulk_transfer(IN PUMSS_DEVICE_EXTENSION pdev_ext,
+ IN UCHAR trans_dir, IN PVOID buf, IN ULONG buf_length, IN PURBCOMPLETION completion)
{
- PURB purb;
- NTSTATUS status;
- DEV_HANDLE endp_handle;
-
- if( pdev_ext == NULL || buf == NULL || completion == NULL )
- return STATUS_INVALID_PARAMETER;
-
- if( buf_length > ( ULONG )MAX_BULK_TRANSFER_LENGTH )
- return STATUS_INVALID_PARAMETER;
-
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
-
- if( purb == NULL )
- return STATUS_NO_MEMORY;
-
- if( trans_dir == USB_DIR_OUT )
- {
- endp_handle = usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->out_endp_idx );
- }
- else
- {
- endp_handle = usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->in_endp_idx );
- }
-
- UsbBuildInterruptOrBulkTransferRequest( purb,
- endp_handle,
- buf,
- buf_length,
- completion,
- pdev_ext,
- 0 );
- dev_mgr_register_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb );
- status = usb_submit_urb( pdev_ext->dev_mgr, purb );
- if( status == STATUS_PENDING )
- {
- return status;
- }
-
- dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
- if( purb )
- {
- usb_free_mem( purb );
- purb = NULL;
- }
- return status;
+ PURB purb;
+ NTSTATUS status;
+ DEV_HANDLE endp_handle;
+
+ if (pdev_ext == NULL || buf == NULL || completion == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (buf_length > (ULONG) MAX_BULK_TRANSFER_LENGTH)
+ return STATUS_INVALID_PARAMETER;
+
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+
+ if (purb == NULL)
+ return STATUS_NO_MEMORY;
+
+ if (trans_dir == USB_DIR_OUT)
+ {
+ endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx);
+ }
+ else
+ {
+ endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx);
+ }
+
+ UsbBuildInterruptOrBulkTransferRequest(purb, endp_handle, buf, buf_length, completion, pdev_ext, 0);
+ dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb);
+ status = usb_submit_urb(pdev_ext->dev_mgr, purb);
+ if (status == STATUS_PENDING)
+ {
+ return status;
+ }
+
+ dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
+ if (purb)
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ }
+ return status;
}
VOID
-umss_bulkonly_send_cbw_completion(
-IN PURB purb,
-IN PVOID context
-)
+umss_bulkonly_send_cbw_completion(IN PURB purb, IN PVOID context)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )context;
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
- status = purb->status;
- dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
+ status = purb->status;
+ dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
- if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_SENSE )
- {
- usb_free_mem( purb->data_buffer );
- purb->data_buffer = NULL;
- purb->data_length = 0;
- }
+ if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE)
+ {
+ usb_free_mem(purb->data_buffer);
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ }
- if ( status != STATUS_SUCCESS )
+ if (status != STATUS_SUCCESS)
{
- if ( usb_halted( status ) )
+ if (usb_halted(status))
{
//Schedule a work-item to do a reset recovery
- if( !umss_schedule_workitem( (PVOID)pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
- {
- umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
- }
+ if (!umss_schedule_workitem
+ ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle))
+ {
+ umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
+ }
}
else
{
// Device failed CBW without stalling, so complete with error
- umss_complete_request( pdev_ext, status );
+ umss_complete_request(pdev_ext, status);
}
}
else
{
// CBW was accepted by device, so start data phase of I/O operation
- umss_bulkonly_transfer_data( pdev_ext );
+ umss_bulkonly_transfer_data(pdev_ext);
}
- if( purb )
- usb_free_mem( purb );
+ if (purb)
+ usb_free_mem(purb);
- purb = NULL;
- return;
+ purb = NULL;
+ return;
}
-NTSTATUS
-umss_sync_submit_urb(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-PURB purb
-)
//can only be called at passive level
+NTSTATUS
+umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext, PURB purb)
{
- NTSTATUS status;
-
- if( pdev_ext == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- purb->completion = umss_sync_submit_urb_completion;
- purb->context = ( PVOID )pdev_ext;
-
- dev_mgr_register_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb );
- status = usb_submit_urb( pdev_ext->dev_mgr, purb );
- if( status == STATUS_PENDING )
- {
- KeWaitForSingleObject(
- &pdev_ext->sync_event,
- Executive,
- KernelMode,
- TRUE,
- NULL );
- status = purb->status;
- }
- else
- dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
-
- return status;
+ NTSTATUS status;
+
+ if (pdev_ext == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ purb->completion = umss_sync_submit_urb_completion;
+ purb->context = (PVOID) pdev_ext;
+
+ dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb);
+ status = usb_submit_urb(pdev_ext->dev_mgr, purb);
+ if (status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL);
+ status = purb->status;
+ }
+ else
+ dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
+
+ return status;
}
VOID
-umss_sync_submit_urb_completion(
-PURB purb,
-PVOID context
-)
+umss_sync_submit_urb_completion(PURB purb, PVOID context)
{
- PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
- if( purb == NULL || context == NULL )
- return;
+ if (purb == NULL || context == NULL)
+ return;
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )context;
- dev_mgr_remove_irp( pdev_ext->dev_mgr, pdev_ext->io_packet.pirp );
- KeSetEvent( &pdev_ext->sync_event, 0, FALSE );
- return;
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
+ dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
+ KeSetEvent(&pdev_ext->sync_event, 0, FALSE);
+ return;
}
-VOID
-umss_bulkonly_reset_recovery(
-IN PVOID reference
-)
/*++
Routine Description:
NONE
--*/
-
+VOID
+umss_bulkonly_reset_recovery(IN PVOID reference)
{
PUMSS_DEVICE_EXTENSION pdev_ext;
URB urb;
NTSTATUS status;
- DEV_HANDLE endp_handle;
+ DEV_HANDLE endp_handle;
- pdev_ext = (PUMSS_DEVICE_EXTENSION)reference;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_bulkonly_reset_recovery(): entering...\n" ) );
- // Steps for reset recovery:
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) reference;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_bulkonly_reset_recovery(): entering...\n"));
+ // Steps for reset recovery:
// 1. Send device a mass storage reset command on the default endpoint.
// 2. Reset the bulk-in endpoint.
// 3. Reset the bulk-out endpoint.
// Build the mass storage reset command
- UsbBuildVendorRequest(
- &urb,
- pdev_ext->dev_handle | 0xffff, //default pipe
- NULL, //no extra data
- 0, //no size
- 0x21, //class, interface
- BULK_ONLY_MASS_STORAGE_RESET,
- 0,
- pdev_ext->pif_desc->bInterfaceNumber,
- NULL, //completion
- NULL, //context
- 0 ); //reference
+ UsbBuildVendorRequest(&urb, pdev_ext->dev_handle | 0xffff, //default pipe
+ NULL, //no extra data
+ 0, //no size
+ 0x21, //class, interface
+ BULK_ONLY_MASS_STORAGE_RESET,
+ 0,
+ pdev_ext->pif_desc->bInterfaceNumber,
+ NULL, //completion
+ NULL, //context
+ 0); //reference
// Send mass storage reset command to device
- status = umss_sync_submit_urb( pdev_ext, &urb);
+ status = umss_sync_submit_urb(pdev_ext, &urb);
- if ( status != STATUS_SUCCESS )
+ if (status != STATUS_SUCCESS)
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_recovery(): Reset Recovery failed!\n"));
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_recovery(): Reset Recovery failed!\n"));
}
else
{
//Reset Bulk-in endpoint
- endp_handle = usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->in_endp_idx );
- status = umss_reset_pipe(
- pdev_ext,
- endp_handle
- );
+ endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx);
+ status = umss_reset_pipe(pdev_ext, endp_handle);
if (!NT_SUCCESS(status))
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_recovery(): Unable to clear Bulk-in endpoint\n"));
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-in endpoint\n"));
}
//Reset Bulk-out endpoint
- endp_handle = usb_make_handle( ( pdev_ext->dev_handle >> 16 ), pdev_ext->if_idx, pdev_ext->out_endp_idx );
- status = umss_reset_pipe(
- pdev_ext,
- endp_handle
- );
+ endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx);
+ status = umss_reset_pipe(pdev_ext, endp_handle);
if (!NT_SUCCESS(status))
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n"));
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n"));
}
}
- umss_complete_request( pdev_ext, status );
+ umss_complete_request(pdev_ext, status);
}
-
-VOID
-umss_bulkonly_transfer_data(
-PUMSS_DEVICE_EXTENSION pdev_ext
-)
/*++
Routine Description:
NONE
--*/
-
+VOID
+umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext)
{
PVOID data_buf;
ULONG data_buf_length;
- NTSTATUS status;
- UCHAR trans_dir;
+ NTSTATUS status;
+ UCHAR trans_dir;
// Steps for data phase
// 1. Get data buffer fragment (either SGD list, flat buffer, or none).
// 4. Move to status phase.
// Get next data buffer element, if any
- data_buf = umss_get_buffer( pdev_ext, &data_buf_length);
+ data_buf = umss_get_buffer(pdev_ext, &data_buf_length);
if (NULL == data_buf)
{
//No data to transfer, so move to status phase
- umss_bulkonly_get_status( pdev_ext );
+ umss_bulkonly_get_status(pdev_ext);
}
else
{
// Schedule the data transfer.
// Calls umss_bulkonly_transfer_data_complete when transfer completes.
-
- if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_NORMAL )
- trans_dir = ( UCHAR )( ( pdev_ext->cbw.bmCBWFlags & USB_DIR_IN ) ? USB_DIR_IN : USB_DIR_OUT );
- else if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_SENSE )
- trans_dir = USB_DIR_IN;
-
- if( ( status = umss_bulk_transfer(
- pdev_ext,
- trans_dir,
- data_buf,
- data_buf_length,
- umss_bulkonly_transfer_data_complete )
- ) != STATUS_PENDING )
- {
- umss_complete_request( pdev_ext, status );
- }
+
+ if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL)
+ trans_dir = (UCHAR) ((pdev_ext->cbw.bmCBWFlags & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT);
+ else if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE)
+ trans_dir = USB_DIR_IN;
+
+ if ((status = umss_bulk_transfer(pdev_ext,
+ trans_dir,
+ data_buf,
+ data_buf_length,
+ umss_bulkonly_transfer_data_complete)) != STATUS_PENDING)
+ {
+ umss_complete_request(pdev_ext, status);
+ }
}
- return;
+ return;
}
-
-VOID
-umss_bulkonly_transfer_data_complete(
-PURB purb,
-PVOID reference
-)
/*++
Routine Description:
Completion handler for bulk data transfer requests.
--*/
-
+VOID
+umss_bulkonly_transfer_data_complete(PURB purb, PVOID reference)
{
NTSTATUS status;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )reference;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) reference;
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 ( status != STATUS_SUCCESS )
+ if (status != STATUS_SUCCESS)
{
- //
- // clear the data length if this is a scsi pass through request
- //
- umss_clear_pass_through_length( &pdev_ext->io_packet );
+ //
+ // clear the data length if this is a scsi pass through request
+ //
+ umss_clear_pass_through_length(&pdev_ext->io_packet);
// Device failed data phase
// Check if we need to clear stalled pipe
- if ( usb_halted( status ) )
+ if (usb_halted(status))
{
- PULONG buf;
- buf = usb_alloc_mem( NonPagedPool, 32 );
- buf[ 0 ] = ( ULONG )pdev_ext;
- buf[ 1 ] = ( ULONG )purb->endp_handle;
-
- usb_dbg_print( DBGLVL_MINIMUM,("umss_transfer_data_complete(): transfer data error!\n"));
- if (!umss_schedule_workitem( ( PVOID )buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
+ PULONG buf;
+ buf = usb_alloc_mem(NonPagedPool, 32);
+ buf[0] = (ULONG) pdev_ext;
+ buf[1] = (ULONG) purb->endp_handle;
+
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_transfer_data_complete(): transfer data error!\n"));
+ if (!umss_schedule_workitem
+ ((PVOID) buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr,
+ pdev_ext->dev_handle))
{
- usb_free_mem( buf ), buf = NULL;
- usb_dbg_print( DBGLVL_MINIMUM,("umss_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
+ usb_free_mem(buf), buf = NULL;
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
TRAP();
- umss_complete_request( pdev_ext, status );
+ umss_complete_request(pdev_ext, status);
}
}
- else
- {
- //finish our request
- umss_complete_request( pdev_ext, status );
- }
+ else
+ {
+ //finish our request
+ umss_complete_request(pdev_ext, status);
+ }
}
else
{
// Start next part of data phase
//umss_bulkonly_transfer_data( pdev_ext );
- umss_bulkonly_get_status( pdev_ext );
- //umss_complete_request( pdev_ext, status );
+ umss_bulkonly_get_status(pdev_ext);
+ //umss_complete_request( pdev_ext, status );
}
- usb_free_mem( purb );
- purb = NULL;
+ usb_free_mem(purb);
+ purb = NULL;
- return; // STATUS_MORE_PROCESSING_REQUIRED;
+ return; // STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
-umss_bulkonly_reset_pipe_and_get_status(
-IN PVOID reference
-)
+umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference)
{
- PUMSS_DEVICE_EXTENSION pdev_ext;
- DEV_HANDLE endp_handle;
- NTSTATUS status;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ DEV_HANDLE endp_handle;
+ NTSTATUS status;
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_pipe_and_get_status(): entering...\n") );
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_pipe_and_get_status(): entering...\n"));
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )( ( ( PULONG )reference )[ 0 ] );
- endp_handle = ( DEV_HANDLE )( ( PULONG )reference )[ 1 ];
- usb_free_mem( reference );
- reference = NULL;
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) (((PULONG) reference)[0]);
+ endp_handle = (DEV_HANDLE) ((PULONG) reference)[1];
+ usb_free_mem(reference);
+ reference = NULL;
// Reset the endpoint
- if( ( status = umss_reset_pipe( pdev_ext, endp_handle ) ) != STATUS_SUCCESS )
- {
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_pipe_and_get_status(): reset pipe failed\n") );
- umss_complete_request( pdev_ext, status );
- return;
- }
+ if ((status = umss_reset_pipe(pdev_ext, endp_handle)) != STATUS_SUCCESS)
+ {
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe failed\n"));
+ umss_complete_request(pdev_ext, status);
+ return;
+ }
// Data phase is finished since the endpoint stalled, so go to status phase
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_reset_pipe_and_get_status(): reset pipe succeeds, continue to get status\n") );
- umss_bulkonly_get_status( pdev_ext );
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe succeeds, continue to get status\n"));
+ umss_bulkonly_get_status(pdev_ext);
}
VOID
-umss_bulkonly_get_status(
-PUMSS_DEVICE_EXTENSION pdev_ext
-)
+umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext)
{
- NTSTATUS status;
+ NTSTATUS status;
// Schedule bulk transfer to get command status wrapper from device
- status = umss_bulk_transfer(
- pdev_ext,
- USB_DIR_IN,
- &( pdev_ext->csw ),
- sizeof( COMMAND_STATUS_WRAPPER ),
- umss_bulkonly_get_status_complete
- );
- if( status != STATUS_PENDING )
- {
- umss_complete_request( pdev_ext, status );
- }
+ status = umss_bulk_transfer(pdev_ext,
+ USB_DIR_IN,
+ &(pdev_ext->csw),
+ sizeof(COMMAND_STATUS_WRAPPER), umss_bulkonly_get_status_complete);
+ if (status != STATUS_PENDING)
+ {
+ umss_complete_request(pdev_ext, status);
+ }
}
-
-VOID
-umss_bulkonly_get_status_complete(
-IN PURB purb,
-IN PVOID context
-)
/*++
Routine Description:
Driver-originated IRPs always return STATUS_MORE_PROCESSING_REQUIRED.
--*/
-
+VOID
+umss_bulkonly_get_status_complete(IN PURB purb, IN PVOID context)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
PCOMMAND_STATUS_WRAPPER csw;
- pdev_ext = ( PUMSS_DEVICE_EXTENSION ) context;
- status = purb->status;
+ 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);
- csw = &( pdev_ext->csw );
- if ( status == STATUS_SUCCESS &&
- ( ( csw->dCSWSignature == CSW_SIGNATURE ) || OLYMPUS_CSW( pdev_ext, csw->dCSWSignature ) ) )
+ csw = &(pdev_ext->csw);
+ if (status == STATUS_SUCCESS &&
+ ((csw->dCSWSignature == CSW_SIGNATURE) || OLYMPUS_CSW(pdev_ext, csw->dCSWSignature)))
{
- if ( csw->bCSWStatus == CSW_STATUS_PASSED )
+ if (csw->bCSWStatus == CSW_STATUS_PASSED)
{
// Received valid CSW with good status
- if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_NORMAL &&
- ( pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE ) &&
- pdev_ext->io_packet.sense_data != NULL )
- UMSS_FORGE_GOOD_SENSE( pdev_ext->io_packet.sense_data )
-
- umss_complete_request( pdev_ext, STATUS_SUCCESS );
+ if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL &&
+ (pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE) && pdev_ext->io_packet.sense_data != NULL)
+ UMSS_FORGE_GOOD_SENSE(pdev_ext->io_packet.sense_data)
+ umss_complete_request(pdev_ext, STATUS_SUCCESS);
+ }
+ else if (csw->bCSWStatus == CSW_STATUS_FAILED)
+ {
+ // start a request sense if necessary
+ if ((pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE) &&
+ (pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL)
+ {
+ if (umss_bulkonly_send_sense_req(pdev_ext) != STATUS_PENDING)
+ {
+ // don't know how to handle.
+ umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
+ }
+ else
+ {
+ // fall through to free the urb
+ }
+ }
+ else
+ {
+ // error occurred, reset device
+ if (!umss_schedule_workitem
+ ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle))
+ {
+ umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
+ }
+ }
}
- else if ( csw->bCSWStatus == CSW_STATUS_FAILED )
- {
- // start a request sense if necessary
- if( ( pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE ) &&
- ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_NORMAL )
- {
- if( umss_bulkonly_send_sense_req( pdev_ext ) != STATUS_PENDING )
- {
- // don't know how to handle.
- umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
- }
- else
- {
- // fall through to free the urb
- }
- }
- else
- {
- // error occurred, reset device
- if( !umss_schedule_workitem( (PVOID)pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
- {
- umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
- }
- }
- }
else
{
// error occurred, reset device
- if( !umss_schedule_workitem( (PVOID)pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
- {
- umss_complete_request( pdev_ext, STATUS_IO_DEVICE_ERROR );
- }
+ if (!umss_schedule_workitem
+ ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle))
+ {
+ umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
+ }
}
}
- else if ( ( status != STATUS_SUCCESS ) && ( usb_halted( status ) ) && ( pdev_ext->retry ) )
+ else if ((status != STATUS_SUCCESS) && (usb_halted(status)) && (pdev_ext->retry))
{
// Device stalled CSW transfer, retry once before failing
- PULONG buf;
+ PULONG buf;
pdev_ext->retry = FALSE;
- buf = usb_alloc_mem( NonPagedPool, 32 );
- buf[ 0 ] = ( ULONG )pdev_ext;
- buf[ 1 ] = ( ULONG )purb->endp_handle;
+ buf = usb_alloc_mem(NonPagedPool, 32);
+ buf[0] = (ULONG) pdev_ext;
+ buf[1] = (ULONG) purb->endp_handle;
- if ( !umss_schedule_workitem( ( PVOID )buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
+ if (!umss_schedule_workitem
+ ((PVOID) buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr, pdev_ext->dev_handle))
{
- usb_free_mem( buf ), buf = NULL;
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
+ usb_free_mem(buf), buf = NULL;
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
TRAP();
- umss_complete_request( pdev_ext, status );
+ umss_complete_request(pdev_ext, status);
}
}
- else if( status != STATUS_CANCELLED )
+ else if (status != STATUS_CANCELLED)
{
// An error has occured. Reset the device.
- if ( !umss_schedule_workitem( ( PVOID )pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle ) )
+ if (!umss_schedule_workitem
+ ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle))
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_status_complete(): Failed to schedule work-item to reset pipe!\n"));
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_get_status_complete(): Failed to schedule work-item to reset pipe!\n"));
TRAP();
- umss_complete_request( pdev_ext, status );
+ umss_complete_request(pdev_ext, status);
}
}
- else
- {
- // the request is canceled
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_status_complete(): the request is canceled\n"));
- umss_complete_request( pdev_ext, STATUS_CANCELLED );
- }
+ else
+ {
+ // the request is canceled
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_get_status_complete(): the request is canceled\n"));
+ umss_complete_request(pdev_ext, STATUS_CANCELLED);
+ }
- usb_free_mem( purb );
- purb = NULL;
+ usb_free_mem(purb);
+ purb = NULL;
- return;
+ return;
}
-
-CHAR
-umss_bulkonly_get_maxlun(
-IN PUMSS_DEVICE_EXTENSION pdev_ext
-)
/*++
Routine Description:
Maximum LUN number for device, or 0 if error occurred.
--*/
-
+CHAR
+umss_bulkonly_get_maxlun(IN PUMSS_DEVICE_EXTENSION pdev_ext)
{
- PURB purb=NULL;
+ PURB purb = NULL;
CHAR max_lun;
NTSTATUS status;
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (!purb)
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_maxlun(): Failed to allocate URB, setting max LUN to 0\n"));
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_get_maxlun(): Failed to allocate URB, setting max LUN to 0\n"));
max_lun = 0;
}
else
{
// Build the get max lun command
- UsbBuildVendorRequest(
- purb,
- ( pdev_ext->dev_handle | 0xffff ),
- &max_lun,
- sizeof( max_lun ),
- 0xb1, //class, interface, in
- BULK_ONLY_GET_MAX_LUN,
- 0,
- pdev_ext->pif_desc->bInterfaceNumber,
- NULL,
- NULL,
- 0);
+ UsbBuildVendorRequest(purb, (pdev_ext->dev_handle | 0xffff), &max_lun, sizeof(max_lun), 0xb1, //class, interface, in
+ BULK_ONLY_GET_MAX_LUN, 0, pdev_ext->pif_desc->bInterfaceNumber, NULL, NULL, 0);
// Send get max lun command to device
- status = umss_sync_submit_urb( pdev_ext, purb);
+ status = umss_sync_submit_urb(pdev_ext, purb);
- if ( status != STATUS_PENDING )
+ if (status != STATUS_PENDING)
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_maxlun(): Get Max LUN command failed, setting max LUN to 0!\n"));
+ usb_dbg_print(DBGLVL_MINIMUM,
+ ("umss_bulkonly_get_maxlun(): Get Max LUN command failed, setting max LUN to 0!\n"));
max_lun = 0;
}
}
- if ( purb )
- usb_free_mem( purb );
+ if (purb)
+ usb_free_mem(purb);
- usb_dbg_print( DBGLVL_MINIMUM,("umss_bulkonly_get_maxlun(): Max LUN = %x\n", max_lun));
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_get_maxlun(): Max LUN = %x\n", max_lun));
return max_lun;
}
PVOID
-umss_get_buffer(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-ULONG* buf_length
-)
+umss_get_buffer(PUMSS_DEVICE_EXTENSION pdev_ext, ULONG * buf_length)
{
PVOID buffer;
- if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_NORMAL )
- {
- buffer = (PVOID)pdev_ext->io_packet.data_buffer;
- *buf_length = pdev_ext->io_packet.data_length;
- }
- else if( ( pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK ) == IOP_FLAG_STAGE_SENSE )
- {
- buffer = (PVOID)pdev_ext->io_packet.sense_data;
- *buf_length = pdev_ext->io_packet.sense_data_length;
- }
-
- return buffer;
+ if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL)
+ {
+ buffer = (PVOID) pdev_ext->io_packet.data_buffer;
+ *buf_length = pdev_ext->io_packet.data_length;
+ }
+ else if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE)
+ {
+ buffer = (PVOID) pdev_ext->io_packet.sense_data;
+ *buf_length = pdev_ext->io_packet.sense_data_length;
+ }
+
+ return buffer;
}
BOOL
-umss_bulkonly_build_sense_cdb(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-PCOMMAND_BLOCK_WRAPPER cbw
-)
+umss_bulkonly_build_sense_cdb(PUMSS_DEVICE_EXTENSION pdev_ext, PCOMMAND_BLOCK_WRAPPER cbw)
{
- UCHAR sub_class;
- PUCHAR cdb;
-
- if( pdev_ext == NULL || cbw == NULL )
- return FALSE;
-
- cdb = cbw->CBWCB;
- RtlZeroMemory( cdb, MAX_CDB_LENGTH );
- sub_class = pdev_ext->pif_desc->bInterfaceSubClass;
-
- cdb[ 0 ] = SFF_REQUEST_SENSEE;
- cdb[ 1 ] = pdev_ext->io_packet.lun << 5;
- cdb[ 4 ] = 18;
-
- switch( sub_class )
- {
- case UMSS_SUBCLASS_SFF8070I:
- case UMSS_SUBCLASS_UFI:
- {
- cbw->bCBWLength = 12;
- break;
- }
- case UMSS_SUBCLASS_RBC:
- case UMSS_SUBCLASS_SCSI_TCS:
- {
- cbw->bCBWLength = 6;
- break;
- }
- default:
- return FALSE;
- }
- return TRUE;
+ UCHAR sub_class;
+ PUCHAR cdb;
+
+ if (pdev_ext == NULL || cbw == NULL)
+ return FALSE;
+
+ cdb = cbw->CBWCB;
+ RtlZeroMemory(cdb, MAX_CDB_LENGTH);
+ sub_class = pdev_ext->pif_desc->bInterfaceSubClass;
+
+ cdb[0] = SFF_REQUEST_SENSEE;
+ cdb[1] = pdev_ext->io_packet.lun << 5;
+ cdb[4] = 18;
+
+ switch (sub_class)
+ {
+ case UMSS_SUBCLASS_SFF8070I:
+ case UMSS_SUBCLASS_UFI:
+ {
+ cbw->bCBWLength = 12;
+ break;
+ }
+ case UMSS_SUBCLASS_RBC:
+ case UMSS_SUBCLASS_SCSI_TCS:
+ {
+ cbw->bCBWLength = 6;
+ break;
+ }
+ default:
+ return FALSE;
+ }
+ return TRUE;
}
NTSTATUS
-umss_bulkonly_send_sense_req(
-PUMSS_DEVICE_EXTENSION pdev_ext
-)
+umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext)
{
- PCOMMAND_BLOCK_WRAPPER cbw;
- NTSTATUS status;
+ PCOMMAND_BLOCK_WRAPPER cbw;
+ NTSTATUS status;
- if( pdev_ext == NULL || pdev_ext->io_packet.sense_data == NULL || pdev_ext->io_packet.sense_data_length < 18 )
- return STATUS_INVALID_PARAMETER;
+ if (pdev_ext == NULL || pdev_ext->io_packet.sense_data == NULL
+ || pdev_ext->io_packet.sense_data_length < 18)
+ return STATUS_INVALID_PARAMETER;
pdev_ext->retry = TRUE;
- cbw = usb_alloc_mem( NonPagedPool, sizeof( COMMAND_BLOCK_WRAPPER ) );
- RtlZeroMemory( cbw, sizeof( COMMAND_BLOCK_WRAPPER ) );
- pdev_ext->io_packet.flags &= ~IOP_FLAG_STAGE_MASK;
- pdev_ext->io_packet.flags |= IOP_FLAG_STAGE_SENSE;
+ cbw = usb_alloc_mem(NonPagedPool, sizeof(COMMAND_BLOCK_WRAPPER));
+ RtlZeroMemory(cbw, sizeof(COMMAND_BLOCK_WRAPPER));
+ pdev_ext->io_packet.flags &= ~IOP_FLAG_STAGE_MASK;
+ pdev_ext->io_packet.flags |= IOP_FLAG_STAGE_SENSE;
cbw->dCBWSignature = CBW_SIGNATURE;
cbw->dCBWTag = 0;
cbw->bmCBWFlags = USB_DIR_IN;
cbw->bCBWLun = 0;
- if( umss_bulkonly_build_sense_cdb( pdev_ext, cbw ) == FALSE )
- {
- usb_free_mem( cbw );
- cbw = NULL;
- return STATUS_UNSUCCESSFUL;
- }
-
- status = umss_bulk_transfer(
- pdev_ext,
- USB_DIR_OUT,
- cbw,
- sizeof( COMMAND_BLOCK_WRAPPER ),
- umss_bulkonly_send_cbw_completion
- );
-
- if( status != STATUS_PENDING )
- {
- usb_free_mem( cbw );
- cbw = NULL;
- }
- return status;
+ if (umss_bulkonly_build_sense_cdb(pdev_ext, cbw) == FALSE)
+ {
+ usb_free_mem(cbw);
+ cbw = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ status = umss_bulk_transfer(pdev_ext,
+ USB_DIR_OUT,
+ cbw, sizeof(COMMAND_BLOCK_WRAPPER), umss_bulkonly_send_cbw_completion);
+
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(cbw);
+ cbw = NULL;
+ }
+ return status;
}
BOOL
-umss_clear_pass_through_length(
-PIO_PACKET io_packet
-)
+umss_clear_pass_through_length(PIO_PACKET io_packet)
{
- //
- // clear the respective data length to meet request of scsi pass through requirement.
- //
-
- BOOL sense_stage;
- ULONG ctrl_code;
- PIO_STACK_LOCATION cur_stack;
- PSCSI_PASS_THROUGH pass_through;
- PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
-
- if( io_packet == NULL )
- return FALSE;
-
- if( ( io_packet->flags & IOP_FLAG_SCSI_CTRL_TRANSFER ) == 0 )
- return FALSE;
-
- sense_stage = FALSE;
- if( io_packet->flags & IOP_FLAG_STAGE_SENSE )
- sense_stage = TRUE;
-
- cur_stack = IoGetCurrentIrpStackLocation( io_packet->pirp );
- ctrl_code = cur_stack->Parameters.DeviceIoControl.IoControlCode;
- if( ctrl_code == IOCTL_SCSI_PASS_THROUGH_DIRECT )
- {
- pass_through_direct = io_packet->pirp->AssociatedIrp.SystemBuffer;
- if( sense_stage )
- pass_through_direct->SenseInfoLength = 0;
- else
- pass_through_direct->DataTransferLength = 0;
- }
- else if( ctrl_code == IOCTL_SCSI_PASS_THROUGH )
- {
- pass_through= io_packet->pirp->AssociatedIrp.SystemBuffer;
- if( sense_stage )
- pass_through->SenseInfoLength = 0;
- else
- pass_through->DataTransferLength = 0;
- }
- else
- return FALSE;
-
- return TRUE;
+ //
+ // clear the respective data length to meet request of scsi pass through requirement.
+ //
+
+ BOOL sense_stage;
+ ULONG ctrl_code;
+ PIO_STACK_LOCATION cur_stack;
+ PSCSI_PASS_THROUGH pass_through;
+ PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
+
+ if (io_packet == NULL)
+ return FALSE;
+
+ if ((io_packet->flags & IOP_FLAG_SCSI_CTRL_TRANSFER) == 0)
+ return FALSE;
+
+ sense_stage = FALSE;
+ if (io_packet->flags & IOP_FLAG_STAGE_SENSE)
+ sense_stage = TRUE;
+
+ cur_stack = IoGetCurrentIrpStackLocation(io_packet->pirp);
+ ctrl_code = cur_stack->Parameters.DeviceIoControl.IoControlCode;
+ if (ctrl_code == IOCTL_SCSI_PASS_THROUGH_DIRECT)
+ {
+ pass_through_direct = io_packet->pirp->AssociatedIrp.SystemBuffer;
+ if (sense_stage)
+ pass_through_direct->SenseInfoLength = 0;
+ else
+ pass_through_direct->DataTransferLength = 0;
+ }
+ else if (ctrl_code == IOCTL_SCSI_PASS_THROUGH)
+ {
+ pass_through = io_packet->pirp->AssociatedIrp.SystemBuffer;
+ if (sense_stage)
+ pass_through->SenseInfoLength = 0;
+ else
+ pass_through->DataTransferLength = 0;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
}
#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;
-
- 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;
+ 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);
+
+ 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
- );
-
- return status;
+ 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;
}
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)
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;
+ umss_complete_request(pdev_ext, STATUS_SUCCESS);
+ return;
}
-VOID
-umss_cbi_get_status(
-PUMSS_DEVICE_EXTENSION pdev_ext
-)
+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
- );
+
+ 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;
+ 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
-)
+umss_cbi_get_status_complete(PURB purb, PVOID context)
{
NTSTATUS status;
PUMSS_DEVICE_EXTENSION pdev_ext;
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);
}
}
#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_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle);
-BOOL
-compdev_stop(
-PUSB_DEV_MANAGER dev_mgr,
-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_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;
-
- 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.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;
-
- 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;
+ 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.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.
+
+ //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;
+
+ 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;
-
- if( param == NULL || dev_handle == 0 )
- return FALSE;
-
- dev_mgr = param->dev_mgr;
-
- // 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;
- }
-
- // 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;
- }
-
- // 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;
-
- 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;
- }
-
- //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 );
-
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
-
- if( status == STATUS_SUCCESS )
- return TRUE;
-
- return FALSE;
- }
-
- return TRUE;
+ 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;
+
+ dev_mgr = param->dev_mgr;
+
+ // 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;
+ }
+
+ // 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;
+ }
+
+ // 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;
+
+ 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;
+ }
+
+ //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);
+
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+
+ if (status == STATUS_SUCCESS)
+ return TRUE;
+
+ return FALSE;
+ }
+
+ 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;
-
- 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;
+ PUSB_DEV_MANAGER dev_mgr;
+ DEV_HANDLE dev_handle;
+ PUMSS_CREATE_DATA cd;
+
+ 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;
}
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;
-
- USE_IRQL;
-
- if( dev_mgr == NULL || dev_handle == 0 )
- 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 );
-
- 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;
-
- 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:
-
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- usb_unlock_dev( pdev );
- return bret;
+ PUSB_EVENT pevent;
+ BOOL bret;
+ PUSB_DEV pdev;
+
+ USE_IRQL;
+
+ if (dev_mgr == NULL || dev_handle == 0)
+ 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);
+
+ 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;
+
+ 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:
+
+ 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;
-
- USE_IRQL;
-
- if( purb == NULL || context == NULL )
- return;
-
- 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;
- }
-
- 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 );
-
- 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;
-
- //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 );
-
- return;
+ DEV_HANDLE dev_handle;
+ PUSB_DEV_MANAGER dev_mgr;
+ PWORK_QUEUE_ITEM pwork_item;
+ PUSB_DRIVER pdriver;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+
+ USE_IRQL;
+
+ if (purb == NULL || context == NULL)
+ return;
+
+ 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;
+ }
+
+ 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);
+
+ 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;
+
+ //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);
+
+ 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;
-
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_DEV pdev;
-
- USE_IRQL;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "compdev_select_driver(): entering...\n" ) );
-
- dev_id = dev_handle >> 16;
-
- buf = usb_alloc_mem( NonPagedPool, 512 );
-
- 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;
-
- 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 ];
-
- 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;
- }
-
- 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( buf )
- {
- usb_free_mem( buf );
- buf = NULL;
- }
- return;
+ 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;
+
+ USE_IRQL;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): entering...\n"));
+
+ dev_id = dev_handle >> 16;
+
+ buf = usb_alloc_mem(NonPagedPool, 512);
+
+ 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;
+
+ 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];
+
+ 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;
+ }
+
+ 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 (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;
-
- 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;
+ PUSB_DEV pdev;
+ LONG i;
+ ULONG dev_id;
+ PUSB_DRIVER pdrv;
+ NTSTATUS status;
+
+ 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;
}
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;
-
- 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;
+ PUSB_DEV pdev;
+ LONG i;
+ ULONG dev_id;
+ PUSB_DRIVER pdrv;
+ NTSTATUS status;
+
+ 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;
}
// note:
#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;
-
- 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 );
-
- 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;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_DEV_MANAGER dev_mgr;
+ ULONG ctrl_code;
+ NTSTATUS status;
+ PDEVEXT_HEADER dev_hdr;
+
+ 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);
+
+ 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;
-
- 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;
-
- if( purb2->pirp == NULL )
- return;
-
- dev_mgr = ( PUSB_DEV_MANAGER )purb2->context;
-
- 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;
+ 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;
+
+ 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;
+ }
+
+ if (purb2->pirp == NULL)
+ return;
+
+ dev_mgr = (PUSB_DEV_MANAGER) purb2->context;
+
+ 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;
-
- 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;
-
- 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;
-
- irp->IoStatus.Information = 0;
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( LONG ) )
- {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
-
- 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.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 );
-
- 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 );
- }
-
- 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 );
- }
-
- 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;
- }
-
- 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 );
-
- 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 );
+ 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;
+
+ 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;
+
+ irp->IoStatus.Information = 0;
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+
+ 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.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);
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ 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);
+
+ 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 )
//declarations
typedef struct
{
- union
- {
- PUHCI_DEV uhci;
- PEHCI_DEV ehci;
- };
- PVOID context;
- ULONG ret;
+ union
+ {
+ PUHCI_DEV uhci;
+ PEHCI_DEV ehci;
+ };
+ PVOID context;
+ ULONG ret;
} SYNC_PARAM, *PSYNC_PARAM;
PDEVICE_OBJECT
-ehci_alloc(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-ULONG bus_addr,
-PUSB_DEV_MANAGER dev_mgr
-);
+ehci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr);
-BOOL
-ehci_init_schedule(
-PEHCI_DEV ehci,
-PADAPTER_OBJECT padapter
-);
+BOOL ehci_init_schedule(PEHCI_DEV ehci, PADAPTER_OBJECT padapter);
-BOOL
-ehci_release(
-PDEVICE_OBJECT pdev
-);
+BOOL ehci_release(PDEVICE_OBJECT pdev);
-static VOID
-ehci_stop(
-PEHCI_DEV ehci
-);
+static VOID ehci_stop(PEHCI_DEV ehci);
-BOOL
-ehci_destroy_schedule(
-PEHCI_DEV ehci
-);
+BOOL ehci_destroy_schedule(PEHCI_DEV ehci);
-BOOLEAN
-ehci_sync_insert_urb_schedule(
-PVOID context
-);
+BOOLEAN ehci_sync_insert_urb_schedule(PVOID context);
-VOID
-ehci_init_hcd_interface(
-PEHCI_DEV ehci
-);
+VOID ehci_init_hcd_interface(PEHCI_DEV ehci);
-NTSTATUS
-ehci_rh_submit_urb(
-PUSB_DEV rh,
-PURB purb
-);
+NTSTATUS ehci_rh_submit_urb(PUSB_DEV rh, PURB purb);
-NTSTATUS
-ehci_dispatch_irp(
-IN PDEVICE_OBJECT DeviceObject,
-IN PIRP irp
-);
+NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp);
-VOID
-ehci_generic_urb_completion(
-PURB purb,
-PVOID context
-);
+VOID ehci_generic_urb_completion(PURB purb, PVOID context);
-static NTSTATUS
-ehci_internal_submit_bulk(
-PEHCI_DEV ehci,
-PURB purb
-);
+static NTSTATUS ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb);
-static NTSTATUS
-ehci_internal_submit_int(
-PEHCI_DEV ehci,
-PURB purb
-);
+static NTSTATUS ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb);
-static NTSTATUS
-ehci_internal_submit_ctrl(
-PEHCI_DEV ehci,
-PURB purb
-);
+static NTSTATUS ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb);
-static NTSTATUS
-ehci_internal_submit_iso(
-PEHCI_DEV ehci,
-PURB purb
-);
+static NTSTATUS ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb);
-static ULONG
-ehci_scan_iso_error(
-PEHCI_DEV ehci,
-PURB purb
-);
+static ULONG ehci_scan_iso_error(PEHCI_DEV ehci, PURB purb);
-BOOL
-ehci_claim_bandwidth(
-PEHCI_DEV ehci,
-PURB purb,
-BOOL claim_bw
-);//true to claim band-width, false to free band-width
+BOOL ehci_claim_bandwidth(PEHCI_DEV ehci, PURB purb, BOOL claim_bw); //true to claim band-width, false to free band-width
-static VOID
-ehci_insert_bulk_schedule(
-PEHCI_DEV ehci,
-PURB purb
-);
+static VOID ehci_insert_bulk_schedule(PEHCI_DEV ehci, PURB purb);
#define ehci_insert_control_schedule ehci_insert_bulk_schedule
-static VOID
-ehci_insert_int_schedule(
-PEHCI_DEV ehci,
-PURB purb
-);
+static VOID ehci_insert_int_schedule(PEHCI_DEV ehci, PURB purb);
-static VOID
-ehci_insert_iso_schedule(
-PEHCI_DEV ehci,
-PURB purb
-);
+static VOID ehci_insert_iso_schedule(PEHCI_DEV ehci, PURB purb);
#define ehci_remove_control_from_schedule ehci_remove_bulk_from_schedule
-PDEVICE_OBJECT
-ehci_probe(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-PUSB_DEV_MANAGER dev_mgr
-);
+PDEVICE_OBJECT ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr);
-PDEVICE_OBJECT
-ehci_create_device(
-PDRIVER_OBJECT drvr_obj,
-PUSB_DEV_MANAGER dev_mgr
-);
+PDEVICE_OBJECT ehci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr);
-BOOL
-ehci_delete_device(
-PDEVICE_OBJECT pdev
-);
+BOOL ehci_delete_device(PDEVICE_OBJECT pdev);
-VOID
-ehci_get_capabilities(
-PEHCI_DEV ehci,
-PBYTE base
-);
+VOID ehci_get_capabilities(PEHCI_DEV ehci, PBYTE base);
-BOOLEAN
-ehci_isr(
-PKINTERRUPT interrupt,
-PVOID context
-);
+BOOLEAN ehci_isr(PKINTERRUPT interrupt, PVOID context);
-BOOL
-ehci_start(
-PHCD hcd
-);
+BOOL ehci_start(PHCD hcd);
-extern VOID
-rh_timer_svc_reset_port_completion(
-PUSB_DEV dev,
-PVOID context
-);
+extern VOID rh_timer_svc_reset_port_completion(PUSB_DEV dev, PVOID context);
-extern VOID
-rh_timer_svc_int_completion(
-PUSB_DEV dev,
-PVOID context
-);
+extern VOID rh_timer_svc_int_completion(PUSB_DEV dev, PVOID context);
-extern USB_DEV_MANAGER g_dev_mgr;
+extern USB_DEV_MANAGER g_dev_mgr;
#ifndef INCLUDE_EHCI
-ULONG debug_level = DBGLVL_MAXIMUM;
-PDRIVER_OBJECT usb_driver_obj = NULL;
+ULONG debug_level = DBGLVL_MAXIMUM;
+PDRIVER_OBJECT usb_driver_obj = NULL;
//pending endpoint pool funcs
VOID
-ehci_wait_ms(
-PEHCI_DEV ehci,
-LONG ms
-)
+ehci_wait_ms(PEHCI_DEV ehci, LONG ms)
{
LARGE_INTEGER lms;
- if( ms <= 0 )
- return;
+ if (ms <= 0)
+ return;
lms.QuadPart = -10 * ms;
- KeSetTimer( &ehci->reset_timer, lms, NULL );
+ KeSetTimer(&ehci->reset_timer, lms, NULL);
- KeWaitForSingleObject(
- &ehci->reset_timer,
- Executive,
- KernelMode,
- FALSE,
- NULL );
+ KeWaitForSingleObject(&ehci->reset_timer, Executive, KernelMode, FALSE, NULL);
- return;
+ return;
}
BOOL
-init_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-)
+init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
{
- int i;
- if( pool == NULL )
- return FALSE;
-
- pool->pending_endp_array = usb_alloc_mem( NonPagedPool, sizeof( UHCI_PENDING_ENDP ) * UHCI_MAX_PENDING_ENDPS );
- InitializeListHead( &pool->free_que );
- pool->free_count = 0;
- pool->total_count = UHCI_MAX_PENDING_ENDPS;
- KeInitializeSpinLock( &pool->pool_lock );
-
- for( i = 0; i < MAX_TIMER_SVCS; i++ )
- {
- free_pending_endp( pool, &pool->pending_endp_array[i] );
- }
+ int i;
+ if (pool == NULL)
+ return FALSE;
+
+ pool->pending_endp_array =
+ usb_alloc_mem(NonPagedPool, sizeof(UHCI_PENDING_ENDP) * UHCI_MAX_PENDING_ENDPS);
+ InitializeListHead(&pool->free_que);
+ pool->free_count = 0;
+ pool->total_count = UHCI_MAX_PENDING_ENDPS;
+ KeInitializeSpinLock(&pool->pool_lock);
+
+ for(i = 0; i < MAX_TIMER_SVCS; i++)
+ {
+ free_pending_endp(pool, &pool->pending_endp_array[i]);
+ }
- return TRUE;
+ return TRUE;
}
BOOL
-free_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-PUHCI_PENDING_ENDP pending_endp
-)
+free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp)
{
- if( pool == NULL || pending_endp == NULL )
- {
- return FALSE;
- }
-
- RtlZeroMemory( pending_endp, sizeof( UHCI_PENDING_ENDP ) );
- InsertTailList( &pool->free_que, (PLIST_ENTRY) &pending_endp->endp_link );
- pool->free_count++;
-
- return TRUE;
+ if (pool == NULL || pending_endp == NULL)
+ {
+ return FALSE;
+ }
+
+ RtlZeroMemory(pending_endp, sizeof(UHCI_PENDING_ENDP));
+ InsertTailList(&pool->free_que, (PLIST_ENTRY) & pending_endp->endp_link);
+ pool->free_count++;
+
+ return TRUE;
}
PUHCI_PENDING_ENDP
-alloc_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-LONG count)
+alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count)
{
- PUHCI_PENDING_ENDP new;
- if( pool == NULL || count != 1 )
- return NULL;
+ PUHCI_PENDING_ENDP new;
+ if (pool == NULL || count != 1)
+ return NULL;
- if( pool->free_count <= 0 )
- return NULL;
+ if (pool->free_count <= 0)
+ return NULL;
- new = ( PUHCI_PENDING_ENDP )RemoveHeadList( &pool->free_que );
- pool->free_count --;
- return new;
+ new = (PUHCI_PENDING_ENDP) RemoveHeadList(&pool->free_que);
+ pool->free_count--;
+ return new;
}
BOOL
-destroy_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-)
+destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- InitializeListHead( &pool->free_que );
- pool->free_count = pool->total_count = 0;
- usb_free_mem( pool->pending_endp_array );
- pool->pending_endp_array = NULL;
+ InitializeListHead(&pool->free_que);
+ pool->free_count = pool->total_count = 0;
+ usb_free_mem(pool->pending_endp_array);
+ pool->pending_endp_array = NULL;
- return TRUE;
+ return TRUE;
}
#else
#define ehci_wait_ms uhci_wait_ms
-extern VOID
-uhci_wait_ms(
-PEHCI_DEV ehci,
-LONG ms
-);
-
-extern BOOL
-init_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-);
-
-extern BOOL
-free_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-PUHCI_PENDING_ENDP pending_endp
-);
-
-extern PUHCI_PENDING_ENDP
-alloc_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-LONG count);
-
-extern BOOL
-destroy_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-);
+extern VOID uhci_wait_ms(PEHCI_DEV ehci, LONG ms);
+
+extern BOOL init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool);
+
+extern BOOL free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp);
+
+extern PUHCI_PENDING_ENDP alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count);
+
+extern BOOL destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool);
#endif
//end of pending endpoint pool funcs
static VOID
-ehci_cancel_pending_endp_urb(
-IN PVOID Parameter
-)
+ehci_cancel_pending_endp_urb(IN PVOID Parameter)
{
- PLIST_ENTRY abort_list;
- PUSB_DEV pdev;
- PURB purb;
- USE_IRQL;
-
- abort_list = ( PLIST_ENTRY )Parameter;
-
- if( abort_list == NULL )
- return;
-
- while( IsListEmpty( abort_list ) == FALSE )
- {
- //these devs are protected by purb's ref-count
- purb = ( PURB )RemoveHeadList( abort_list );
- pdev = purb->pdev;
- // purb->status is set when they are added to abort_list
-
- ehci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, FALSE );
- pdev->ref_count--;
- unlock_dev( pdev, FALSE );
- }
- usb_free_mem( abort_list );
- return;
+ PLIST_ENTRY abort_list;
+ PUSB_DEV pdev;
+ PURB purb;
+ USE_IRQL;
+
+ abort_list = (PLIST_ENTRY) Parameter;
+
+ if (abort_list == NULL)
+ return;
+
+ while (IsListEmpty(abort_list) == FALSE)
+ {
+ //these devs are protected by purb's ref-count
+ purb = (PURB) RemoveHeadList(abort_list);
+ pdev = purb->pdev;
+ // purb->status is set when they are added to abort_list
+
+ ehci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, FALSE);
+ pdev->ref_count--;
+ unlock_dev(pdev, FALSE);
+ }
+ usb_free_mem(abort_list);
+ return;
}
static BOOL
-ehci_process_pending_endp(
-PEHCI_DEV ehci
-)
+ehci_process_pending_endp(PEHCI_DEV ehci)
{
- PUSB_DEV pdev;
- LIST_ENTRY temp_list, abort_list;
- PLIST_ENTRY pthis;
- PURB purb;
- PUSB_ENDPOINT pendp;
- BOOL can_submit;
- PWORK_QUEUE_ITEM pwork_item;
- PLIST_ENTRY cancel_list;
- PUSB_DEV pparent;
- UCHAR port_idx;
- BOOL tt_needed;
- UCHAR hub_addr;
- PURB_HS_CONTEXT_CONTENT phcc;
- USE_IRQL;
-
- if( ehci == NULL )
- return FALSE;
-
- InitializeListHead( &temp_list );
- InitializeListHead( &abort_list );
-
- purb = NULL;
- ehci_dbg_print( DBGLVL_MEDIUM, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci ) );
-
- lock_pending_endp_list( &ehci->pending_endp_list_lock );
- while( IsListEmpty( &ehci->pending_endp_list ) == FALSE )
- {
-
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_process_pending_endp(): pending_endp_list=0x%x\n", \
- &ehci->pending_endp_list ) );
-
- tt_needed = FALSE;
- pthis = RemoveHeadList( &ehci->pending_endp_list );
- pendp = ( ( PUHCI_PENDING_ENDP )pthis )->pendp;
- pdev = dev_from_endp( pendp );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- //delegate to ehci_remove_device for remiving the purb queue on the endpoint
- continue;
- }
- if( ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )
- {
- // prepare split transaction
- unlock_dev( pdev, TRUE );
-
- // pparent won't be removed when pending_endp_list_lock is acquired.
- get_parent_hs_hub( pdev, pparent, port_idx );
-
- if( pparent == NULL )
- {
- TRAP();
- ehci_dbg_print( DBGLVL_MEDIUM, ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n" ) );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- continue;
- }
-
- if( hub_lock_tt( pparent, port_idx, ( UCHAR )endp_type( pendp ) ) == FALSE )
- {
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) != USB_DEV_STATE_ZOMB )
- {
- // reinsert the pending-endp to the list
- InsertTailList( &temp_list, pthis );
- unlock_dev( pdev, TRUE );
- }
- else
- {
- // delegate to ehci_remove_device for purb removal
- unlock_dev( pdev, TRUE );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- }
- continue;
- }
-
- // backup the hub address for future use
- hub_addr = pparent->dev_addr;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- hub_unlock_tt( pparent, port_idx, ( UCHAR )endp_type( pendp ) );
- continue;
- }
- tt_needed = TRUE;
- // go on processing
- }
-
- if( endp_state( pendp ) == USB_ENDP_FLAG_STALL )
- {
- while( IsListEmpty( &pendp->urb_list ) == FALSE )
- {
- purb = ( PURB )RemoveHeadList( &pendp->urb_list );
- purb->status = USB_STATUS_ENDPOINT_HALTED;
- InsertTailList( &abort_list, ( LIST_ENTRY* )purb );
- }
- InitializeListHead( &pendp->urb_list );
- unlock_dev( pdev, TRUE );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- if( tt_needed )
- hub_unlock_tt( pparent, port_idx, ( UCHAR )endp_type( pendp ) );
- continue;
- }
-
- if( IsListEmpty( &pendp->urb_list ) == FALSE )
- {
- purb = ( PURB )RemoveHeadList( &pendp->urb_list );
- ASSERT( purb );
- }
- else
- {
- InitializeListHead( &pendp->urb_list );
- unlock_dev( pdev, TRUE );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- if( tt_needed )
- hub_unlock_tt( pparent, port_idx, ( UCHAR )endp_type( pendp ) );
- continue;
- }
-
- if( tt_needed )
- {
- ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr = hub_addr;
- ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx = port_idx;
- }
-
- // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
- switch( endp_type( pendp ) )
- {
- case USB_ENDPOINT_XFER_BULK:
- {
- can_submit = ehci_internal_submit_bulk( ehci, purb );
- break;
- }
- case USB_ENDPOINT_XFER_CONTROL:
- {
- can_submit = ehci_internal_submit_ctrl( ehci, purb );
- break;
- }
- case USB_ENDPOINT_XFER_INT:
- {
- can_submit = ehci_internal_submit_int( ehci, purb );
- break;
- }
- case USB_ENDPOINT_XFER_ISOC:
- {
- can_submit = ehci_internal_submit_iso( ehci, purb );
- break;
- }
- }
-
- if( can_submit == STATUS_NO_MORE_ENTRIES )
- {
- //no enough bandwidth or tds
- InsertHeadList( &pendp->urb_list, ( PLIST_ENTRY )purb );
- InsertTailList( &temp_list, pthis );
- }
- else
- {
- // otherwise error or success
- free_pending_endp(
- &ehci->pending_endp_pool,
- struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
-
- if( can_submit != STATUS_SUCCESS )
- {
- //abort these URBs
- InsertTailList( &abort_list, ( LIST_ENTRY* )purb );
- purb->status = can_submit;
- }
- }
- unlock_dev( pdev, TRUE );
- if( can_submit != STATUS_SUCCESS && tt_needed )
- {
- hub_unlock_tt( pparent, port_idx, ( UCHAR )endp_type( pendp ) );
- }
- }
-
- if( IsListEmpty( &temp_list ) == FALSE )
- {
- //re-append them to the pending_endp_list
- ListFirst( &temp_list, pthis );
- RemoveEntryList( &temp_list );
- MergeList( &ehci->pending_endp_list, pthis );
- }
- unlock_pending_endp_list( &ehci->pending_endp_list_lock );
-
- if( IsListEmpty( &abort_list ) == FALSE )
- {
- PLIST_ENTRY pthis;
- cancel_list = ( PLIST_ENTRY )usb_alloc_mem( NonPagedPool, sizeof( WORK_QUEUE_ITEM ) + sizeof( LIST_ENTRY ) );
- ASSERT( cancel_list );
-
- ListFirst( &abort_list, pthis );
- RemoveEntryList( &abort_list );
- InsertTailList( pthis, cancel_list );
-
- pwork_item = ( PWORK_QUEUE_ITEM )&cancel_list[ 1 ];
-
- // we do not need to worry the ehci_cancel_pending_endp_urb running when the
- // driver is unloading since purb-reference count will prevent the dev_mgr to
- // quit till all the reference count to the dev drop to zero.
- ExInitializeWorkItem( pwork_item, ehci_cancel_pending_endp_urb, ( PVOID )cancel_list );
- ExQueueWorkItem( pwork_item, DelayedWorkQueue );
- }
- return TRUE;
+ PUSB_DEV pdev;
+ LIST_ENTRY temp_list, abort_list;
+ PLIST_ENTRY pthis;
+ PURB purb;
+ PUSB_ENDPOINT pendp;
+ BOOL can_submit;
+ PWORK_QUEUE_ITEM pwork_item;
+ PLIST_ENTRY cancel_list;
+ PUSB_DEV pparent;
+ UCHAR port_idx;
+ BOOL tt_needed;
+ UCHAR hub_addr;
+ PURB_HS_CONTEXT_CONTENT phcc;
+ USE_IRQL;
+
+ if (ehci == NULL)
+ return FALSE;
+
+ InitializeListHead(&temp_list);
+ InitializeListHead(&abort_list);
+
+ purb = NULL;
+ ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci));
+
+ lock_pending_endp_list(&ehci->pending_endp_list_lock);
+ while (IsListEmpty(&ehci->pending_endp_list) == FALSE)
+ {
+
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_process_pending_endp(): pending_endp_list=0x%x\n",
+ &ehci->pending_endp_list));
+
+ tt_needed = FALSE;
+ pthis = RemoveHeadList(&ehci->pending_endp_list);
+ pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp;
+ pdev = dev_from_endp(pendp);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ //delegate to ehci_remove_device for remiving the purb queue on the endpoint
+ continue;
+ }
+ if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
+ {
+ // prepare split transaction
+ unlock_dev(pdev, TRUE);
+
+ // pparent won't be removed when pending_endp_list_lock is acquired.
+ get_parent_hs_hub(pdev, pparent, port_idx);
+
+ if (pparent == NULL)
+ {
+ TRAP();
+ ehci_dbg_print(DBGLVL_MEDIUM,
+ ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n"));
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ continue;
+ }
+
+ if (hub_lock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)) == FALSE)
+ {
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
+ {
+ // reinsert the pending-endp to the list
+ InsertTailList(&temp_list, pthis);
+ unlock_dev(pdev, TRUE);
+ }
+ else
+ {
+ // delegate to ehci_remove_device for purb removal
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&ehci->pending_endp_pool,
+ struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ }
+ continue;
+ }
+
+ // backup the hub address for future use
+ hub_addr = pparent->dev_addr;
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
+ continue;
+ }
+ tt_needed = TRUE;
+ // go on processing
+ }
+
+ if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
+ {
+ while (IsListEmpty(&pendp->urb_list) == FALSE)
+ {
+ purb = (PURB) RemoveHeadList(&pendp->urb_list);
+ purb->status = USB_STATUS_ENDPOINT_HALTED;
+ InsertTailList(&abort_list, (LIST_ENTRY *) purb);
+ }
+ InitializeListHead(&pendp->urb_list);
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ if (tt_needed)
+ hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
+ continue;
+ }
+
+ if (IsListEmpty(&pendp->urb_list) == FALSE)
+ {
+ purb = (PURB) RemoveHeadList(&pendp->urb_list);
+ ASSERT(purb);
+ }
+ else
+ {
+ InitializeListHead(&pendp->urb_list);
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ if (tt_needed)
+ hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
+ continue;
+ }
+
+ if (tt_needed)
+ {
+ ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr = hub_addr;
+ ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx = port_idx;
+ }
+
+ // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
+ switch (endp_type(pendp))
+ {
+ case USB_ENDPOINT_XFER_BULK:
+ {
+ can_submit = ehci_internal_submit_bulk(ehci, purb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ can_submit = ehci_internal_submit_ctrl(ehci, purb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
+ can_submit = ehci_internal_submit_int(ehci, purb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_ISOC:
+ {
+ can_submit = ehci_internal_submit_iso(ehci, purb);
+ break;
+ }
+ }
+
+ if (can_submit == STATUS_NO_MORE_ENTRIES)
+ {
+ //no enough bandwidth or tds
+ InsertHeadList(&pendp->urb_list, (PLIST_ENTRY) purb);
+ InsertTailList(&temp_list, pthis);
+ }
+ else
+ {
+ // otherwise error or success
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+
+ if (can_submit != STATUS_SUCCESS)
+ {
+ //abort these URBs
+ InsertTailList(&abort_list, (LIST_ENTRY *) purb);
+ purb->status = can_submit;
+ }
+ }
+ unlock_dev(pdev, TRUE);
+ if (can_submit != STATUS_SUCCESS && tt_needed)
+ {
+ hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
+ }
+ }
+
+ if (IsListEmpty(&temp_list) == FALSE)
+ {
+ //re-append them to the pending_endp_list
+ ListFirst(&temp_list, pthis);
+ RemoveEntryList(&temp_list);
+ MergeList(&ehci->pending_endp_list, pthis);
+ }
+ unlock_pending_endp_list(&ehci->pending_endp_list_lock);
+
+ if (IsListEmpty(&abort_list) == FALSE)
+ {
+ PLIST_ENTRY pthis;
+ cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY));
+ ASSERT(cancel_list);
+
+ ListFirst(&abort_list, pthis);
+ RemoveEntryList(&abort_list);
+ InsertTailList(pthis, cancel_list);
+
+ pwork_item = (PWORK_QUEUE_ITEM) & cancel_list[1];
+
+ // we do not need to worry the ehci_cancel_pending_endp_urb running when the
+ // driver is unloading since purb-reference count will prevent the dev_mgr to
+ // quit till all the reference count to the dev drop to zero.
+ ExInitializeWorkItem(pwork_item, ehci_cancel_pending_endp_urb, (PVOID) cancel_list);
+ ExQueueWorkItem(pwork_item, DelayedWorkQueue);
+ }
+ return TRUE;
}
BOOL
-ehci_submit_urb(
-PEHCI_DEV ehci,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
+ehci_submit_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- int i;
- PLIST_ENTRY pthis, pnext;
- PUHCI_PENDING_ENDP pending_endp;
- NTSTATUS status;
- USE_IRQL;
-
- if( ehci == NULL )
- return STATUS_INVALID_PARAMETER;
-
- if( pdev == NULL || pendp == NULL || purb == NULL )
- {
- // give a chance to those pending urb, especially for clearing hub tt
- ehci_process_pending_endp( ehci );
- return STATUS_INVALID_PARAMETER;
- }
-
- lock_pending_endp_list( &ehci->pending_endp_list_lock );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- goto LBL_OUT;
- }
-
- if( dev_class( pdev ) == USB_DEV_CLASS_ROOT_HUB )
- {
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &ehci->pending_endp_list_lock );
- status = ehci_rh_submit_urb( pdev, purb );
- return status;
- }
-
- if( pendp )
- purb->pendp = pendp;
- else
- purb->pendp = &pdev->default_endp;
-
- if( dev_from_endp( purb->pendp ) != pdev )
- {
- status = purb->status = STATUS_INVALID_PARAMETER;
- goto LBL_OUT;
- }
-
- if( endp_state( purb->pendp ) == USB_ENDP_FLAG_STALL )
- {
- status = purb->status = USB_STATUS_ENDPOINT_HALTED;
- goto LBL_OUT;
- }
-
- if( ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )
- {
- // wait one ms
- usb_wait_ms_dpc( 1 );
- }
-
- purb->pdev = pdev;
- purb->rest_bytes = purb->data_length;
-
- if( endp_type( purb->pendp ) == USB_ENDPOINT_XFER_BULK )
- purb->bytes_to_transfer =
- ( purb->data_length > EHCI_MAX_SIZE_TRANSFER ?
- EHCI_MAX_SIZE_TRANSFER : purb->data_length ); //multiple transfer for large data block
- else
- purb->bytes_to_transfer = purb->data_length;
-
- ehci_dbg_print( DBGLVL_MEDIUM, ( "ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer ) );
-
- purb->bytes_transfered = 0;
- InitializeListHead( &purb->trasac_list );
- purb->last_finished_td = &purb->trasac_list;
- purb->flags &= ~( URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL );
- purb->flags |= URB_FLAG_STATE_PENDING;
-
-
- i = IsListEmpty( &pendp->urb_list );
- InsertTailList( &pendp->urb_list, &purb->urb_link );
-
- pdev->ref_count ++; //for purb reference
-
- if( i == FALSE )
- {
- //there is purb pending, simply queue it and return
- status = purb->status = STATUS_PENDING;
- goto LBL_OUT;
- }
- else if( usb_endp_busy_count( purb->pendp )
- && endp_type( purb->pendp) != USB_ENDPOINT_XFER_ISOC )
- {
+ int i;
+ PLIST_ENTRY pthis, pnext;
+ PUHCI_PENDING_ENDP pending_endp;
+ NTSTATUS status;
+ USE_IRQL;
+
+ if (ehci == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (pdev == NULL || pendp == NULL || purb == NULL)
+ {
+ // give a chance to those pending urb, especially for clearing hub tt
+ ehci_process_pending_endp(ehci);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ lock_pending_endp_list(&ehci->pending_endp_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ goto LBL_OUT;
+ }
+
+ if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB)
+ {
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&ehci->pending_endp_list_lock);
+ status = ehci_rh_submit_urb(pdev, purb);
+ return status;
+ }
+
+ if (pendp)
+ purb->pendp = pendp;
+ else
+ purb->pendp = &pdev->default_endp;
+
+ if (dev_from_endp(purb->pendp) != pdev)
+ {
+ status = purb->status = STATUS_INVALID_PARAMETER;
+ goto LBL_OUT;
+ }
+
+ if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL)
+ {
+ status = purb->status = USB_STATUS_ENDPOINT_HALTED;
+ goto LBL_OUT;
+ }
+
+ if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
+ {
+ // wait one ms
+ usb_wait_ms_dpc(1);
+ }
+
+ purb->pdev = pdev;
+ purb->rest_bytes = purb->data_length;
+
+ if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK)
+ purb->bytes_to_transfer = (purb->data_length > EHCI_MAX_SIZE_TRANSFER ? EHCI_MAX_SIZE_TRANSFER : purb->data_length); //multiple transfer for large data block
+ else
+ purb->bytes_to_transfer = purb->data_length;
+
+ ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer));
+
+ purb->bytes_transfered = 0;
+ InitializeListHead(&purb->trasac_list);
+ purb->last_finished_td = &purb->trasac_list;
+ purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL);
+ purb->flags |= URB_FLAG_STATE_PENDING;
+
+
+ i = IsListEmpty(&pendp->urb_list);
+ InsertTailList(&pendp->urb_list, &purb->urb_link);
+
+ pdev->ref_count++; //for purb reference
+
+ if (i == FALSE)
+ {
+ //there is purb pending, simply queue it and return
+ status = purb->status = STATUS_PENDING;
+ goto LBL_OUT;
+ }
+ else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC)
+ {
//
- //No purb waiting but purb overlap not allowed,
- //so leave it in queue and return, will be scheduled
- //later
- //
- status = purb->status = STATUS_PENDING;
- goto LBL_OUT;
- }
-
- pending_endp = alloc_pending_endp( &ehci->pending_endp_pool, 1 );
- if( pending_endp == NULL )
- {
- //panic
- status = purb->status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT2;
- }
-
- pending_endp->pendp = purb->pendp;
- InsertTailList( &ehci->pending_endp_list, ( PLIST_ENTRY )pending_endp );
-
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &ehci->pending_endp_list_lock );
-
- ehci_process_pending_endp( ehci );
- return STATUS_PENDING;
-
-LBL_OUT2:
- pdev->ref_count --;
- RemoveEntryList( ( PLIST_ENTRY )purb );
-
-LBL_OUT:
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &ehci->pending_endp_list_lock );
- ehci_process_pending_endp( ehci );
- return status;
+ //No purb waiting but purb overlap not allowed,
+ //so leave it in queue and return, will be scheduled
+ //later
+ //
+ status = purb->status = STATUS_PENDING;
+ goto LBL_OUT;
+ }
+
+ pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1);
+ if (pending_endp == NULL)
+ {
+ //panic
+ status = purb->status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT2;
+ }
+
+ pending_endp->pendp = purb->pendp;
+ InsertTailList(&ehci->pending_endp_list, (PLIST_ENTRY) pending_endp);
+
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&ehci->pending_endp_list_lock);
+
+ ehci_process_pending_endp(ehci);
+ return STATUS_PENDING;
+
+ LBL_OUT2:
+ pdev->ref_count--;
+ RemoveEntryList((PLIST_ENTRY) purb);
+
+ LBL_OUT:
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&ehci->pending_endp_list_lock);
+ ehci_process_pending_endp(ehci);
+ return status;
}
static NTSTATUS
-ehci_set_error_code(
-PURB purb,
-ULONG raw_status
-)
+ehci_set_error_code(PURB purb, ULONG raw_status)
{
- PURB_HS_PIPE_CONTENT pipe_content;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
-
- //test if the purb is canceled
- if( purb->flags & URB_FLAG_FORCE_CANCEL )
- {
- purb->status = STATUS_CANCELLED;
- }
- else if( raw_status == 0 )
- purb->status = STATUS_SUCCESS;
-
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_INT ||
- pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
- pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL )
- {
-
- if( raw_status & QTD_STS_BABBLE )
- purb->status = USB_STATUS_DATA_OVERRUN;
-
- else if( raw_status & QTD_STS_HALT )
- purb->status = USB_STATUS_ENDPOINT_HALTED;
-
- else if( raw_status & QTD_STS_DBE )
- purb->status = USB_STATUS_BUFFER_OVERRUN;
-
- else if( raw_status & QTD_STS_XACT )
- purb->status = USB_STATUS_CRC; // crc is included in xact err.
-
- else if( raw_status & QTD_STS_MMF )
- purb->status = USB_STATUS_BTSTUFF;
-
- else
- purb->status = STATUS_UNSUCCESSFUL;
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC )
- {
- if( pipe_content->speed_high )
- {
- if( raw_status & ITD_STS_BUFERR )
- purb->status = USB_STATUS_BUFFER_OVERRUN;
-
- else if( raw_status & ITD_STS_BABBLE )
- purb->status = USB_STATUS_BABBLE_DETECTED;
-
- else if( raw_status & ITD_STS_XACTERR ) // Xact Err
- purb->status = USB_STATUS_CRC;
-
- else
- purb->status = STATUS_UNSUCCESSFUL;
-
- }
- else
- {
- if( raw_status & SITD_STS_ERR ) // ERR is received from hub's tt
- purb->status = USB_STATUS_ERROR;
-
- else if( raw_status & SITD_STS_DBE )
- purb->status = USB_STATUS_BUFFER_OVERRUN;
-
- else if( raw_status & SITD_STS_BABBLE )
- purb->status = USB_STATUS_BABBLE_DETECTED;
-
- else if( raw_status & SITD_STS_XACTERR ) // Xact Error
- purb->status = USB_STATUS_CRC;
-
- else if( raw_status & SITD_STS_MISSFRM ) // missing microframe
- purb->status = USB_STATUS_DATA_TOGGLE_MISMATCH;
-
- else
- purb->status = STATUS_UNSUCCESSFUL;
- }
- }
- if( purb->status != STATUS_SUCCESS )
- {
- hcd_dbg_print( DBGLVL_MEDIUM, ( "ehci_set_error_code(): error status 0x%x\n", raw_status ) );
- }
- return purb->status;
+ PURB_HS_PIPE_CONTENT pipe_content;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+
+ //test if the purb is canceled
+ if (purb->flags & URB_FLAG_FORCE_CANCEL)
+ {
+ purb->status = STATUS_CANCELLED;
+ }
+ else if (raw_status == 0)
+ purb->status = STATUS_SUCCESS;
+
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL)
+ {
+
+ if (raw_status & QTD_STS_BABBLE)
+ purb->status = USB_STATUS_DATA_OVERRUN;
+
+ else if (raw_status & QTD_STS_HALT)
+ purb->status = USB_STATUS_ENDPOINT_HALTED;
+
+ else if (raw_status & QTD_STS_DBE)
+ purb->status = USB_STATUS_BUFFER_OVERRUN;
+
+ else if (raw_status & QTD_STS_XACT)
+ purb->status = USB_STATUS_CRC; // crc is included in xact err.
+
+ else if (raw_status & QTD_STS_MMF)
+ purb->status = USB_STATUS_BTSTUFF;
+
+ else
+ purb->status = STATUS_UNSUCCESSFUL;
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC)
+ {
+ if (pipe_content->speed_high)
+ {
+ if (raw_status & ITD_STS_BUFERR)
+ purb->status = USB_STATUS_BUFFER_OVERRUN;
+
+ else if (raw_status & ITD_STS_BABBLE)
+ purb->status = USB_STATUS_BABBLE_DETECTED;
+
+ else if (raw_status & ITD_STS_XACTERR) // Xact Err
+ purb->status = USB_STATUS_CRC;
+
+ else
+ purb->status = STATUS_UNSUCCESSFUL;
+
+ }
+ else
+ {
+ if (raw_status & SITD_STS_ERR) // ERR is received from hub's tt
+ purb->status = USB_STATUS_ERROR;
+
+ else if (raw_status & SITD_STS_DBE)
+ purb->status = USB_STATUS_BUFFER_OVERRUN;
+
+ else if (raw_status & SITD_STS_BABBLE)
+ purb->status = USB_STATUS_BABBLE_DETECTED;
+
+ else if (raw_status & SITD_STS_XACTERR) // Xact Error
+ purb->status = USB_STATUS_CRC;
+
+ else if (raw_status & SITD_STS_MISSFRM) // missing microframe
+ purb->status = USB_STATUS_DATA_TOGGLE_MISMATCH;
+
+ else
+ purb->status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ if (purb->status != STATUS_SUCCESS)
+ {
+ hcd_dbg_print(DBGLVL_MEDIUM, ("ehci_set_error_code(): error status 0x%x\n", raw_status));
+ }
+ return purb->status;
}
BOOLEAN
-ehci_sync_remove_urb_finished(
-PVOID context
-)
+ehci_sync_remove_urb_finished(PVOID context)
{
- PEHCI_DEV ehci;
- PLIST_ENTRY pthis, pnext, ptemp;
- PURB purb;
- PSYNC_PARAM pparam;
-
- pparam = ( PSYNC_PARAM )context;
- ehci = pparam->ehci;
- ptemp = ( PLIST_ENTRY )pparam->context;
-
- if( ehci == NULL )
- {
- return ( UCHAR )pparam->ret = FALSE;
- }
-
- ListFirst( &ehci->urb_list, pthis );
- while( pthis )
- {
+ PEHCI_DEV ehci;
+ PLIST_ENTRY pthis, pnext, ptemp;
+ PURB purb;
+ PSYNC_PARAM pparam;
+
+ pparam = (PSYNC_PARAM) context;
+ ehci = pparam->ehci;
+ ptemp = (PLIST_ENTRY) pparam->context;
+
+ if (ehci == NULL)
+ {
+ return (UCHAR) pparam->ret = FALSE;
+ }
+
+ ListFirst(&ehci->urb_list, pthis);
+ while (pthis)
+ {
//remove urbs not in the schedule
- ListNext( &ehci->urb_list, pthis, pnext );
- purb = ( PURB )pthis;
+ ListNext(&ehci->urb_list, pthis, pnext);
+ purb = (PURB) pthis;
- if( ( purb->flags & URB_FLAG_IN_SCHEDULE ) == 0 )
- {
+ if ((purb->flags & URB_FLAG_IN_SCHEDULE) == 0)
+ {
//finished or canceled( not applied for split bulk ).
- RemoveEntryList( pthis );
- InsertTailList( ptemp, pthis );
- }
- pthis = pnext;
- }
- pparam->ret = TRUE;
- return ( UCHAR )TRUE;
+ RemoveEntryList(pthis);
+ InsertTailList(ptemp, pthis);
+ }
+ pthis = pnext;
+ }
+ pparam->ret = TRUE;
+ return (UCHAR) TRUE;
}
VOID
-ehci_dpc_callback(
-PKDPC dpc,
-PVOID context,
-PVOID sysarg1,
-PVOID sysarg2
-)
+ehci_dpc_callback(PKDPC dpc, PVOID context, PVOID sysarg1, PVOID sysarg2)
{
- PEHCI_DEV ehci;
-
- LIST_HEAD temp_list;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- PEHCI_QH pqh;
- PEHCI_QTD ptd;
- PUHCI_PENDING_ENDP pending_endp;
- PEHCI_FSTN pfstn;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
-
- BOOL finished;
- LONG i;
- ULONG ehci_status, urb_status, toggle = 0;
-
- SYNC_PARAM sync_param;
- UCHAR ep_type;
- USE_IRQL;
-
- ehci = ( PEHCI_DEV ) context;
- if( ehci == NULL )
- return;
-
- ehci_status = ( ULONG )sysarg1;
-
- InitializeListHead( &temp_list );
-
- sync_param.ehci = ehci;
- sync_param.context = ( PVOID )&temp_list;
-
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci ) );
- //remove finished purb from ehci's purb-list
- KeSynchronizeExecution( ehci->pdev_ext->ehci_int, ehci_sync_remove_urb_finished, &sync_param );
+ PEHCI_DEV ehci;
+
+ LIST_HEAD temp_list;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ PEHCI_QH pqh;
+ PEHCI_QTD ptd;
+ PUHCI_PENDING_ENDP pending_endp;
+ PEHCI_FSTN pfstn;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+
+ BOOL finished;
+ LONG i;
+ ULONG ehci_status, urb_status, toggle = 0;
+
+ SYNC_PARAM sync_param;
+ UCHAR ep_type;
+ USE_IRQL;
+
+ ehci = (PEHCI_DEV) context;
+ if (ehci == NULL)
+ return;
+
+ ehci_status = (ULONG) sysarg1;
+
+ InitializeListHead(&temp_list);
+
+ sync_param.ehci = ehci;
+ sync_param.context = (PVOID) & temp_list;
+
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci));
+ //remove finished purb from ehci's purb-list
+ KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_remove_urb_finished, &sync_param);
//release resources( itds, sitds, fstns, tds, and qhs ) allocated for the purb
- while( IsListEmpty( &temp_list ) == FALSE )
- {
- //not in any public queue, if do not access into dev, no race
+ while (IsListEmpty(&temp_list) == FALSE)
+ {
+ //not in any public queue, if do not access into dev, no race
//condition will occur
- purb = ( PURB ) RemoveHeadList( &temp_list );
- urb_status = purb->status;
- ep_type = endp_type( purb->pendp );
-
- if( ep_type == USB_ENDPOINT_XFER_ISOC )
- {
- // collect error for iso transfer
- urb_status = ehci_scan_iso_error( ehci, purb );
- }
-
- //the only place we do not use this lock on non-pending-endp-list data
- KeAcquireSpinLockAtDpcLevel( &ehci->pending_endp_list_lock );
- while( IsListEmpty( &purb->trasac_list ) == FALSE )
- {
- UCHAR em_type;
- pthis = RemoveHeadList( &purb->trasac_list );
- em_type = ( UCHAR )elem_type( pthis, TRUE );
-
- if( em_type == INIT_LIST_FLAG_QH )
- {
- pqh = qh_from_list_entry( pthis );
- elem_safe_free( pthis, TRUE );
- }
- else
- {
- //must be an itd, sitd chain
- InsertHeadList( &purb->trasac_list, pthis );
- for( i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++ )
- {
- PEHCI_QTD_CONTENT ptdc;
- PEHCI_ITD_CONTENT pitdc;
- PEHCI_SITD_CONTENT psitdc;
-
- em_type = ( UCHAR )elem_type( pthis, TRUE );
-
- // accumulate data transfered in tds
- if( em_type == INIT_LIST_FLAG_QTD )
- {
- ptd = qtd_from_list_entry( pthis );
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
- if( ( ptdc->status & QTD_STS_ACTIVE ) == 0 && ( ( ptdc->status & QTD_ANY_ERROR ) == 0 ) )
- purb->bytes_transfered += ptd->bytes_to_transfer;
- }
- else if( em_type == INIT_LIST_FLAG_ITD )
- {
- int j;
- pitdc = ( PEHCI_ITD_CONTENT )itd_from_list_entry( pthis );
- for( j = 0; j < 8; j++ )
- {
- if( ( pitdc->status_slot[ j ].status & ITD_STS_ACTIVE ) == 0 && ( pitdc->status_slot[ j ].status & ITD_ANY_ERROR ) == 0 )
- purb->bytes_transfered += ptdc->bytes_to_transfer;
- }
- }
- else if( em_type == INIT_LIST_FLAG_SITD )
- {
- psitdc = ( PEHCI_SITD_CONTENT )sitd_from_list_entry( pthis );
- if( ( psitdc->status & SITD_STS_ACTIVE ) == 0 && ( psitdc->status & SITD_ANY_ERROR ) == 0 )
- purb->bytes_transfered += ptdc->bytes_to_transfer;
- }
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
-
- // check to see if an fstn is there
- ListFirstPrev( &purb->trasac_list, pthis );
- if( elem_type( pthis, TRUE ) == INIT_LIST_FLAG_FSTN )
- {
- RemoveEntryList( pthis );
- elem_safe_free( pthis, TRUE );
- }
-
- ListFirst( &purb->trasac_list, pthis );
- RemoveEntryList( &purb->trasac_list );
-
- // free the tds
- elem_safe_free( pthis, FALSE );
-
- //termination condition
- InitializeListHead( &purb->trasac_list );
- purb->last_finished_td = NULL;
- }
- }
-
- if( ep_type == USB_ENDPOINT_XFER_ISOC
- || ep_type == USB_ENDPOINT_XFER_INT )
- ehci_claim_bandwidth( ehci, purb, FALSE); //release band-width
-
- KeReleaseSpinLockFromDpcLevel( &ehci->pending_endp_list_lock );
-
- ehci_set_error_code( purb, urb_status );
-
- pdev = dev_from_endp( purb->pendp );
- pendp = purb->pendp;
-
- // perform clear tt buffer if error on full/low bulk/control pipe
- if( ep_type == USB_ENDPOINT_XFER_BULK || ep_type == USB_ENDPOINT_XFER_CONTROL )
- {
- PURB_HS_PIPE_CONTENT pipe_content;
- PUSB_DEV phub;
- UCHAR port_idx;
-
- get_parent_hs_hub( pdev, phub, port_idx );
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
-
- if( pipe_content->speed_high == 0 && purb->status != STATUS_SUCCESS )
- {
- // lets schedule an event to clear the tt buffer
- hub_post_clear_tt_event( phub, port_idx, purb->pipe );
- }
- else if( pipe_content->speed_high == 0 )
- {
- if( phub == NULL )
- TRAP();
- else
- {
- // release tt if no error
- hub_unlock_tt( phub, ( UCHAR )port_idx, ( UCHAR )pipe_content->trans_type );
- }
- }
- }
-
- finished = TRUE;
-
- //since the ref_count for the purb is not released, we can safely have one
+ purb = (PURB) RemoveHeadList(&temp_list);
+ urb_status = purb->status;
+ ep_type = endp_type(purb->pendp);
+
+ if (ep_type == USB_ENDPOINT_XFER_ISOC)
+ {
+ // collect error for iso transfer
+ urb_status = ehci_scan_iso_error(ehci, purb);
+ }
+
+ //the only place we do not use this lock on non-pending-endp-list data
+ KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock);
+ while (IsListEmpty(&purb->trasac_list) == FALSE)
+ {
+ UCHAR em_type;
+ pthis = RemoveHeadList(&purb->trasac_list);
+ em_type = (UCHAR) elem_type(pthis, TRUE);
+
+ if (em_type == INIT_LIST_FLAG_QH)
+ {
+ pqh = qh_from_list_entry(pthis);
+ elem_safe_free(pthis, TRUE);
+ }
+ else
+ {
+ //must be an itd, sitd chain
+ InsertHeadList(&purb->trasac_list, pthis);
+ for(i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++)
+ {
+ PEHCI_QTD_CONTENT ptdc;
+ PEHCI_ITD_CONTENT pitdc;
+ PEHCI_SITD_CONTENT psitdc;
+
+ em_type = (UCHAR) elem_type(pthis, TRUE);
+
+ // accumulate data transfered in tds
+ if (em_type == INIT_LIST_FLAG_QTD)
+ {
+ ptd = qtd_from_list_entry(pthis);
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+ if ((ptdc->status & QTD_STS_ACTIVE) == 0 && ((ptdc->status & QTD_ANY_ERROR) == 0))
+ purb->bytes_transfered += ptd->bytes_to_transfer;
+ }
+ else if (em_type == INIT_LIST_FLAG_ITD)
+ {
+ int j;
+ pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis);
+ for(j = 0; j < 8; j++)
+ {
+ if ((pitdc->status_slot[j].status & ITD_STS_ACTIVE) == 0
+ && (pitdc->status_slot[j].status & ITD_ANY_ERROR) == 0)
+ purb->bytes_transfered += ptdc->bytes_to_transfer;
+ }
+ }
+ else if (em_type == INIT_LIST_FLAG_SITD)
+ {
+ psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis);
+ if ((psitdc->status & SITD_STS_ACTIVE) == 0 && (psitdc->status & SITD_ANY_ERROR) == 0)
+ purb->bytes_transfered += ptdc->bytes_to_transfer;
+ }
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ // check to see if an fstn is there
+ ListFirstPrev(&purb->trasac_list, pthis);
+ if (elem_type(pthis, TRUE) == INIT_LIST_FLAG_FSTN)
+ {
+ RemoveEntryList(pthis);
+ elem_safe_free(pthis, TRUE);
+ }
+
+ ListFirst(&purb->trasac_list, pthis);
+ RemoveEntryList(&purb->trasac_list);
+
+ // free the tds
+ elem_safe_free(pthis, FALSE);
+
+ //termination condition
+ InitializeListHead(&purb->trasac_list);
+ purb->last_finished_td = NULL;
+ }
+ }
+
+ if (ep_type == USB_ENDPOINT_XFER_ISOC || ep_type == USB_ENDPOINT_XFER_INT)
+ ehci_claim_bandwidth(ehci, purb, FALSE); //release band-width
+
+ KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
+
+ ehci_set_error_code(purb, urb_status);
+
+ pdev = dev_from_endp(purb->pendp);
+ pendp = purb->pendp;
+
+ // perform clear tt buffer if error on full/low bulk/control pipe
+ if (ep_type == USB_ENDPOINT_XFER_BULK || ep_type == USB_ENDPOINT_XFER_CONTROL)
+ {
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PUSB_DEV phub;
+ UCHAR port_idx;
+
+ get_parent_hs_hub(pdev, phub, port_idx);
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+
+ if (pipe_content->speed_high == 0 && purb->status != STATUS_SUCCESS)
+ {
+ // lets schedule an event to clear the tt buffer
+ hub_post_clear_tt_event(phub, port_idx, purb->pipe);
+ }
+ else if (pipe_content->speed_high == 0)
+ {
+ if (phub == NULL)
+ TRAP();
+ else
+ {
+ // release tt if no error
+ hub_unlock_tt(phub, (UCHAR) port_idx, (UCHAR) pipe_content->trans_type);
+ }
+ }
+ }
+
+ finished = TRUE;
+
+ //since the ref_count for the purb is not released, we can safely have one
//pointer to dev
-
- if( purb->status == USB_STATUS_BABBLE_DETECTED )
- {
- usb_dbg_print( DBGLVL_MEDIUM, ( "ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n" ) );
- // ehci_start( ehci );
- }
-
- if ( ehci_status & STS_HALT ) //&& !ehci->is_suspended
- {
- ehci_start( &ehci->hcd_interf );
- }
-
- //this will let the new request in ehci_generic_urb_completion to this endp
- //be processed rather than queued in the pending_endp_list
- lock_dev( pdev, TRUE );
- usb_endp_busy_count_dec( pendp );
- unlock_dev( pdev, TRUE );
-
- if( usb_success( purb->status ) == FALSE )
- {
- // set error code and complete the purb and purb is invalid from this point
- ehci_generic_urb_completion( purb, purb->context );
- }
- else
- {
- if( ep_type == USB_ENDPOINT_XFER_BULK )
- {
- purb->rest_bytes -= purb->bytes_transfered;
- if( purb->rest_bytes )
- {
- finished = FALSE;
- }
- else
- {
- ehci_generic_urb_completion( purb, purb->context );
- }
- }
- else
- {
- ehci_generic_urb_completion( purb, purb->context );
- // DbgBreakPoint();
- //purb is now invalid
- }
- }
-
- KeAcquireSpinLockAtDpcLevel( &ehci->pending_endp_list_lock );
- lock_dev( pdev, TRUE );
-
- if( finished )
- pdev->ref_count--;
-
- if( urb_status &&
- ( ( ep_type == USB_ENDPOINT_XFER_BULK ) ||
- ( ep_type == USB_ENDPOINT_XFER_INT ) ) )
- {
- // error on int or bulk pipe, cleared in usb_reset_pipe_completion
- pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
- pendp->flags |= USB_ENDP_FLAG_STALL;
- }
-
- if( dev_state( pdev )== USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &ehci->pending_endp_list_lock );
- if( finished == FALSE )
- {
-
- purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- ehci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, TRUE );
- pdev->ref_count--;
- unlock_dev( pdev, TRUE);
- }
- continue;
- }
-
- if( finished && IsListEmpty( &pendp->urb_list ) == TRUE )
- {
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &ehci->pending_endp_list_lock );
- continue;
- }
- else if( finished == TRUE )
- {
- //has purb in the endp's purb-list
- if( usb_endp_busy_count( pendp ) > 0 )
- {
+
+ if (purb->status == USB_STATUS_BABBLE_DETECTED)
+ {
+ usb_dbg_print(DBGLVL_MEDIUM,
+ ("ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n"));
+ // ehci_start( ehci );
+ }
+
+ if (ehci_status & STS_HALT) //&& !ehci->is_suspended
+ {
+ ehci_start(&ehci->hcd_interf);
+ }
+
+ //this will let the new request in ehci_generic_urb_completion to this endp
+ //be processed rather than queued in the pending_endp_list
+ lock_dev(pdev, TRUE);
+ usb_endp_busy_count_dec(pendp);
+ unlock_dev(pdev, TRUE);
+
+ if (usb_success(purb->status) == FALSE)
+ {
+ // set error code and complete the purb and purb is invalid from this point
+ ehci_generic_urb_completion(purb, purb->context);
+ }
+ else
+ {
+ if (ep_type == USB_ENDPOINT_XFER_BULK)
+ {
+ purb->rest_bytes -= purb->bytes_transfered;
+ if (purb->rest_bytes)
+ {
+ finished = FALSE;
+ }
+ else
+ {
+ ehci_generic_urb_completion(purb, purb->context);
+ }
+ }
+ else
+ {
+ ehci_generic_urb_completion(purb, purb->context);
+ // DbgBreakPoint();
+ //purb is now invalid
+ }
+ }
+
+ KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (finished)
+ pdev->ref_count--;
+
+ if (urb_status && ((ep_type == USB_ENDPOINT_XFER_BULK) || (ep_type == USB_ENDPOINT_XFER_INT)))
+ {
+ // error on int or bulk pipe, cleared in usb_reset_pipe_completion
+ pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
+ pendp->flags |= USB_ENDP_FLAG_STALL;
+ }
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
+ if (finished == FALSE)
+ {
+
+ purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ ehci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, TRUE);
+ pdev->ref_count--;
+ unlock_dev(pdev, TRUE);
+ }
+ continue;
+ }
+
+ if (finished && IsListEmpty(&pendp->urb_list) == TRUE)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
+ continue;
+ }
+ else if (finished == TRUE)
+ {
+ //has purb in the endp's purb-list
+ if (usb_endp_busy_count(pendp) > 0)
+ {
//the urbs still have chance to be sheduled but not this time
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &ehci->pending_endp_list_lock );
- continue;
- }
- }
-
- if( finished == FALSE )
- {
- //a split bulk transfer, ( not the high speed split transfer )
- purb->bytes_transfered = 0;
- purb->bytes_to_transfer =
- EHCI_MAX_SIZE_TRANSFER > purb->rest_bytes
- ? purb->rest_bytes
- : EHCI_MAX_SIZE_TRANSFER;
-
- //the purb is not finished
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_PENDING;
-
- InsertHeadList( &pendp->urb_list, ( PLIST_ENTRY )purb );
- }
-
- pending_endp = alloc_pending_endp( &ehci->pending_endp_pool, 1 );
- pending_endp->pendp = pendp;
- InsertTailList( &ehci->pending_endp_list, &pending_endp->endp_link );
-
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &ehci->pending_endp_list_lock );
- }
-
- //ah...exhausted, let's find some in the pending_endp_list to rock
- ehci_process_pending_endp( ehci );
- return;
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
+ continue;
+ }
+ }
+
+ if (finished == FALSE)
+ {
+ //a split bulk transfer, ( not the high speed split transfer )
+ purb->bytes_transfered = 0;
+ purb->bytes_to_transfer =
+ EHCI_MAX_SIZE_TRANSFER > purb->rest_bytes ? purb->rest_bytes : EHCI_MAX_SIZE_TRANSFER;
+
+ //the purb is not finished
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_PENDING;
+
+ InsertHeadList(&pendp->urb_list, (PLIST_ENTRY) purb);
+ }
+
+ pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1);
+ pending_endp->pendp = pendp;
+ InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link);
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
+ }
+
+ //ah...exhausted, let's find some in the pending_endp_list to rock
+ ehci_process_pending_endp(ehci);
+ return;
}
BOOLEAN
-ehci_sync_cancel_urbs_dev(
-PVOID context
-)
+ehci_sync_cancel_urbs_dev(PVOID context)
{
- //cancel all the urbs on one dev
- PEHCI_DEV ehci;
- PUSB_DEV pdev, dest_dev;
- PSYNC_PARAM sync_param;
- PLIST_ENTRY pthis, pnext;
- LONG count;
-
- sync_param = ( PSYNC_PARAM )context;
- dest_dev = ( PUSB_DEV )sync_param->context;
- ehci = sync_param->ehci;
-
- if( ehci == NULL || dest_dev == NULL )
- {
- return ( UCHAR )sync_param->ret = FALSE;
- }
- count = 0;
- ListFirst( &ehci->urb_list, pthis );
- while( pthis )
- {
- pdev = dev_from_endp( ( ( PURB ) pthis )->pendp );
- if( pdev == dest_dev )
- {
- ( ( PURB ) pthis )->flags |= URB_FLAG_FORCE_CANCEL;
- }
- ListNext( &ehci->urb_list, pthis, pnext );
- pthis = pnext;
- count ++;
- }
-
- if( count )
- {
- // signal an int for further process
- press_doorbell( ehci );
- }
- return ( UCHAR )sync_param->ret = TRUE;
+ //cancel all the urbs on one dev
+ PEHCI_DEV ehci;
+ PUSB_DEV pdev, dest_dev;
+ PSYNC_PARAM sync_param;
+ PLIST_ENTRY pthis, pnext;
+ LONG count;
+
+ sync_param = (PSYNC_PARAM) context;
+ dest_dev = (PUSB_DEV) sync_param->context;
+ ehci = sync_param->ehci;
+
+ if (ehci == NULL || dest_dev == NULL)
+ {
+ return (UCHAR) sync_param->ret = FALSE;
+ }
+ count = 0;
+ ListFirst(&ehci->urb_list, pthis);
+ while (pthis)
+ {
+ pdev = dev_from_endp(((PURB) pthis)->pendp);
+ if (pdev == dest_dev)
+ {
+ ((PURB) pthis)->flags |= URB_FLAG_FORCE_CANCEL;
+ }
+ ListNext(&ehci->urb_list, pthis, pnext);
+ pthis = pnext;
+ count++;
+ }
+
+ if (count)
+ {
+ // signal an int for further process
+ press_doorbell(ehci);
+ }
+ return (UCHAR) sync_param->ret = TRUE;
}
BOOL
-ehci_remove_device(
-PEHCI_DEV ehci,
-PUSB_DEV dev
-)
+ehci_remove_device(PEHCI_DEV ehci, PUSB_DEV dev)
{
- PUHCI_PENDING_ENDP ppending_endp;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- LIST_HEAD temp_list;
- int i, j, k;
- SYNC_PARAM sync_param;
-
- USE_IRQL;
-
- if( ehci == NULL || dev == NULL )
- return FALSE;
-
- InitializeListHead( &temp_list );
-
- //free pending endp that has purb queued from pending endp list
- lock_pending_endp_list( &ehci->pending_endp_list_lock );
-
- ListFirst( &ehci->pending_endp_list, pthis );
-
- while( pthis )
- {
- ppending_endp = ( PUHCI_PENDING_ENDP ) pthis;
- ListNext( &ehci->pending_endp_list, pthis, pnext );
- if( dev_from_endp( ppending_endp->pendp ) == dev )
- {
- RemoveEntryList( pthis );
- free_pending_endp( &ehci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- }
- pthis = pnext;
- }
- unlock_pending_endp_list( &ehci->pending_endp_list_lock );
-
- //cancel all the urbs in the purb-list
- sync_param.ehci = ehci;
- sync_param.context = ( PVOID )dev;
-
- KeSynchronizeExecution( ehci->pdev_ext->ehci_int, ehci_sync_cancel_urbs_dev, &sync_param );
-
- //cancel all the purb in the endp's purb-list
- k = 0;
- lock_dev( dev, FALSE );
- if( dev->usb_config )
- {
- //only for configed dev
- for( i = 0; i < dev->usb_config->if_count; i++ )
- {
- for( j = 0; j < dev->usb_config->interf[ i ].endp_count; j++ )
- {
- ListFirst( &dev->usb_config->interf[ i ].endp[ j ].urb_list, pthis );
- while( pthis )
- {
- ListNext( &dev->usb_config->interf[ i ].endp[ j ].urb_list,
- pthis,
- pnext );
-
- RemoveEntryList( pthis );
- InsertHeadList( &temp_list, pthis );
- pthis = pnext;
- k++;
- }
-
- }
- }
- }
- ListFirst( &dev->default_endp.urb_list, pthis );
-
- while( pthis )
- {
- ListNext( &dev->default_endp.urb_list,
- pthis,
- pnext );
-
- RemoveEntryList( pthis );
- InsertHeadList( &temp_list, pthis );
- pthis = pnext;
- k++;
- }
- unlock_dev( dev, FALSE );
-
- if( IsListEmpty( &temp_list ) == FALSE )
- {
- for( i = 0; i < k ; i++ )
- {
- //complete those urbs with error
- pthis = RemoveHeadList( &temp_list );
- purb = ( PURB ) pthis;
- purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- {
- ehci_generic_urb_completion( purb, purb->context );
- }
- }
- }
-
- lock_dev( dev, FALSE )
- dev->ref_count -= k;
- unlock_dev( dev, FALSE );
-
- return TRUE;
+ PUHCI_PENDING_ENDP ppending_endp;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ LIST_HEAD temp_list;
+ int i, j, k;
+ SYNC_PARAM sync_param;
+
+ USE_IRQL;
+
+ if (ehci == NULL || dev == NULL)
+ return FALSE;
+
+ InitializeListHead(&temp_list);
+
+ //free pending endp that has purb queued from pending endp list
+ lock_pending_endp_list(&ehci->pending_endp_list_lock);
+
+ ListFirst(&ehci->pending_endp_list, pthis);
+
+ while (pthis)
+ {
+ ppending_endp = (PUHCI_PENDING_ENDP) pthis;
+ ListNext(&ehci->pending_endp_list, pthis, pnext);
+ if (dev_from_endp(ppending_endp->pendp) == dev)
+ {
+ RemoveEntryList(pthis);
+ free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ }
+ pthis = pnext;
+ }
+ unlock_pending_endp_list(&ehci->pending_endp_list_lock);
+
+ //cancel all the urbs in the purb-list
+ sync_param.ehci = ehci;
+ sync_param.context = (PVOID) dev;
+
+ KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urbs_dev, &sync_param);
+
+ //cancel all the purb in the endp's purb-list
+ k = 0;
+ lock_dev(dev, FALSE);
+ if (dev->usb_config)
+ {
+ //only for configed dev
+ for(i = 0; i < dev->usb_config->if_count; i++)
+ {
+ for(j = 0; j < dev->usb_config->interf[i].endp_count; j++)
+ {
+ ListFirst(&dev->usb_config->interf[i].endp[j].urb_list, pthis);
+ while (pthis)
+ {
+ ListNext(&dev->usb_config->interf[i].endp[j].urb_list, pthis, pnext);
+
+ RemoveEntryList(pthis);
+ InsertHeadList(&temp_list, pthis);
+ pthis = pnext;
+ k++;
+ }
+
+ }
+ }
+ }
+ ListFirst(&dev->default_endp.urb_list, pthis);
+
+ while (pthis)
+ {
+ ListNext(&dev->default_endp.urb_list, pthis, pnext);
+
+ RemoveEntryList(pthis);
+ InsertHeadList(&temp_list, pthis);
+ pthis = pnext;
+ k++;
+ }
+ unlock_dev(dev, FALSE);
+
+ if (IsListEmpty(&temp_list) == FALSE)
+ {
+ for(i = 0; i < k; i++)
+ {
+ //complete those urbs with error
+ pthis = RemoveHeadList(&temp_list);
+ purb = (PURB) pthis;
+ purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ {
+ ehci_generic_urb_completion(purb, purb->context);
+ }
+ }
+ }
+
+ lock_dev(dev, FALSE) dev->ref_count -= k;
+ unlock_dev(dev, FALSE);
+
+ return TRUE;
}
static BOOL
-ehci_insert_urb_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_insert_urb_schedule(PEHCI_DEV ehci, PURB purb)
// must have dev_lock( ehci_process_pending_endp ) and frame_list_lock acquired
{
- PURB_HS_PIPE_CONTENT pipe_content;
-
- if( ehci == NULL || purb == NULL )
- return FALSE;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- switch( pipe_content->trans_type )
- {
- case USB_ENDPOINT_XFER_CONTROL:
- ehci_insert_control_schedule( ehci, purb );
- break;
- case USB_ENDPOINT_XFER_BULK:
- ehci_insert_bulk_schedule( ehci, purb );
- break;
- case USB_ENDPOINT_XFER_INT:
- ehci_insert_int_schedule( ehci, purb );
- break;
- case USB_ENDPOINT_XFER_ISOC:
- ehci_insert_iso_schedule( ehci, purb );
- break;
- default:
- return FALSE;
- }
-
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE;
- InsertTailList( &ehci->urb_list, ( PLIST_ENTRY )purb );
-
- return TRUE;
+ PURB_HS_PIPE_CONTENT pipe_content;
+
+ if (ehci == NULL || purb == NULL)
+ return FALSE;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ switch (pipe_content->trans_type)
+ {
+ case USB_ENDPOINT_XFER_CONTROL:
+ ehci_insert_control_schedule(ehci, purb);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ ehci_insert_bulk_schedule(ehci, purb);
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ ehci_insert_int_schedule(ehci, purb);
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ ehci_insert_iso_schedule(ehci, purb);
+ break;
+ default:
+ return FALSE;
+ }
+
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE;
+ InsertTailList(&ehci->urb_list, (PLIST_ENTRY) purb);
+
+ return TRUE;
}
static BOOL
-ehci_insert_tds_qh(
-PEHCI_DEV ehci,
-PEHCI_QH pqh,
-PEHCI_QTD td_chain
-)
+ehci_insert_tds_qh(PEHCI_DEV ehci, PEHCI_QH pqh, PEHCI_QTD td_chain)
{
- if( pqh == NULL || td_chain == NULL )
- return FALSE;
+ if (pqh == NULL || td_chain == NULL)
+ return FALSE;
- ehci_copy_overlay( ( PEHCI_QH_CONTENT )pqh, ( PEHCI_QTD_CONTENT )td_chain );
- InsertTailList( &td_chain->elem_head_link->elem_link, &pqh->elem_head_link->elem_link );
- return TRUE;
- ehci;
+ ehci_copy_overlay((PEHCI_QH_CONTENT) pqh, (PEHCI_QTD_CONTENT) td_chain);
+ InsertTailList(&td_chain->elem_head_link->elem_link, &pqh->elem_head_link->elem_link);
+ return TRUE;
+ ehci;
}
static BOOL
-ehci_insert_qh_urb(
-PURB purb,
-PEHCI_QH pqh
-)
+ehci_insert_qh_urb(PURB purb, PEHCI_QH pqh)
{
- PLIST_ENTRY pthis, pnext;
- if( pqh == NULL || purb == NULL )
- return FALSE;
-
- InsertTailList( &pqh->elem_head_link->elem_link, &purb->trasac_list );
- ListFirst( &purb->trasac_list, pthis )
- while( pthis )
- {
- // note: fstn may in this chain
- struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link )->purb = purb;
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
- return TRUE;
+ PLIST_ENTRY pthis, pnext;
+ if (pqh == NULL || purb == NULL)
+ return FALSE;
+
+ InsertTailList(&pqh->elem_head_link->elem_link, &purb->trasac_list);
+ ListFirst(&purb->trasac_list, pthis) while (pthis)
+ {
+ // note: fstn may in this chain
+ struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb;
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+ return TRUE;
}
#define calc_td_count( pURB, start_aDDR, td_coUNT ) \
}
static BOOL
-ehci_fill_td_buf_ptr(
-PURB purb,
-LONG start_addr, // start idx into purb->data_buffer
-PLIST_ENTRY td_list,
-LONG td_count,
-ULONG toggle
-)
+ehci_fill_td_buf_ptr(PURB purb, LONG start_addr, // start idx into purb->data_buffer
+ PLIST_ENTRY td_list, LONG td_count, ULONG toggle)
// fill the tds' bytes_to_transfer and hw_buf, return next toggle value: true 1, false 0
{
- LONG i, j, k, data_load;
- LONG packets_per_td, packets_per_page, bytes_to_transfer, max_packet_size;
- PLIST_ENTRY pthis, pnext;
- PEHCI_QTD_CONTENT ptdc;
- PEHCI_QTD ptd;
- PVOID ptr;
-
- if( purb == NULL || td_list == NULL || td_count == 0 )
- return toggle;
-
- max_packet_size = 1 << ( ( PURB_HS_PIPE_CONTENT )&purb->pipe )->max_packet_size;
- packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;
- packets_per_page = PAGE_SIZE / max_packet_size;
-
- pthis = td_list;
- bytes_to_transfer = purb->bytes_to_transfer;
-
- i = ( ( LONG )&( purb )->data_buffer[ ( start_addr ) ] ) & ( PAGE_SIZE - 1 );
- if( i )
- {
- i = PAGE_SIZE - i;
- j = i & ( max_packet_size - 1 );
- }
- else
- {
- i = j = 0;
- }
-
- while( bytes_to_transfer )
- {
- ptd = qtd_from_list_entry( pthis );
- ptd->hw_buf[ 0 ] = MmGetPhysicalAddress( &purb->data_buffer[ start_addr ] ).LowPart;
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
-
- if( i != 0 )
- {
- data_load = ( LONG )( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) < bytes_to_transfer
- ? ( LONG )( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) : bytes_to_transfer;
-
- ptdc->bytes_to_transfer = ( USHORT )data_load;
- ptd->bytes_to_transfer = ( USHORT )data_load;
-
- // subtract the header part
- data_load -= ( i < data_load ? i : data_load );
-
- for( k = 1; data_load > 0; k++ )
- {
- ptr = &purb->data_buffer[ start_addr + i + ( k - 1 ) * PAGE_SIZE ];
- ptr = ( PVOID )( ( ( ULONG )ptr ) & ~( PAGE_SIZE - 1 ) );
- ptd->hw_buf[ k ] = MmGetPhysicalAddress( ptr ).LowPart;
- data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
- }
- }
- else
- {
- // aligned on page boundary
- data_load = EHCI_QTD_MAX_TRANS_SIZE < bytes_to_transfer
- ? EHCI_QTD_MAX_TRANS_SIZE : bytes_to_transfer;
-
- ptdc->bytes_to_transfer = ( USHORT )data_load;
- ptd->bytes_to_transfer = ( USHORT )data_load;
-
- data_load -= ( PAGE_SIZE < data_load ? PAGE_SIZE : data_load );
-
- for( k = 1; data_load > 0; k++ )
- {
- ptr = &purb->data_buffer[ start_addr + k * PAGE_SIZE ];
- ptr = ( PVOID )( ( ( ULONG )ptr ) & ~( PAGE_SIZE - 1 ) );
- ptd->hw_buf[ k ] = MmGetPhysicalAddress( ptr ).LowPart;
- data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
- }
- }
- ptdc->data_toggle = toggle;
- if( ( ( ptdc->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size ) & 1 )
- {
- //only odd num of transactions has effect
- toggle ^= 1;
- }
- start_addr += ptdc->bytes_to_transfer;
- bytes_to_transfer -= ptdc->bytes_to_transfer;
- ListNext( td_list, pthis, pnext );
- pthis = pnext;
- i = j;
- }
- return toggle;
+ LONG i, j, k, data_load;
+ LONG packets_per_td, packets_per_page, bytes_to_transfer, max_packet_size;
+ PLIST_ENTRY pthis, pnext;
+ PEHCI_QTD_CONTENT ptdc;
+ PEHCI_QTD ptd;
+ PVOID ptr;
+
+ if (purb == NULL || td_list == NULL || td_count == 0)
+ return toggle;
+
+ max_packet_size = 1 << ((PURB_HS_PIPE_CONTENT) & purb->pipe)->max_packet_size;
+ packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;
+ packets_per_page = PAGE_SIZE / max_packet_size;
+
+ pthis = td_list;
+ bytes_to_transfer = purb->bytes_to_transfer;
+
+ i = ((LONG) & (purb)->data_buffer[(start_addr)]) & (PAGE_SIZE - 1);
+ if (i)
+ {
+ i = PAGE_SIZE - i;
+ j = i & (max_packet_size - 1);
+ }
+ else
+ {
+ i = j = 0;
+ }
+
+ while (bytes_to_transfer)
+ {
+ ptd = qtd_from_list_entry(pthis);
+ ptd->hw_buf[0] = MmGetPhysicalAddress(&purb->data_buffer[start_addr]).LowPart;
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+
+ if (i != 0)
+ {
+ data_load = (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) < bytes_to_transfer
+ ? (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) : bytes_to_transfer;
+
+ ptdc->bytes_to_transfer = (USHORT) data_load;
+ ptd->bytes_to_transfer = (USHORT) data_load;
+
+ // subtract the header part
+ data_load -= (i < data_load ? i : data_load);
+
+ for(k = 1; data_load > 0; k++)
+ {
+ ptr = &purb->data_buffer[start_addr + i + (k - 1) * PAGE_SIZE];
+ ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1));
+ ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart;
+ data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
+ }
+ }
+ else
+ {
+ // aligned on page boundary
+ data_load = EHCI_QTD_MAX_TRANS_SIZE < bytes_to_transfer
+ ? EHCI_QTD_MAX_TRANS_SIZE : bytes_to_transfer;
+
+ ptdc->bytes_to_transfer = (USHORT) data_load;
+ ptd->bytes_to_transfer = (USHORT) data_load;
+
+ data_load -= (PAGE_SIZE < data_load ? PAGE_SIZE : data_load);
+
+ for(k = 1; data_load > 0; k++)
+ {
+ ptr = &purb->data_buffer[start_addr + k * PAGE_SIZE];
+ ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1));
+ ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart;
+ data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
+ }
+ }
+ ptdc->data_toggle = toggle;
+ if (((ptdc->bytes_to_transfer + max_packet_size - 1) / max_packet_size) & 1)
+ {
+ //only odd num of transactions has effect
+ toggle ^= 1;
+ }
+ start_addr += ptdc->bytes_to_transfer;
+ bytes_to_transfer -= ptdc->bytes_to_transfer;
+ ListNext(td_list, pthis, pnext);
+ pthis = pnext;
+ i = j;
+ }
+ return toggle;
}
static NTSTATUS
-ehci_internal_submit_bulk(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb)
//
// assume that the purb has its rest_bytes and bytes_to_transfer set
// and bytes_transfered is zeroed.
{
LONG max_packet_size, td_count, offset, bytes_to_transfer, data_load;
- PBYTE start_addr;
- PEHCI_QTD ptd;
- PEHCI_QH pqh;
- LIST_ENTRY td_list, *pthis, *pnext;
+ PBYTE start_addr;
+ PEHCI_QTD ptd;
+ PEHCI_QH pqh;
+ LIST_ENTRY td_list, *pthis, *pnext;
BOOL old_toggle, toggle, ret;
- UCHAR pid;
- LONG i, j, k;
- PURB_HS_PIPE_CONTENT pipe_content;
- PEHCI_QTD_CONTENT ptdc;
- PEHCI_QH_CONTENT pqhc;
- PEHCI_ELEM_LINKS pelnk;
+ UCHAR pid;
+ LONG i, j, k;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PEHCI_QTD_CONTENT ptdc;
+ PEHCI_QH_CONTENT pqhc;
+ PEHCI_ELEM_LINKS pelnk;
+
+ if (ehci == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ max_packet_size = endp_max_packet_size(purb->pendp);
+ if (purb->bytes_to_transfer == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
- if( ehci == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
+ start_addr = &purb->data_buffer[purb->data_length - purb->rest_bytes];
+ calc_td_count(purb, purb->data_length - purb->rest_bytes, td_count);
- max_packet_size = endp_max_packet_size( purb->pendp );
- if( purb->bytes_to_transfer == 0 )
- {
- return STATUS_INVALID_PARAMETER;
- }
+ elem_pool_lock(qtd_pool, TRUE);
+ pelnk = elem_pool_alloc_elems(qtd_pool, td_count);
+ elem_pool_unlock(qtd_pool, TRUE);
- start_addr = &purb->data_buffer[ purb->data_length - purb->rest_bytes ];
- calc_td_count( purb, purb->data_length - purb->rest_bytes, td_count );
+ if (pelnk == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
- elem_pool_lock( qtd_pool , TRUE );
- pelnk = elem_pool_alloc_elems( qtd_pool, td_count );
- elem_pool_unlock( qtd_pool, TRUE );
+ InitializeListHead(&td_list);
+ InsertTailList(&ptd->elem_head_link->elem_link, &td_list);
- if( pelnk == NULL )
- {
- return STATUS_UNSUCCESSFUL;
- }
- ptd = ( PEHCI_QTD )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
+ ListFirst(&td_list, pthis);
+ ListNext(&td_list, pthis, pnext);
- InitializeListHead( &td_list );
- InsertTailList( &ptd->elem_head_link->elem_link, &td_list );
+ offset = 0;
- ListFirst( &td_list, pthis );
- ListNext( &td_list, pthis, pnext );
+ old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE;
+ bytes_to_transfer = purb->bytes_to_transfer;
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle));
- offset = 0;
+ for(i = 1; i < 16; i++)
+ {
+ if ((max_packet_size >> i) == 0)
+ break;
+ }
+ i--;
+ i &= 0xf;
+
+ purb->pipe = 0;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ pipe_content->max_packet_size = i;
+ pipe_content->endp_addr = endp_num(purb->pendp);
+ pipe_content->dev_addr = dev_from_endp(purb->pendp)->dev_addr;
+ pipe_content->trans_dir = endp_dir(purb->pendp);
+ pipe_content->trans_type = USB_ENDPOINT_XFER_BULK;
+ pipe_content->data_toggle = toggle;
+ pipe_content->speed_high = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0;
+ pipe_content->speed_low = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0;
+
+ pid = (((ULONG) purb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT);
+
+ i = ((ULONG) start_addr) & (PAGE_SIZE - 1); // header part within first page
+ if (i)
+ {
+ i = PAGE_SIZE - i;
+ if (i < purb->bytes_to_transfer)
+ j = i & (max_packet_size - 1);
+ else
+ j = 0;
+ }
+ else
+ j = 0;
- old_toggle = toggle = ( purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ) ? TRUE : FALSE;
- bytes_to_transfer = purb->bytes_to_transfer;
- ehci_dbg_print( DBGLVL_MAXIMUM, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle ) );
-
- for( i = 1; i < 16; i++ )
- {
- if( ( max_packet_size >> i ) == 0 )
- break;
- }
- i--;
- i &= 0xf;
-
- purb->pipe = 0;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- pipe_content->max_packet_size = i;
- pipe_content->endp_addr = endp_num( purb->pendp );
- pipe_content->dev_addr = dev_from_endp( purb->pendp )->dev_addr;
- pipe_content->trans_dir = endp_dir( purb->pendp );
- pipe_content->trans_type = USB_ENDPOINT_XFER_BULK;
- pipe_content->data_toggle = toggle;
- pipe_content->speed_high = ( dev_from_endp( purb->pendp )->flags & USB_DEV_FLAG_HIGH_SPEED ) ? 1 : 0;
- pipe_content->speed_low = ( dev_from_endp( purb->pendp )->flags & USB_DEV_FLAG_LOW_SPEED ) ? 1 : 0;
-
- pid = ( ( ( ULONG )purb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? QTD_PID_IN : QTD_PID_OUT );
-
- i = ( ( ULONG )start_addr ) & ( PAGE_SIZE - 1 ) ; // header part within first page
- if( i )
- {
- i = PAGE_SIZE - i;
- if( i < purb->bytes_to_transfer )
- j = i & ( max_packet_size - 1 );
- else
- j = 0;
- }
- else
- j = 0;
-
- // fill the page pointer and toggle
-
- toggle = ehci_fill_td_buf_ptr( purb, purb->data_length - purb->rest_bytes, pthis, td_count, toggle );
- while( pthis )
- {
- ptd = qtd_from_list_entry( pthis );
- ptdc = ( PEHCI_QTD_CONTENT ) ptd;
-
- // ptdc->alt_terminal = 1;
- // ptdc->alt_qtd = 0;
- ptd->hw_alt_next = EHCI_PTR_TERM;
- ptdc->pid = pid;
-
- // ptd->elem_head_link->purb = purb; will be filled later
- ptdc->err_count = 3;
- ptdc->status = 0x80; // active, and do_start_split for split transfer
- ptdc->cur_page = 0;
- // ptdc->data_toggle = toggle;
-
- if( pnext )
- {
- ptd->hw_next = qtd_from_list_entry( pnext )->phys_addr;
- }
- else
- {
- //Last one, enable ioc and short packet detect if necessary
- ptd->hw_next = EHCI_PTR_TERM;
- ptdc->ioc = TRUE;
- if( bytes_to_transfer < max_packet_size && ( pid == QTD_PID_IN ) )
- {
- //ptd->status |= TD_CTRL_SPD;
- }
- }
-
- pthis = pnext;
-
- if( pthis )
- ListNext( &td_list, pthis, pnext );
- }
-
- ListFirst( &td_list, pthis );
- RemoveEntryList( &td_list );
-
- elem_pool_lock( qh_pool, TRUE );
- pqh = ( PEHCI_QH )( ( ULONG )elem_pool_alloc_elem( qh_pool )->phys_part & PHYS_PART_ADDR_MASK );
- elem_pool_unlock( qh_pool, TRUE);
-
- if( pqh == NULL )
- {
- // free the qtds
- elem_safe_free( pthis, TRUE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
-
- purb->td_count = td_count;
- pqhc = ( PEHCI_QH_CONTENT )pqh;
- pqh->hw_next = EHCI_PTR_TERM; // filled later
- pqhc->dev_addr = pipe_content->dev_addr;
- pqhc->inactive = 0;
- pqhc->endp_addr = pipe_content->endp_addr;
- pqhc->data_toggle = 0; //pipe_content->data_toggle;
- pqhc->is_async_head = 0;
- pqhc->max_packet_size = ( 1 << pipe_content->max_packet_size );
- pqhc->is_ctrl_endp = 0;
- pqhc->reload_counter = EHCI_NAK_RL_COUNT;
-
- if( pipe_content->speed_high )
- pqhc->endp_spd = USB_SPEED_HIGH;
- else if( pipe_content->speed_low )
- pqhc->endp_spd = USB_SPEED_LOW;
- else
- pqhc->endp_spd = USB_SPEED_FULL;
-
- pqh->hw_info2 = 0;
- pqhc->mult = 1;
- pqh->hw_current = 0;
- pqh->hw_qtd_next = 0; // filled later
- pqh->hw_alt_next = EHCI_PTR_TERM;
- pqh->hw_token = 0; //indicate to advance queue before execution
-
- if( !pipe_content->speed_high )
- {
- pqhc->hub_addr = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr;
- pqhc->port_idx = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx;
- }
-
- ptd = qtd_from_list_entry( pthis );
- ehci_insert_tds_qh( ehci, pqh, ptd );
- ehci_insert_qh_urb( purb, pqh );
- purb->pendp->flags = ( purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( toggle ? USB_ENDP_FLAG_DATATOGGLE : 0 ) ;
- usb_endp_busy_count_inc( purb->pendp );
- ehci_insert_urb_to_schedule( ehci, purb, ret );
-
- if( ret == FALSE )
- {
- // undo all we have done
- ListFirst( &pqh->elem_head_link->elem_link, pthis );
-
- RemoveEntryList( &purb->trasac_list );
- RemoveEntryList( &pqh->elem_head_link->elem_link ); //remove qh from td_chain
-
- elem_safe_free( pthis, FALSE );
- elem_safe_free( &pqh->elem_head_link->elem_link, TRUE );
-
- InitializeListHead( &purb->trasac_list );
- // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback
- purb->pendp->flags = ( purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0 ) ;
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
-}
+ // fill the page pointer and toggle
-static NTSTATUS
-ehci_internal_submit_ctrl(
-PEHCI_DEV ehci,
-PURB purb
-)
-{
+ toggle = ehci_fill_td_buf_ptr(purb, purb->data_length - purb->rest_bytes, pthis, td_count, toggle);
+ while (pthis)
+ {
+ ptd = qtd_from_list_entry(pthis);
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+
+ // ptdc->alt_terminal = 1;
+ // ptdc->alt_qtd = 0;
+ ptd->hw_alt_next = EHCI_PTR_TERM;
+ ptdc->pid = pid;
+
+ // ptd->elem_head_link->purb = purb; will be filled later
+ ptdc->err_count = 3;
+ ptdc->status = 0x80; // active, and do_start_split for split transfer
+ ptdc->cur_page = 0;
+ // ptdc->data_toggle = toggle;
+
+ if (pnext)
+ {
+ ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
+ }
+ else
+ {
+ //Last one, enable ioc and short packet detect if necessary
+ ptd->hw_next = EHCI_PTR_TERM;
+ ptdc->ioc = TRUE;
+ if (bytes_to_transfer < max_packet_size && (pid == QTD_PID_IN))
+ {
+ //ptd->status |= TD_CTRL_SPD;
+ }
+ }
+
+ pthis = pnext;
+
+ if (pthis)
+ ListNext(&td_list, pthis, pnext);
+ }
- LIST_ENTRY td_list, *pthis, *pnext;
- LONG i, j, td_count;
- LONG toggle;
- LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx;
-
- PEHCI_QTD ptd;
- PEHCI_QH pqh;
- PEHCI_QH_CONTENT pqhc;
- UCHAR dev_addr;
- BOOL ret;
- PURB_HS_PIPE_CONTENT pipe_content;
- PEHCI_QTD_CONTENT ptdc;
- PEHCI_ELEM_LINKS pelnk;
- PUSB_DEV pdev;
-
- if( ehci == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- bytes_rest = purb->rest_bytes;
- bytes_to_transfer = purb->bytes_to_transfer;
- max_packet_size = endp_max_packet_size( purb->pendp );
- start_idx = purb->data_length - purb->rest_bytes;
-
- calc_td_count( purb, start_idx, td_count );
- td_count += 2; // add setup td and handshake td
-
- elem_pool_lock( qtd_pool, TRUE );
- pelnk = elem_pool_alloc_elems( qtd_pool, td_count );
- elem_pool_unlock( qtd_pool, TRUE );
-
- if( pelnk == NULL )
- {
- return STATUS_NO_MORE_ENTRIES;
- }
-
- InsertTailList( &pelnk->elem_link, &td_list );
- ListFirst( &td_list, pthis );
- ListNext( &td_list, pthis, pnext );
-
- ptd = qtd_from_list_entry( pthis );
-
- pdev = dev_from_endp( purb->pendp );
- dev_addr = pdev->dev_addr;
-
- if( dev_state( pdev ) <= USB_DEV_STATE_RESET ) //only valid for control transfer
- dev_addr = 0;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_internal_submit_ctrl(): dev_addr =0x%x\n", \
- dev_addr ) );
-
- // fill the setup packet
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
- ptd->hw_next = qtd_from_list_entry( pnext )->phys_addr;
- ptd->hw_alt_next = EHCI_PTR_TERM;
- ptdc->status = 0x80; // active
- ptdc->pid = QTD_PID_SETUP;
- ptdc->err_count = 3;
- ptdc->cur_page = 0;
- ptdc->ioc = 0;
- ptdc->bytes_to_transfer = sizeof( USB_CTRL_SETUP_PACKET );
- ptdc->data_toggle = 0;
- ptd->hw_buf[ 0 ] = MmGetPhysicalAddress( purb->setup_packet ).LowPart;
-
- for( i = 1; i < 16; i++ )
- {
- if( ( max_packet_size >> i ) == 0 )
- break;
- }
- i--;
- i &= 0xf;
-
- purb->pipe = 0;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- pipe_content->max_packet_size = i;
- pipe_content->endp_addr = endp_num( purb->pendp );
- pipe_content->dev_addr = dev_addr;
- pipe_content->speed_low = ( pdev->flags & USB_DEV_FLAG_LOW_SPEED ) ? 1 : 0;
- pipe_content->speed_high = ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) ? 1 : 0;
- pipe_content->trans_type = USB_ENDPOINT_XFER_CONTROL;
-
- pthis = pnext;
- ListNext( &td_list, pthis, pnext );
-
- // all the tds's toggle and data_buffer pointer is filled here
- toggle = 1;
- ehci_fill_td_buf_ptr( purb, start_idx, pthis, td_count - 2, toggle );
-
- for( i = 0; ( ( i < td_count - 2 ) && pthis ); i++ )
- {
- //construct tds for DATA packets of data stage.
- ptd = qtd_from_list_entry( pthis );
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
- ptd->hw_alt_next = EHCI_PTR_TERM;
- ptdc->status = 0x80; // active and startXSplit
- ptdc->pid = ( ( purb->setup_packet[ 0 ] & USB_DIR_IN ) ? QTD_PID_IN : QTD_PID_OUT );
- ptdc->err_count = 3;
- ptdc->cur_page = 0;
- ptdc->ioc = 0;
-
- if( pnext )
- ptd->hw_next = qtd_from_list_entry( pnext )->phys_addr;
- else
- ptd->hw_next = EHCI_PTR_TERM;
-
- pthis = pnext;
- if( pthis )
- ListNext( &td_list, pthis, pnext );
- }
-
- if( pthis )
- ptd->hw_next = qtd_from_list_entry( pthis )->phys_addr;
- else
- TRAP();
-
- // ListFirstPrev( &td_list, pthis );
- ptd = qtd_from_list_entry( pthis );
+ ListFirst(&td_list, pthis);
+ RemoveEntryList(&td_list);
- //the last is an IN transaction
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
- ptd->hw_alt_next = EHCI_PTR_TERM;
- ptdc->status = 0x80;
- ptdc->pid = ( ( td_count > 2 )
- ? ( ( purb->setup_packet[ 0 ] & USB_DIR_IN )
- ? QTD_PID_OUT : QTD_PID_IN )
- : QTD_PID_IN );
-
- ptdc->err_count = 3;
- ptdc->cur_page = 0;
- ptdc->ioc = 1;
- ptdc->bytes_to_transfer = 0;
- ptdc->data_toggle = 1;
- ptd->hw_next = EHCI_PTR_TERM;
-
- ListFirst( &td_list, pthis );
- RemoveEntryList( &td_list );
-
- ptd = qtd_from_list_entry( pthis );
- elem_pool_lock( qh_pool, TRUE );
- pelnk = elem_pool_alloc_elem( qh_pool );
- elem_pool_unlock( qh_pool, TRUE);
-
- if( pelnk == NULL )
- {
- elem_safe_free( pthis, FALSE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
- pqh = ( PEHCI_QH )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- pqhc = ( PEHCI_QH_CONTENT )pqh;
-
- pqh->hw_alt_next = pqh->hw_next = EHCI_PTR_TERM;
-
- pqhc->dev_addr = dev_addr;
- pqhc->inactive = 0;
- pqhc->endp_addr = endp_num( purb->pendp );
-
- if( pipe_content->speed_high )
- pqhc->endp_spd = USB_SPEED_HIGH;
- else if( pipe_content->speed_low )
- pqhc->endp_spd = USB_SPEED_LOW;
- else
- pqhc->endp_spd = USB_SPEED_FULL;
-
- pqhc->data_toggle = 1; // use dt from qtd
- pqhc->is_async_head = 0;
- pqhc->max_packet_size = endp_max_packet_size( purb->pendp );
-
- if( pipe_content->speed_high == 0 )
- pqhc->is_ctrl_endp = 1;
- else
- pqhc->is_ctrl_endp = 0;
-
- pqhc->reload_counter = EHCI_NAK_RL_COUNT;
-
- // DWORD 2
- pqh->hw_info2 = 0;
- pqhc->mult = 1;
-
- if( !pipe_content->speed_high )
- {
- pqhc->hub_addr = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr;
- pqhc->port_idx = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx;
- }
-
- purb->td_count = td_count;
-
- ehci_insert_tds_qh( ehci, pqh, ptd );
- ehci_insert_qh_urb( purb, pqh );
-
- usb_endp_busy_count_inc( purb->pendp );
- ehci_insert_urb_to_schedule( ehci, purb, ret );
-
- if( ret == FALSE )
- {
- RemoveEntryList( &purb->trasac_list );
- RemoveEntryList( &pqh->elem_head_link->elem_link );
-
- elem_safe_free( &pqh->elem_head_link->elem_link, TRUE );
- elem_safe_free( pthis, FALSE );
-
- InitializeListHead( &purb->trasac_list );
- // usb_endp_busy_count_dec( purb->pendp );
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
-}
+ elem_pool_lock(qh_pool, TRUE);
+ pqh = (PEHCI_QH) ((ULONG) elem_pool_alloc_elem(qh_pool)->phys_part & PHYS_PART_ADDR_MASK);
+ elem_pool_unlock(qh_pool, TRUE);
-static NTSTATUS
-ehci_internal_submit_int(
-PEHCI_DEV ehci,
-PURB purb
-)
-{
- LIST_ENTRY td_list, *pthis, *pnext;
- LONG i, max_packet_size;
- PEHCI_QTD ptd;
- BOOL ret;
- PUSB_DEV pdev;
- PURB_HS_PIPE_CONTENT pipe_content;
- UCHAR mult_trans, toggle, old_toggle;
- PEHCI_ELEM_LINKS pelnk;
- PEHCI_QTD_CONTENT ptdc;
- PEHCI_QH pqh;
- PEHCI_QH_CONTENT pqhc;
- PEHCI_FSTN pfstn;
-
- if( ehci == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- old_toggle = toggle = ( purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ) ? TRUE : FALSE;
- max_packet_size = endp_max_packet_size( purb->pendp );
- pdev = dev_from_endp( purb->pendp );
-
- if( max_packet_size == 0 || max_packet_size > 64 )
- return STATUS_INVALID_PARAMETER;
-
- if( ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )
- {
- if( max_packet_size < purb->data_length )
- return STATUS_INVALID_PARAMETER;
-
- for( i = 1; i < 16; i ++ )
- {
- if ( ( ( ( ULONG )purb->pendp->pusb_endp_desc->bInterval ) >> i ) == 0 )
- break;
- }
- i--;
- mult_trans = 1;
- }
- else
- {
- mult_trans = endp_mult_count( purb->pendp );
- if( max_packet_size * endp_mult_count( purb->pendp ) < purb->data_length )
- return STATUS_INVALID_PARAMETER;
- i = purb->pendp->pusb_endp_desc->bInterval - 1;
- }
-
- purb->pipe = 0;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- pipe_content->interval = i;
- pipe_content->trans_type = USB_ENDPOINT_XFER_INT;// bit 0-1
- pipe_content->speed_high = ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) ? 1 : 0; // bit 5
- pipe_content->speed_low = ( pdev->flags & USB_DEV_FLAG_LOW_SPEED ) ? 1 : 0; // bit 6
- pipe_content->trans_dir = endp_dir( purb->pendp ) == USB_DIR_IN ? 1 : 0; // bit 7
- pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
- pipe_content->endp_addr = endp_num( purb->pendp ); // bit 15-18
- pipe_content->data_toggle = 1; // bit 19
- pipe_content->mult_count = mult_trans;
-
- // pipe_content->start_uframe : 3; // bit 28-30 will be filled later
-
- for( i = 1; i <= 16; i++ )
- {
- if( ( ( ULONG )max_packet_size ) >> i )
- continue;
- else
- break;
- }
- i --;
- i &= 0xf;
-
- pipe_content->max_packet_size = i; // bit 20-23 log2( max_packet_size )
-
- if( ehci_claim_bandwidth( ehci, purb, TRUE ) == FALSE )
- {
- // can not allocate bandwidth for it
- return STATUS_UNSUCCESSFUL;
- }
-
- // one qtd is enough
- elem_pool_lock( qtd_pool, TRUE );
- pelnk = elem_pool_alloc_elem( qtd_pool );
- elem_pool_unlock( qtd_pool, TRUE );
-
- if( pelnk == NULL )
- {
- ehci_claim_bandwidth( ehci, purb, FALSE );
- return STATUS_NO_MORE_ENTRIES;
- }
-
- ptd = ( PEHCI_QTD )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- ptdc = ( PEHCI_QTD_CONTENT )ptd;
- ptd->hw_next = EHCI_PTR_TERM;
- // DWORD 1
- ptd->hw_alt_next = EHCI_PTR_TERM;
- // DWORD 2
- ptdc->status = 0x80;
- ptdc->pid = pipe_content->trans_dir ? QTD_PID_IN : QTD_PID_OUT;
- ptdc->err_count = 3;
- ptdc->cur_page = 0;
- ptdc->ioc = 1;
- ptdc->bytes_to_transfer = purb->data_length;
- toggle = ( UCHAR )ehci_fill_td_buf_ptr( purb, 0, &pelnk->elem_link, 1, toggle );
-
- elem_pool_lock( qh_pool, TRUE );
- pelnk = elem_pool_alloc_elem( qh_pool );
- elem_pool_unlock( qh_pool, TRUE );
- if( pelnk == NULL )
- {
- elem_safe_free( &ptd->elem_head_link->elem_link, TRUE );
- InitializeListHead( &purb->trasac_list );
- ehci_claim_bandwidth( ehci, purb, FALSE );
- return STATUS_NO_MORE_ENTRIES;
- }
- pqh = ( PEHCI_QH )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- pqhc = ( PEHCI_QH_CONTENT )pqh;
-
- pqh->hw_next = EHCI_PTR_TERM;
- pqhc->dev_addr = pdev->dev_addr;
- pqhc->inactive = 0;
- pqhc->endp_addr = endp_num( purb->pendp );
-
- if( pipe_content->speed_high )
- pqhc->endp_spd = USB_SPEED_HIGH;
- else if( pipe_content->speed_low )
- pqhc->endp_spd = USB_SPEED_LOW;
- else
- pqhc->endp_spd = USB_SPEED_FULL;
-
- pqhc->data_toggle = 0;
- pqhc->is_async_head = 0;
- pqhc->max_packet_size = endp_max_packet_size( purb->pendp );
- pqhc->is_ctrl_endp = 0;
- pqhc->reload_counter = 0;
-
- // DWORD 2
- pqh->hw_info2 = 0;
- pqhc->mult = mult_trans;
-
- if( pipe_content->speed_high )
- {
- if( pipe_content->interval == 0 ) // one poll per uframe
- pqhc->s_mask = 0xff;
- else if( pipe_content->interval == 1 ) // one poll every 2 uframe
- pqhc->s_mask = pipe_content->start_uframe == 0 ? 0x55 : 0xbb;
- else if( pipe_content->interval == 2 )
- {
- pqhc->s_mask = 0x11;
- pqhc->s_mask <<= pipe_content->start_uframe;
- }
- else
- {
- pqhc->s_mask = 1 << ( pipe_content->start_uframe );
- }
- pqhc->c_mask = 0;
- }
- else // full/low speed
- {
- pqhc->s_mask = 1 << pipe_content->start_uframe;
- if( pipe_content->start_uframe < 4 )
- {
- pqhc->c_mask = 0x07 << ( pipe_content->start_uframe + 2 );
- }
- else if( pipe_content->start_uframe == 4 )
- {
- pqhc->c_mask = 0xc1;
- }
- else if( pipe_content->start_uframe >= 5 )
- {
- // we need fstn
- pqhc->c_mask = 0x03;
- if( pipe_content->start_uframe == 5 )
- {
- pqhc->c_mask |= 0x80;
- }
- }
- if( pipe_content->start_uframe >= 4 )
- {
- // chain an fstn
- elem_pool_lock( fstn_pool, TRUE );
- pelnk = elem_pool_alloc_elem( fstn_pool );
- elem_pool_unlock( fstn_pool, TRUE );
- if( pelnk == NULL )
- {
- elem_safe_free( &pqh->elem_head_link->elem_link, TRUE );
- elem_safe_free( &ptd->elem_head_link->elem_link, TRUE );
- InitializeListHead( &purb->trasac_list );
- ehci_claim_bandwidth( ehci, purb, FALSE );
- return STATUS_NO_MORE_ENTRIES;
- }
- pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- pfstn->hw_prev = ptd->phys_addr;
- pfstn->elem_head_link->purb = purb;
- InsertTailList( &ptd->elem_head_link->elem_link, &pfstn->elem_head_link->elem_link );
- }
- pqhc->hub_addr = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr;
- pqhc->port_idx = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx;
- }
-
- // DWORD 3
- purb->td_count = 1;
-
- InitializeListHead( &purb->trasac_list );
- ehci_insert_tds_qh( ehci, pqh, ptd );
- ehci_insert_qh_urb( purb, pqh );
-
- purb->pendp->flags = ( purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( toggle << 31 );
- usb_endp_busy_count_inc( purb->pendp );
-
- ehci_insert_urb_to_schedule( ehci, purb, ret );
-
- if( ret == FALSE )
- {
- RemoveEntryList( &purb->trasac_list );
- RemoveEntryList( &pqh->elem_head_link->elem_link );
-
- elem_safe_free( &pqh->elem_head_link->elem_link, TRUE );
- // an fstn may follow the td
- elem_safe_free( &ptd->elem_head_link->elem_link, FALSE );
-
- InitializeListHead( &purb->trasac_list );
- ehci_claim_bandwidth( ehci, purb, FALSE );
-
- purb->pendp->flags = ( purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( ( toggle ^ 1 ) << 31 );
- // usb_endp_busy_count_dec( purb->pendp );
-
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
+ if (pqh == NULL)
+ {
+ // free the qtds
+ elem_safe_free(pthis, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
-static NTSTATUS
-ehci_internal_submit_iso(
-PEHCI_DEV ehci,
-PURB purb
-)
-{
- LONG i, j, td_count, temp;
- PEHCI_ITD pitd;
- PEHCI_SITD psitd;
- PEHCI_SITD_CONTENT psitdc;
- PEHCI_ITD_CONTENT pitdc;
- LIST_ENTRY td_list, *pthis, *pnext, *pprev;
- BOOL toggle, ret;
- KIRQL old_irql;
- PURB_HS_PIPE_CONTENT pipe_content;
- PUSB_DEV pdev;
- PEHCI_ELEM_LINKS pelnk;
-
- if( ehci == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- if( purb->iso_frame_count == 0 )
- return STATUS_INVALID_PARAMETER;
-
- pdev = dev_from_endp( purb->pendp );
- purb->pipe = 0;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- pipe_content->trans_type = USB_ENDPOINT_XFER_ISOC; // bit 0-1
- pipe_content->speed_high = ( pdev->flags & USB_DEV_FLAG_HIGH_SPEED ) ? 1 : 0; // bit 5
- pipe_content->speed_low = 0; // bit 6
- pipe_content->trans_dir = endp_dir( purb->pendp ) == USB_DIR_IN ? 1 : 0; // bit 7
- pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
- pipe_content->endp_addr = endp_num( purb->pendp ); // bit 15-18
- pipe_content->data_toggle = 0; // bit 19
-
- ret = FALSE;
- purb->params[ 0 ] = j = endp_max_packet_size( purb->pendp );
-
- if( pipe_content->speed_high == 0 )
- {
- // check to see if the frame data is too long to transfer
- if( purb->iso_frame_count >= ( LONG )ehci->frame_count )
- return STATUS_INVALID_PARAMETER;
-
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- if( purb->iso_packet_desc[ i ].length > j )
- return STATUS_INVALID_PARAMETER;
- }
- }
- else
- {
- // excess the frame count limit
- if( purb->iso_frame_count >= ( LONG )( ehci->frame_count << 3 ) )
- return STATUS_INVALID_PARAMETER;
-
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- if( purb->iso_packet_desc[ i ].length > j * endp_mult_count( purb->pendp ) ) // 3 is max mult-transaction count
- return STATUS_INVALID_PARAMETER;
- }
-
- pipe_content->mult_count = endp_mult_count( purb->pendp );
- }
-
- pipe_content->max_packet_size = 0; // bit 20-23 log( max_packet_size ), not correct, should not be used
-
- if( pipe_content->speed_high == 0 )
- {
- for( i = 1; i < 16; i ++ )
- {
- if ( ( ( ( ULONG )purb->pendp->pusb_endp_desc->bInterval ) >> i ) == 0 )
- break;
- }
- i--;
- }
- else
- {
- i = purb->pendp->pusb_endp_desc->bInterval - 1;
- }
-
- pipe_content->interval = i; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed
-
- if( ehci_claim_bandwidth( ehci, purb, TRUE ) == FALSE )
- return STATUS_UNSUCCESSFUL;
-
- if( pipe_content->speed_high == 0 )
- {
- td_count = purb->iso_frame_count;
-
- // test to see if the last td needs one more sitd for pure complete-split
- if( pipe_content->trans_dir == 0 )
- {
- j = ( purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length + 187 ) / 188;
- if( purb->iso_packet_desc[ purb->iso_frame_count - 1 ].params.start_uframe + 1 + j >= 8 )
- {
- td_count++;
- ret = TRUE;
- }
- }
- elem_pool_lock( itd_pool, TRUE );
- pelnk = elem_pool_alloc_elems( itd_pool, td_count );
- elem_pool_unlock( itd_pool, TRUE );
-
- }
- else
- {
- i = REAL_INTERVAL;
- if( pipe_content->interval >= 3 )
- {
- td_count = purb->iso_frame_count;
- j = 0;
- }
- else
- {
- j = purb->iso_start_frame & 0x07;
- if( j == 0 )
- {
- td_count = ( purb->iso_frame_count + 8 / i - 1 ) * i / 8;
- }
- else
- {
- j = 1 + ( 7 - j ) / i; // the leading packets from the 8-trans boundary
- td_count = ( j >= ( LONG )purb->iso_frame_count ?
- 1 : 1 + ( purb->iso_frame_count - j + 8 / i - 1 ) * i / 8 );
- }
- }
-
- elem_pool_lock( sitd_pool, TRUE );
- pelnk = elem_pool_alloc_elems( sitd_pool, td_count );
- elem_pool_unlock( sitd_pool, TRUE );
- }
-
- if( pelnk == NULL )
- {
- ehci_claim_bandwidth( ehci, purb, FALSE );
- return STATUS_NO_MORE_ENTRIES;
- }
-
- InsertTailList( &pelnk->elem_link, &td_list );
- ListFirst( &td_list, pthis );
- pprev = pthis;
- purb->td_count = td_count;
-
- //set up offset for high speed and interval == 1
- if( pipe_content->speed_high && pipe_content->interval == 0 )
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- if( i == 0 )
- purb->iso_packet_desc[ i ].offset = 0;
- else
- purb->iso_packet_desc[ i ].offset = purb->iso_packet_desc[ i - 1 ].offset +
- purb->iso_packet_desc[ i ].length;
- }
- }
-
- i = 0, temp = 0;
-
- while( pthis )
- {
- init_elem_phys_part( struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link ) );
- if( pipe_content->speed_high )
- {
- LONG start_uframe, k;
- LONG l, pk_idx, offset, start_uf, td_length;
- PULONG pbuf;
- ULONG phys_addr[ 8 ];
-
- pitd = itd_from_list_entry( pthis );
- pitdc = ( PEHCI_ITD_CONTENT )pitd;
- start_uframe = purb->iso_start_frame & 0x07;
-
- // will be filled later
- pitd->hw_next = EHCI_PTR_TERM;
-
- // DWORD 9;
- pitdc->dev_addr = pdev->dev_addr;
- pitdc->endp_num = endp_num( purb->pendp );
-
- pitdc->max_packet_size = endp_max_packet_size( purb->pendp );
- pitdc->io_dir = pipe_content->trans_dir;
- pitdc->mult = endp_mult_count( purb->pendp );
-
- pbuf = pitd->hw_bufp;
- RtlZeroMemory( phys_addr, sizeof( phys_addr ) );
-
- if( pipe_content->interval < 3 )
- {
- // this indicates one itd schedules more than one uframes
- // for multiple transactions described by iso_packet_desc
- if( i == 0 )
- k = td_count == 1 ? purb->iso_frame_count : j; // the first itd
- else
- k = ( LONG )( purb->iso_frame_count - i ) <= 8 / REAL_INTERVAL
- ? ( purb->iso_frame_count - i ) : 8 / REAL_INTERVAL;
-
- // j is the header transactions out of the interval
- // aligned transactions per td
- if( j > 0 && i == 0 ) // handle the first itd
- start_uf = start_uframe;
- else
- start_uf = start_uframe % REAL_INTERVAL;
- }
- else
- {
- k = 1, start_uf = start_uframe & 0x07;
- }
-
-
- // calculate the data to transfer with this td
- td_length = 0;
- for( l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL )
- {
- td_length += purb->iso_packet_desc[ pk_idx ].length;
- phys_addr[ l ] = MmGetPhysicalAddress( &purb->data_buffer[ purb->iso_packet_desc[ pk_idx ].offset ] ).LowPart;
- }
-
- // fill the page pointer, and offset
- if( pipe_content->interval != 0 )
- {
- for( l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l+= REAL_INTERVAL )
- {
- pitdc->status_slot[ l ].offset = phys_addr[ l ] & ( PAGE_SIZE - 1 );
- pbuf[ l >> pipe_content->interval ] |= phys_addr[ l ] & ( ~( PAGE_SIZE - 1 ) );
- pitdc->status_slot[ l ].page_sel = l >> pipe_content->interval;
- pitdc->status_slot[ l ].status = 0x08;
- pitdc->status_slot[ l ].trans_length = purb->iso_packet_desc[ pk_idx ].length;
- if( PAGE_SIZE - pitdc->status_slot[ l ].offset < ( ULONG )purb->iso_packet_desc[ pk_idx ].length )
- {
- // fill the next page buf, we can not simply add
- // PAGE_SIZE to the phys_addr[ l ].
- pbuf[ ( l >> pipe_content->interval ) + 1 ] |=
- MmGetPhysicalAddress(
- ( PBYTE )( ( ( ULONG )&purb->data_buffer[ purb->iso_packet_desc[ pk_idx ].offset ] ) & ( ~( PAGE_SIZE - 1 ) ) )
- + PAGE_SIZE ).LowPart;
- }
- }
- }
- else // interval == 0
- {
- LONG m, n, n2;
- // fill the page buffer first
- // calculate the page buffer needed
- offset = phys_addr[ 0 ] & ( PAGE_SIZE - 1 );
- if( offset != 0 )
- {
- offset = PAGE_SIZE - offset;
- l = 1 + ( td_length - offset + PAGE_SIZE - 1 ) / PAGE_SIZE;
- }
- else
- {
- l = ( td_length + PAGE_SIZE - 1 ) / PAGE_SIZE;
- }
-
- if( l > 7 )
- TRAP();
-
- // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp
- for( pk_idx = 0; pk_idx < l; pk_idx++ )
- {
- if( pk_idx == 0 )
- {
- offset = phys_addr[ start_uf ] & ( ~( PAGE_SIZE - 1 ) );
- pbuf[ pk_idx ] |= offset;
- n = pk_idx;
- pitdc->status_slot[ 0 ].page_sel = n;
- n2 = start_uf;
- }
- else
- {
- // scan to find if the buf pointer already filled in the td
- // since interval = 1, we do not need k * REAL_INTERVAL
- // k is transaction count for current td,
- // n is hw_bufp( pbuf ) index
- // n2 is the last phys_addr index we stopped
- for( m = n2; m < start_uf + k ; m++ )
- {
- // we can not determine the phys_addr[ x ] is piror
- // to offset if it is less than offset.
- // because phys_addr is discrete.
- // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset )
- // continue;
-
- if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) == ( ULONG )offset )
- {
- pitdc->status_slot[ m ].page_sel = n;
- continue;
- }
- break;
- }
-
- if( m == start_uf + k )
- TRAP();
-
- offset = phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) );
- pbuf[ pk_idx ] |= offset;
- n = pk_idx;
- n2 = m;
- pitdc->status_slot[ m ].page_sel = n;
- }
- }
- // fill offset and others
- for( l = start_uf, pk_idx = i; l < start_uf + k; l++, pk_idx++ )
- {
- pitdc->status_slot[ l ].offset = ( phys_addr[ l ] & ( PAGE_SIZE - 1 ) );
- pitdc->status_slot[ l ].status = 0x08;
- pitdc->status_slot[ l ].trans_length = purb->iso_packet_desc[ pk_idx ].length;
- }
- // exhausted
- }
- i += k;
- }
- else // full/low speed
- {
- psitd = sitd_from_list_entry( pthis );
- psitdc = ( PEHCI_SITD_CONTENT )psitd;
- psitd->hw_next = EHCI_PTR_TERM;
-
- // DWORD 1;
- psitdc->dev_addr = pdev->dev_addr;
- psitdc->endp_num = endp_num( purb->pendp );
- psitdc->hub_addr = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr;
- psitdc->port_idx = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx;
- psitdc->io_dir = endp_dir( purb->pendp );
-
- psitdc->status &= 0x80; // in DWORD 3
-
- // DWORD 2;
- j = ( purb->iso_packet_desc[ i ].length + 187 ) / 188;
-
- if( psitdc->io_dir == 0 )
- {
- for( ; j > 0; j-- )
- {
- psitdc->s_mask |= ( 1 << ( j - 1 ) );
- }
- psitdc->s_mask <<= purb->iso_packet_desc[ i ].params.start_uframe & 0x07;
- psitdc->c_mask = 0;
- }
- else
- {
- LONG k;
-
- psitdc->s_mask = 1 << purb->iso_packet_desc[ i ].params.start_uframe & 0x07;
- // iso split case 2b: ehci spec 1.0
- if( j == 6 )
- j = 5;
-
- j = j - 1 + 2; // actual complete-split count
-
- psitdc->c_mask |= temp >> 8; // the previous sitd's complete split
- if( temp >> 8 ) // link back for sitd split completion
- {
- psitd->hw_backpointer = sitd_from_list_entry( pprev )->phys_addr;
- psitdc->status &= 0x82;
- }
- else
- {
- psitd->hw_backpointer = EHCI_PTR_TERM;
- }
-
- for( k = temp = 0; k < j; k++ )
- {
- temp |= 1 << k;
- }
-
- temp <<= ( ( purb->iso_packet_desc[ i ].params.start_uframe & 0x07 ) + 2 );
-
- // only uframe zero and one have complete split for prev sitd
- if( ( temp >> 8 ) > 3 )
- TRAP();
-
- psitdc->c_mask |= temp & 0xff;
- }
-
- // DWORD 3:
- psitdc->c_prog_mask = 0;
- psitdc->bytes_to_transfer = purb->iso_packet_desc[ i ].length;
- psitdc->page_sel = 0;
- psitdc->ioc = 0;
-
- // DWORD 4;
- j = ( ULONG )( ( PBYTE )purb->data_buffer + purb->iso_packet_desc[ i ].offset );
- psitd->hw_tx_results2 = MmGetPhysicalAddress( ( PVOID )j ).LowPart;
-
- // DWORD 5;
- if( PAGE_SIZE - ( j & ( PAGE_SIZE - 1 ) ) < ( ULONG )purb->iso_packet_desc[ i ].length )
- {
- // need to fill another slot
- psitdc->page1 = MmGetPhysicalAddress ( ( PVOID ) ( ( j & ~( PAGE_SIZE - 1 ) ) + PAGE_SIZE ) ).LowPart >> 12;
- }
-
- if( purb->iso_packet_desc[ i ].length > 188 )
- psitdc->trans_pos = 0x00;
- else if( purb->iso_packet_desc[ i ].length <= 188 )
- psitdc->trans_pos = 0x01;
-
- if( psitdc->io_dir == 0 )
- psitdc->trans_count = ( purb->iso_packet_desc[ i ].length + 187 ) / 188;
-
- }
- ListNext( &td_list, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
-
- }
-
- if( pipe_content->speed_high == 0 )
- {
- // has an extra sitd to fill at the tail
- if( ret )
- {
- ListFirstPrev( &td_list, pthis );
- init_elem_phys_part( struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link ) );
-
- psitd = sitd_from_list_entry( pthis );
- psitdc = ( PEHCI_SITD_CONTENT )psitd;
- psitd->hw_next = EHCI_PTR_TERM;
-
- // DWORD 1;
- psitdc->dev_addr = pdev->dev_addr;
- psitdc->endp_num = endp_num( purb->pendp );
- psitdc->hub_addr = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->hub_addr;
- psitdc->port_idx = ( ( PURB_HS_CONTEXT_CONTENT )&purb->hs_context )->port_idx;
- psitdc->io_dir = endp_dir( purb->pendp );
-
- psitdc->status &= 0x80; // in DWORD 3
-
- // DWORD 2;
- psitdc->s_mask = 0x04; // uframe 2, random selection
-
- psitdc->c_mask = 0x70; // complete split at uframe 4, 5, 6
- ListFirstPrev( pthis, pprev );
- psitd->hw_backpointer = sitd_from_list_entry( pprev )->phys_addr;
- psitdc->status &= 0x82;
-
- // DWORD 3:
- psitdc->c_prog_mask = 0;
- psitdc->bytes_to_transfer = 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length;
- psitdc->page_sel = 0;
-
- j = ( ULONG )( ( PBYTE )purb->data_buffer + purb->iso_packet_desc[ purb->iso_frame_count - 1 ].offset );
- // the last byte is overridden.
- j += purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length - 1;
- psitd->hw_tx_results2 = MmGetPhysicalAddress( ( PVOID )j ).LowPart;
- }
-
- // set the interrupt
- ListFirstPrev( &td_list, pthis );
- psitdc = ( PEHCI_SITD_CONTENT )sitd_from_list_entry( pthis );
- psitdc->ioc = 1;
- }
- else
- {
- // set the ioc
- ListFirstPrev( &td_list, pthis );
- pitdc = ( PEHCI_ITD_CONTENT )itd_from_list_entry( pthis );
- for( i = 7; i >= 0; i-- )
- {
- if( pitdc->status_slot[ i ].status = 0x08 )
- {
- pitdc->status_slot[ i ].ioc = 1;
- break;
- }
- }
- if( i < 0 )
- TRAP();
- }
-
- ListFirst( &td_list, pthis );
- // ListFirst( &purb->trasac_list, pthis )
- RemoveEntryList( &td_list );
- InsertTailList( pthis, &purb->trasac_list );
-
- while( pthis )
- {
- // fill the purb ptr
- struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link )->purb = purb;
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
-
- //indirectly guarded by pending_endp_list_lock
- usb_endp_busy_count_inc( purb->pendp );
- ehci_insert_urb_to_schedule( ehci, purb, ret );
-
- if( ret == FALSE )
- {
- // usb_endp_busy_count_dec( purb->pendp );
-
- ListFirst( &purb->trasac_list, pthis );
- RemoveEntryList( &purb->trasac_list );
-
- elem_safe_free( pthis, FALSE );
- ehci_claim_bandwidth( ehci, purb, FALSE );
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
-}
+ purb->td_count = td_count;
+ pqhc = (PEHCI_QH_CONTENT) pqh;
+ pqh->hw_next = EHCI_PTR_TERM; // filled later
+ pqhc->dev_addr = pipe_content->dev_addr;
+ pqhc->inactive = 0;
+ pqhc->endp_addr = pipe_content->endp_addr;
+ pqhc->data_toggle = 0; //pipe_content->data_toggle;
+ pqhc->is_async_head = 0;
+ pqhc->max_packet_size = (1 << pipe_content->max_packet_size);
+ pqhc->is_ctrl_endp = 0;
+ pqhc->reload_counter = EHCI_NAK_RL_COUNT;
+
+ if (pipe_content->speed_high)
+ pqhc->endp_spd = USB_SPEED_HIGH;
+ else if (pipe_content->speed_low)
+ pqhc->endp_spd = USB_SPEED_LOW;
+ else
+ pqhc->endp_spd = USB_SPEED_FULL;
+
+ pqh->hw_info2 = 0;
+ pqhc->mult = 1;
+ pqh->hw_current = 0;
+ pqh->hw_qtd_next = 0; // filled later
+ pqh->hw_alt_next = EHCI_PTR_TERM;
+ pqh->hw_token = 0; //indicate to advance queue before execution
+
+ if (!pipe_content->speed_high)
+ {
+ pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
+ pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
+ }
-BOOLEAN
-ehci_sync_insert_urb_schedule(
-PVOID context
-)
-//this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule
-{
- PSYNC_PARAM sync_param;
- PEHCI_DEV ehci;
- PURB purb;
+ ptd = qtd_from_list_entry(pthis);
+ ehci_insert_tds_qh(ehci, pqh, ptd);
+ ehci_insert_qh_urb(purb, pqh);
+ purb->pendp->flags =
+ (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
+ usb_endp_busy_count_inc(purb->pendp);
+ ehci_insert_urb_to_schedule(ehci, purb, ret);
- sync_param = ( PSYNC_PARAM ) context;
- if( sync_param == NULL )
- return FALSE;
+ if (ret == FALSE)
+ {
+ // undo all we have done
+ ListFirst(&pqh->elem_head_link->elem_link, pthis);
- ehci = sync_param->ehci;
- purb = ( PURB )sync_param->context;
+ RemoveEntryList(&purb->trasac_list);
+ RemoveEntryList(&pqh->elem_head_link->elem_link); //remove qh from td_chain
- if( ehci == NULL || purb == NULL )
- return ( UCHAR )sync_param->ret = FALSE;
+ elem_safe_free(pthis, FALSE);
+ elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
- return ( UCHAR )( sync_param->ret = ehci_insert_urb_schedule( ehci, purb ) );
+ InitializeListHead(&purb->trasac_list);
+ // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback
+ purb->pendp->flags =
+ (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
}
-BOOLEAN
-ehci_sync_cancel_urb(
-PVOID context
-)
+static NTSTATUS
+ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb)
{
- //cancel a single purb
- PEHCI_DEV ehci;
- PSYNC_PARAM sync_param;
- PURB purb2, dest_urb;
- PLIST_ENTRY pthis, pnext;
- BOOL found = FALSE;
-
- if( context == NULL )
- return FALSE;
-
- sync_param = ( PSYNC_PARAM )context;
- ehci = sync_param->ehci;
- dest_urb = ( PURB )sync_param->context;
-
- if( ehci == NULL || dest_urb == NULL )
- return ( UCHAR )sync_param->ret = FALSE;
-
- ListFirst( &ehci->urb_list, pthis );
- while( pthis )
- {
- purb2 = ( PURB ) pthis;
- if( purb2 == dest_urb )
- {
- found = TRUE;
- purb2->flags |= URB_FLAG_FORCE_CANCEL;
- break;
- }
- ListNext( &ehci->urb_list, pthis, pnext );
- pthis = pnext;
- }
-
- if( found )
- {
- press_doorbell( ehci );
- }
- return ( UCHAR )( sync_param->ret = found );
-}
-NTSTATUS
-ehci_cancel_urb(
-PEHCI_DEV ehci,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
-//note any fields of the purb can not be referenced unless it is found in some queue
-{
+ LIST_ENTRY td_list, *pthis, *pnext;
+ LONG i, j, td_count;
+ LONG toggle;
+ LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx;
+
+ PEHCI_QTD ptd;
+ PEHCI_QH pqh;
+ PEHCI_QH_CONTENT pqhc;
+ UCHAR dev_addr;
+ BOOL ret;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PEHCI_QTD_CONTENT ptdc;
+ PEHCI_ELEM_LINKS pelnk;
+ PUSB_DEV pdev;
+
+ if (ehci == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ bytes_rest = purb->rest_bytes;
+ bytes_to_transfer = purb->bytes_to_transfer;
+ max_packet_size = endp_max_packet_size(purb->pendp);
+ start_idx = purb->data_length - purb->rest_bytes;
+
+ calc_td_count(purb, start_idx, td_count);
+ td_count += 2; // add setup td and handshake td
+
+ elem_pool_lock(qtd_pool, TRUE);
+ pelnk = elem_pool_alloc_elems(qtd_pool, td_count);
+ elem_pool_unlock(qtd_pool, TRUE);
+
+ if (pelnk == NULL)
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
- NTSTATUS status;
- PLIST_ENTRY pthis, pnext;
- BOOL found;
- PURB purb2;
-
- SYNC_PARAM sync_param;
-
- USE_IRQL;
-
- if( ehci == NULL || purb == NULL || pdev == NULL || pendp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- lock_dev( pdev, FALSE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- //delegate to remove device for this job
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- if( dev_from_endp( pendp ) != pdev )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_INVALID_PARAMETER;
- }
-
- if( endp_state( pendp ) == USB_ENDP_FLAG_STALL )
- {
- //it will be canceled in ehci_process_pending_endp
- unlock_dev( pdev, FALSE );
- return USB_STATUS_ENDPOINT_HALTED;
- }
-
- found = FALSE;
- ListFirst( &pendp->urb_list, pthis );
- while( pthis )
- {
- purb2 = ( PURB ) pthis;
- if( purb2 == purb )
- {
- found = TRUE;
- RemoveEntryList( pthis );
- InitializeListHead( pthis );
- break;
- }
- ListNext( &pendp->urb_list, pthis, pnext );
- pthis = pnext;
- }
- unlock_dev( pdev, FALSE );
-
- if( found )
- {
- purb->status = STATUS_CANCELLED;
-
- ehci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, FALSE );
- pdev->ref_count --;
- unlock_dev( pdev, FALSE );
- return STATUS_SUCCESS;
- }
-
- // search the purb in the purb-list and try to cancel
- sync_param.ehci = ehci;
- sync_param.context = purb;
-
- KeSynchronizeExecution( ehci->pdev_ext->ehci_int, ehci_sync_cancel_urb, &sync_param );
-
- found = sync_param.ret;
-
- if( found )
- return USB_STATUS_CANCELING;
-
- return STATUS_INVALID_PARAMETER;
-}
+ InsertTailList(&pelnk->elem_link, &td_list);
+ ListFirst(&td_list, pthis);
+ ListNext(&td_list, pthis, pnext);
-VOID
-ehci_generic_urb_completion(
-PURB purb,
-PVOID context
-)
-{
- PUSB_DEV pdev;
- KIRQL cur_irql;
- BOOL is_ctrl;
- USE_IRQL;
-
- old_irql = KeGetCurrentIrql();
- if( old_irql > DISPATCH_LEVEL )
- TRAP();
-
- if( old_irql < DISPATCH_LEVEL )
- KeRaiseIrql(DISPATCH_LEVEL, &old_irql);
-
- pdev = purb->pdev;
- if( purb == NULL )
- goto LBL_LOWER_IRQL;
-
- if( pdev == NULL )
- goto LBL_LOWER_IRQL;
-
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- // no need to do following statistics
- unlock_dev( pdev, TRUE );
- goto LBL_CLIENT_PROCESS;
- }
- if( usb_error( purb->status ) )
- {
- pdev->error_count++;
- }
-
- if( purb->pendp == &pdev->default_endp )
- {
- if( usb_halted( purb->status ) )
- {
- pdev->time_out_count++;
- if( pdev->time_out_count > 3 )
- {
- dev_set_state( pdev, USB_DEV_STATE_ZOMB );
- ehci_dbg_print( DBGLVL_MAXIMUM, ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n", pdev ) );
- }
- }
- else
- pdev->time_out_count = 0;
-
- }
-
- is_ctrl = FALSE;
- if( endp_type( purb->pendp ) == USB_ENDPOINT_XFER_CONTROL )
- is_ctrl = TRUE;
-
- unlock_dev( pdev, TRUE );
-
-LBL_CLIENT_PROCESS:
- if( !is_ctrl )
- {
- if( purb->completion )
- purb->completion( purb, context );
- }
- else
- {
- PCTRL_REQ_STACK pstack;
- if( purb->ctrl_req_context.ctrl_stack_count == 0 )
- {
- if( purb->completion )
- purb->completion( purb, context );
- }
- else
- {
- // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
- // if( pstack->urb_completion )
- // pstack->urb_completion( purb, pstack->context );
- usb_call_ctrl_completion( purb );
- }
- }
-
-LBL_LOWER_IRQL:
- if( old_irql < DISPATCH_LEVEL )
- KeLowerIrql( old_irql );
-
- return;
-}
+ ptd = qtd_from_list_entry(pthis);
-NTSTATUS
-ehci_rh_submit_urb(
-PUSB_DEV pdev,
-PURB purb
-)
-{
- PUSB_DEV_MANAGER dev_mgr;
- PTIMER_SVC ptimer;
- PUSB_CTRL_SETUP_PACKET psetup;
- PEHCI_DEV ehci;
- NTSTATUS status;
- PHUB2_EXTENSION hub_ext;
- PUSB_PORT_STATUS ps, psret;
- LONG i;
- UCHAR port_count;
-
- USE_IRQL;
- if( pdev == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- dev_mgr = dev_mgr_from_dev( pdev );
-
- KeAcquireSpinLock( &dev_mgr->timer_svc_list_lock, &old_irql );
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- ehci = ehci_from_hcd( pdev->hcd );
- psetup = ( PUSB_CTRL_SETUP_PACKET ) purb->setup_packet;
-
- hub_ext = ( ( PHUB2_EXTENSION )pdev->dev_ext );
- port_count = ( UCHAR )( ( PEHCI_HCS_CONTENT )&ehci->ehci_caps.hcs_params )->port_count;
-
- switch( endp_type( purb->pendp ) )
- {
- case USB_ENDPOINT_XFER_CONTROL:
- {
- if( psetup->bmRequestType == 0xa3 \
- && psetup->bRequest == USB_REQ_GET_STATUS )
- {
- //get-port-status
- if( psetup->wIndex == 0 \
- || psetup->wIndex > port_count\
- || psetup->wLength < 4 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- i = EHCI_PORTSC + 4 * ( psetup->wIndex - 1 ); // USBPORTSC1;
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + i ) );
- ps = &hub_ext->rh_port_status[ psetup->wIndex ];
-
- psret = ( PUSB_PORT_STATUS )purb->data_buffer;
- ps->wPortStatus = 0;
-
- if( status & PORT_CCS )
- {
- ps->wPortStatus |= USB_PORT_STAT_CONNECTION;
- }
- if( status & PORT_PE )
- {
- ps->wPortStatus |= USB_PORT_STAT_ENABLE;
- ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec
- }
- if( status & PORT_PR )
- {
- ps->wPortStatus |= USB_PORT_STAT_RESET;
- }
- if( status & PORT_SUSP )
- {
- ps->wPortStatus |= USB_PORT_STAT_SUSPEND;
- }
- if( PORT_USB11( status ) )
- {
- ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED;
- }
-
- //always power on
- ps->wPortStatus |= USB_PORT_STAT_POWER;
-
- //now set change field
- if( ( status & PORT_CSC ) && !( ps->wPortStatus & USB_PORT_STAT_LOW_SPEED ) )
- {
- ps->wPortChange |= USB_PORT_STAT_C_CONNECTION;
- }
- if( ( status & PORT_PEC ) && !( ps->wPortStatus & USB_PORT_STAT_LOW_SPEED ) )
- {
- ps->wPortChange |= USB_PORT_STAT_C_ENABLE;
- }
-
- //don't touch other fields, might be filled by
- //other function
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( \
- "ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n", \
- ps->wPortStatus,
- ps->wPortChange,
- ps ) );
-
- psret->wPortChange = ps->wPortChange;
- psret->wPortStatus = ps->wPortStatus;
-
- purb->status = STATUS_SUCCESS;
-
- break;
- }
- else if( psetup->bmRequestType == 0x23 \
- && psetup->bRequest == USB_REQ_CLEAR_FEATURE )
- {
- //clear-port-feature
- if( psetup->wIndex == 0 || psetup->wIndex > port_count )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- i = EHCI_PORTSC + 4 * ( psetup->wIndex - 1 ); // USBPORTSC1;
- ps = &hub_ext->rh_port_status[ psetup->wIndex ];
-
- purb->status = STATUS_SUCCESS;
- switch( psetup->wValue )
- {
- case USB_PORT_FEAT_C_CONNECTION:
- {
- SET_RH2_PORTSTAT( i, USBPORTSC_CSC );
- status = EHCI_READ_PORT_ULONG( ( PULONG ) ( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex ) );
- ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
- break;
- }
- case USB_PORT_FEAT_C_ENABLE:
- {
- SET_RH2_PORTSTAT( i, USBPORTSC_PEC );
- status = EHCI_READ_PORT_ULONG( ( PULONG ) ( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex ) );
- ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE;
- break;
- }
- case USB_PORT_FEAT_C_RESET:
- {
- ps->wPortChange &= ~USB_PORT_STAT_C_RESET;
- //the reset signal is down in rh_timer_svc_reset_port_completion
- // enable or not is set by host controller
- // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n", psetup->wIndex ) );
- break;
- }
- case USB_PORT_FEAT_ENABLE:
- {
- ps->wPortStatus &= ~USB_PORT_STAT_ENABLE;
- CLR_RH2_PORTSTAT( i, USBPORTSC_PE );
- status = EHCI_READ_PORT_ULONG( ( PULONG ) ( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex ) );
- break;
- }
- default:
- purb->status = STATUS_UNSUCCESSFUL;
- }
- break;
- }
- else if( psetup->bmRequestType == 0xd3 \
- && psetup->bRequest == HUB_REQ_GET_STATE )
- {
- // get bus state
- if( psetup->wIndex == 0 ||\
- psetup->wIndex > port_count ||\
- psetup->wLength == 0 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- i = EHCI_PORTSC + 4 * ( psetup->wIndex - 1 ); // USBPORTSC1;
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + i ) );
- purb->data_buffer[ 0 ] = ( status & USBPORTSC_LS );
-
- // reverse the order
- purb->data_buffer[ 0 ] ^= 0x3;
- purb->status = STATUS_SUCCESS;
- break;
- }
- else if( psetup->bmRequestType == 0x23 \
- && psetup->bRequest == USB_REQ_SET_FEATURE )
- {
- //reset port
- if( psetup->wValue != USB_PORT_FEAT_RESET )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- ehci_dbg_print( DBGLVL_MAXIMUM, ("ehci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue ) );
- break;
- }
-
- i = EHCI_PORTSC + 4 * ( psetup->wIndex - 1 ); // USBPORTSC1;
-
- ptimer = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms
- ptimer->context = ( ULONG )purb;
- ptimer->pdev = pdev;
- ptimer->func = rh_timer_svc_reset_port_completion;
-
- //start the timer
- pdev->ref_count += 2; //one for timer and one for purb
-
- status = EHCI_READ_PORT_ULONG( ( PULONG ) ( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status ) );
- InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link );
- purb->status = STATUS_PENDING;
- }
- else
- {
- purb->status = STATUS_INVALID_PARAMETER;
- }
- break;
- }
- case USB_ENDPOINT_XFER_INT:
- {
- ptimer = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- ptimer->threshold = RH_INTERVAL;
- ptimer->context = ( ULONG )purb;
- ptimer->pdev = pdev;
- ptimer->func = rh_timer_svc_int_completion;
-
- //start the timer
- InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link );
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count ) );
- pdev->ref_count += 2; //one for timer and one for purb
-
- purb->status = STATUS_PENDING;
- break;
- }
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_ISOC:
- default:
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
- }
- unlock_dev( pdev, FALSE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return purb->status;
-}
+ pdev = dev_from_endp(purb->pendp);
+ dev_addr = pdev->dev_addr;
-//must have rh dev_lock acquired
-BOOL
-ehci_rh_reset_port(
-PHCD hcd,
-UCHAR port_idx
-)
-{
- ULONG i;
- PEHCI_DEV ehci;
- ULONG status;
- UCHAR port_count;
-
- if( hcd == NULL )
- return FALSE;
-
- ehci = ehci_from_hcd( hcd );
- port_count = ( UCHAR )( ( PEHCI_HCS_CONTENT )&ehci->ehci_caps.hcs_params )->port_count;
-
- if( port_idx < 1 || port_idx > port_count )
- return FALSE;
-
- i = ( ULONG )( EHCI_PORTSC + 4 * ( port_idx - 1 ) );
-
- // assert the reset signal,(implicitly disable the port)
- SET_RH2_PORTSTAT( i, PORT_PR );
-
- usb_wait_ms_dpc( 50 );
- // clear the reset signal, delay port enable till clearing port feature
- CLR_RH2_PORTSTAT( i, PORT_PR );
-
- // wait the port stable
- usb_wait_ms_dpc( 2 );
-
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + i ) );
- if( !( status & PORT_PE ) )
- {
- // release the ownership from ehci to companion hc
- status |= PORT_OWNER;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( ehci->port_base + i ), status );
- // the host controller will set PORTSC automatically
- return FALSE;
- }
- usb_wait_us_dpc( 10 );
- // SET_RH_PORTSTAT( i, PORT_PE );
-
- //recovery time 10ms
- usb_wait_ms_dpc( 10 );
-
- // clear PORT_PEC and PORT_PCC
- SET_RH2_PORTSTAT( i, 0x0a );
-
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_reset_port(): status after written=0x%x\n", status ) );
- return TRUE;
-}
+ if (dev_state(pdev) <= USB_DEV_STATE_RESET) //only valid for control transfer
+ dev_addr = 0;
-NTSTATUS
-ehci_dispatch_irp(
-IN PDEVICE_OBJECT DeviceObject,
-IN PIRP irp
-)
-{
- PEHCI_DEVICE_EXTENSION pdev_ext;
- PUSB_DEV_MANAGER dev_mgr;
- PEHCI_DEV ehci;
-
- pdev_ext = DeviceObject->DeviceExtension;
- ehci = pdev_ext->ehci;
-
- dev_mgr = ehci->hcd_interf.hcd_get_dev_mgr( &ehci->hcd_interf );
- return dev_mgr_dispatch( dev_mgr, irp );
-}
+ usb_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr));
-//the following are for hcd interface methods
-VOID
-ehci_set_dev_mgr(
-PHCD hcd,
-PUSB_DEV_MANAGER dev_mgr
-)
+ // fill the setup packet
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+ ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
+ ptd->hw_alt_next = EHCI_PTR_TERM;
+ ptdc->status = 0x80; // active
+ ptdc->pid = QTD_PID_SETUP;
+ ptdc->err_count = 3;
+ ptdc->cur_page = 0;
+ ptdc->ioc = 0;
+ ptdc->bytes_to_transfer = sizeof(USB_CTRL_SETUP_PACKET);
+ ptdc->data_toggle = 0;
+ ptd->hw_buf[0] = MmGetPhysicalAddress(purb->setup_packet).LowPart;
-{
- hcd->dev_mgr = dev_mgr;
-}
+ for(i = 1; i < 16; i++)
+ {
+ if ((max_packet_size >> i) == 0)
+ break;
+ }
+ i--;
+ i &= 0xf;
+
+ purb->pipe = 0;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ pipe_content->max_packet_size = i;
+ pipe_content->endp_addr = endp_num(purb->pendp);
+ pipe_content->dev_addr = dev_addr;
+ pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0;
+ pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0;
+ pipe_content->trans_type = USB_ENDPOINT_XFER_CONTROL;
+
+ pthis = pnext;
+ ListNext(&td_list, pthis, pnext);
+
+ // all the tds's toggle and data_buffer pointer is filled here
+ toggle = 1;
+ ehci_fill_td_buf_ptr(purb, start_idx, pthis, td_count - 2, toggle);
+
+ for(i = 0; ((i < td_count - 2) && pthis); i++)
+ {
+ //construct tds for DATA packets of data stage.
+ ptd = qtd_from_list_entry(pthis);
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+ ptd->hw_alt_next = EHCI_PTR_TERM;
+ ptdc->status = 0x80; // active and startXSplit
+ ptdc->pid = ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT);
+ ptdc->err_count = 3;
+ ptdc->cur_page = 0;
+ ptdc->ioc = 0;
+
+ if (pnext)
+ ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
+ else
+ ptd->hw_next = EHCI_PTR_TERM;
+
+ pthis = pnext;
+ if (pthis)
+ ListNext(&td_list, pthis, pnext);
+ }
+
+ if (pthis)
+ ptd->hw_next = qtd_from_list_entry(pthis)->phys_addr;
+ else
+ TRAP();
+
+ // ListFirstPrev( &td_list, pthis );
+ ptd = qtd_from_list_entry(pthis);
+
+ //the last is an IN transaction
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+ ptd->hw_alt_next = EHCI_PTR_TERM;
+ ptdc->status = 0x80;
+ ptdc->pid = ((td_count > 2)
+ ? ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_OUT : QTD_PID_IN) : QTD_PID_IN);
+
+ ptdc->err_count = 3;
+ ptdc->cur_page = 0;
+ ptdc->ioc = 1;
+ ptdc->bytes_to_transfer = 0;
+ ptdc->data_toggle = 1;
+ ptd->hw_next = EHCI_PTR_TERM;
+
+ ListFirst(&td_list, pthis);
+ RemoveEntryList(&td_list);
+
+ ptd = qtd_from_list_entry(pthis);
+ elem_pool_lock(qh_pool, TRUE);
+ pelnk = elem_pool_alloc_elem(qh_pool);
+ elem_pool_unlock(qh_pool, TRUE);
+
+ if (pelnk == NULL)
+ {
+ elem_safe_free(pthis, FALSE);
+ return STATUS_NO_MORE_ENTRIES;
+
+ }
+ pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ pqhc = (PEHCI_QH_CONTENT) pqh;
+
+ pqh->hw_alt_next = pqh->hw_next = EHCI_PTR_TERM;
+
+ pqhc->dev_addr = dev_addr;
+ pqhc->inactive = 0;
+ pqhc->endp_addr = endp_num(purb->pendp);
+
+ if (pipe_content->speed_high)
+ pqhc->endp_spd = USB_SPEED_HIGH;
+ else if (pipe_content->speed_low)
+ pqhc->endp_spd = USB_SPEED_LOW;
+ else
+ pqhc->endp_spd = USB_SPEED_FULL;
+
+ pqhc->data_toggle = 1; // use dt from qtd
+ pqhc->is_async_head = 0;
+ pqhc->max_packet_size = endp_max_packet_size(purb->pendp);
+
+ if (pipe_content->speed_high == 0)
+ pqhc->is_ctrl_endp = 1;
+ else
+ pqhc->is_ctrl_endp = 0;
+
+ pqhc->reload_counter = EHCI_NAK_RL_COUNT;
+
+ // DWORD 2
+ pqh->hw_info2 = 0;
+ pqhc->mult = 1;
+
+ if (!pipe_content->speed_high)
+ {
+ pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
+ pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
+ }
+
+ purb->td_count = td_count;
+
+ ehci_insert_tds_qh(ehci, pqh, ptd);
+ ehci_insert_qh_urb(purb, pqh);
+
+ usb_endp_busy_count_inc(purb->pendp);
+ ehci_insert_urb_to_schedule(ehci, purb, ret);
+
+ if (ret == FALSE)
+ {
+ RemoveEntryList(&purb->trasac_list);
+ RemoveEntryList(&pqh->elem_head_link->elem_link);
+
+ elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
+ elem_safe_free(pthis, FALSE);
+
+ InitializeListHead(&purb->trasac_list);
+ // usb_endp_busy_count_dec( purb->pendp );
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb)
+{
+ LIST_ENTRY td_list, *pthis, *pnext;
+ LONG i, max_packet_size;
+ PEHCI_QTD ptd;
+ BOOL ret;
+ PUSB_DEV pdev;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ UCHAR mult_trans, toggle, old_toggle;
+ PEHCI_ELEM_LINKS pelnk;
+ PEHCI_QTD_CONTENT ptdc;
+ PEHCI_QH pqh;
+ PEHCI_QH_CONTENT pqhc;
+ PEHCI_FSTN pfstn;
+
+ if (ehci == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE;
+ max_packet_size = endp_max_packet_size(purb->pendp);
+ pdev = dev_from_endp(purb->pendp);
+
+ if (max_packet_size == 0 || max_packet_size > 64)
+ return STATUS_INVALID_PARAMETER;
+
+ if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
+ {
+ if (max_packet_size < purb->data_length)
+ return STATUS_INVALID_PARAMETER;
+
+ for(i = 1; i < 16; i++)
+ {
+ if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0)
+ break;
+ }
+ i--;
+ mult_trans = 1;
+ }
+ else
+ {
+ mult_trans = endp_mult_count(purb->pendp);
+ if (max_packet_size * endp_mult_count(purb->pendp) < purb->data_length)
+ return STATUS_INVALID_PARAMETER;
+ i = purb->pendp->pusb_endp_desc->bInterval - 1;
+ }
+
+ purb->pipe = 0;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ pipe_content->interval = i;
+ pipe_content->trans_type = USB_ENDPOINT_XFER_INT; // bit 0-1
+ pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5
+ pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0; // bit 6
+ pipe_content->trans_dir = endp_dir(purb->pendp) == USB_DIR_IN ? 1 : 0; // bit 7
+ pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
+ pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18
+ pipe_content->data_toggle = 1; // bit 19
+ pipe_content->mult_count = mult_trans;
+
+ // pipe_content->start_uframe : 3; // bit 28-30 will be filled later
+
+ for(i = 1; i <= 16; i++)
+ {
+ if (((ULONG) max_packet_size) >> i)
+ continue;
+ else
+ break;
+ }
+ i--;
+ i &= 0xf;
+
+ pipe_content->max_packet_size = i; // bit 20-23 log2( max_packet_size )
+
+ if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE)
+ {
+ // can not allocate bandwidth for it
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // one qtd is enough
+ elem_pool_lock(qtd_pool, TRUE);
+ pelnk = elem_pool_alloc_elem(qtd_pool);
+ elem_pool_unlock(qtd_pool, TRUE);
+
+ if (pelnk == NULL)
+ {
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ ptdc = (PEHCI_QTD_CONTENT) ptd;
+ ptd->hw_next = EHCI_PTR_TERM;
+ // DWORD 1
+ ptd->hw_alt_next = EHCI_PTR_TERM;
+ // DWORD 2
+ ptdc->status = 0x80;
+ ptdc->pid = pipe_content->trans_dir ? QTD_PID_IN : QTD_PID_OUT;
+ ptdc->err_count = 3;
+ ptdc->cur_page = 0;
+ ptdc->ioc = 1;
+ ptdc->bytes_to_transfer = purb->data_length;
+ toggle = (UCHAR) ehci_fill_td_buf_ptr(purb, 0, &pelnk->elem_link, 1, toggle);
+
+ elem_pool_lock(qh_pool, TRUE);
+ pelnk = elem_pool_alloc_elem(qh_pool);
+ elem_pool_unlock(qh_pool, TRUE);
+ if (pelnk == NULL)
+ {
+ elem_safe_free(&ptd->elem_head_link->elem_link, TRUE);
+ InitializeListHead(&purb->trasac_list);
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ pqhc = (PEHCI_QH_CONTENT) pqh;
+
+ pqh->hw_next = EHCI_PTR_TERM;
+ pqhc->dev_addr = pdev->dev_addr;
+ pqhc->inactive = 0;
+ pqhc->endp_addr = endp_num(purb->pendp);
+
+ if (pipe_content->speed_high)
+ pqhc->endp_spd = USB_SPEED_HIGH;
+ else if (pipe_content->speed_low)
+ pqhc->endp_spd = USB_SPEED_LOW;
+ else
+ pqhc->endp_spd = USB_SPEED_FULL;
+
+ pqhc->data_toggle = 0;
+ pqhc->is_async_head = 0;
+ pqhc->max_packet_size = endp_max_packet_size(purb->pendp);
+ pqhc->is_ctrl_endp = 0;
+ pqhc->reload_counter = 0;
+
+ // DWORD 2
+ pqh->hw_info2 = 0;
+ pqhc->mult = mult_trans;
+
+ if (pipe_content->speed_high)
+ {
+ if (pipe_content->interval == 0) // one poll per uframe
+ pqhc->s_mask = 0xff;
+ else if (pipe_content->interval == 1) // one poll every 2 uframe
+ pqhc->s_mask = pipe_content->start_uframe == 0 ? 0x55 : 0xbb;
+ else if (pipe_content->interval == 2)
+ {
+ pqhc->s_mask = 0x11;
+ pqhc->s_mask <<= pipe_content->start_uframe;
+ }
+ else
+ {
+ pqhc->s_mask = 1 << (pipe_content->start_uframe);
+ }
+ pqhc->c_mask = 0;
+ }
+ else // full/low speed
+ {
+ pqhc->s_mask = 1 << pipe_content->start_uframe;
+ if (pipe_content->start_uframe < 4)
+ {
+ pqhc->c_mask = 0x07 << (pipe_content->start_uframe + 2);
+ }
+ else if (pipe_content->start_uframe == 4)
+ {
+ pqhc->c_mask = 0xc1;
+ }
+ else if (pipe_content->start_uframe >= 5)
+ {
+ // we need fstn
+ pqhc->c_mask = 0x03;
+ if (pipe_content->start_uframe == 5)
+ {
+ pqhc->c_mask |= 0x80;
+ }
+ }
+ if (pipe_content->start_uframe >= 4)
+ {
+ // chain an fstn
+ elem_pool_lock(fstn_pool, TRUE);
+ pelnk = elem_pool_alloc_elem(fstn_pool);
+ elem_pool_unlock(fstn_pool, TRUE);
+ if (pelnk == NULL)
+ {
+ elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
+ elem_safe_free(&ptd->elem_head_link->elem_link, TRUE);
+ InitializeListHead(&purb->trasac_list);
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ pfstn = (PEHCI_FSTN) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ pfstn->hw_prev = ptd->phys_addr;
+ pfstn->elem_head_link->purb = purb;
+ InsertTailList(&ptd->elem_head_link->elem_link, &pfstn->elem_head_link->elem_link);
+ }
+ pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
+ pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
+ }
+
+ // DWORD 3
+ purb->td_count = 1;
+
+ InitializeListHead(&purb->trasac_list);
+ ehci_insert_tds_qh(ehci, pqh, ptd);
+ ehci_insert_qh_urb(purb, pqh);
+
+ purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle << 31);
+ usb_endp_busy_count_inc(purb->pendp);
+
+ ehci_insert_urb_to_schedule(ehci, purb, ret);
+
+ if (ret == FALSE)
+ {
+ RemoveEntryList(&purb->trasac_list);
+ RemoveEntryList(&pqh->elem_head_link->elem_link);
+
+ elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
+ // an fstn may follow the td
+ elem_safe_free(&ptd->elem_head_link->elem_link, FALSE);
+
+ InitializeListHead(&purb->trasac_list);
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+
+ purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | ((toggle ^ 1) << 31);
+ // usb_endp_busy_count_dec( purb->pendp );
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb)
+{
+ LONG i, j, td_count, temp;
+ PEHCI_ITD pitd;
+ PEHCI_SITD psitd;
+ PEHCI_SITD_CONTENT psitdc;
+ PEHCI_ITD_CONTENT pitdc;
+ LIST_ENTRY td_list, *pthis, *pnext, *pprev;
+ BOOL toggle, ret;
+ KIRQL old_irql;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PUSB_DEV pdev;
+ PEHCI_ELEM_LINKS pelnk;
+
+ if (ehci == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (purb->iso_frame_count == 0)
+ return STATUS_INVALID_PARAMETER;
+
+ pdev = dev_from_endp(purb->pendp);
+ purb->pipe = 0;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ pipe_content->trans_type = USB_ENDPOINT_XFER_ISOC; // bit 0-1
+ pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5
+ pipe_content->speed_low = 0; // bit 6
+ pipe_content->trans_dir = endp_dir(purb->pendp) == USB_DIR_IN ? 1 : 0; // bit 7
+ pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
+ pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18
+ pipe_content->data_toggle = 0; // bit 19
+
+ ret = FALSE;
+ purb->params[0] = j = endp_max_packet_size(purb->pendp);
+
+ if (pipe_content->speed_high == 0)
+ {
+ // check to see if the frame data is too long to transfer
+ if (purb->iso_frame_count >= (LONG) ehci->frame_count)
+ return STATUS_INVALID_PARAMETER;
+
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ if (purb->iso_packet_desc[i].length > j)
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ // excess the frame count limit
+ if (purb->iso_frame_count >= (LONG) (ehci->frame_count << 3))
+ return STATUS_INVALID_PARAMETER;
+
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ if (purb->iso_packet_desc[i].length > j * endp_mult_count(purb->pendp)) // 3 is max mult-transaction count
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ pipe_content->mult_count = endp_mult_count(purb->pendp);
+ }
+
+ pipe_content->max_packet_size = 0; // bit 20-23 log( max_packet_size ), not correct, should not be used
+
+ if (pipe_content->speed_high == 0)
+ {
+ for(i = 1; i < 16; i++)
+ {
+ if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0)
+ break;
+ }
+ i--;
+ }
+ else
+ {
+ i = purb->pendp->pusb_endp_desc->bInterval - 1;
+ }
+
+ pipe_content->interval = i; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed
+
+ if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE)
+ return STATUS_UNSUCCESSFUL;
+
+ if (pipe_content->speed_high == 0)
+ {
+ td_count = purb->iso_frame_count;
+
+ // test to see if the last td needs one more sitd for pure complete-split
+ if (pipe_content->trans_dir == 0)
+ {
+ j = (purb->iso_packet_desc[purb->iso_frame_count - 1].length + 187) / 188;
+ if (purb->iso_packet_desc[purb->iso_frame_count - 1].params.start_uframe + 1 + j >= 8)
+ {
+ td_count++;
+ ret = TRUE;
+ }
+ }
+ elem_pool_lock(itd_pool, TRUE);
+ pelnk = elem_pool_alloc_elems(itd_pool, td_count);
+ elem_pool_unlock(itd_pool, TRUE);
+
+ }
+ else
+ {
+ i = REAL_INTERVAL;
+ if (pipe_content->interval >= 3)
+ {
+ td_count = purb->iso_frame_count;
+ j = 0;
+ }
+ else
+ {
+ j = purb->iso_start_frame & 0x07;
+ if (j == 0)
+ {
+ td_count = (purb->iso_frame_count + 8 / i - 1) * i / 8;
+ }
+ else
+ {
+ j = 1 + (7 - j) / i; // the leading packets from the 8-trans boundary
+ td_count = (j >= (LONG) purb->iso_frame_count ?
+ 1 : 1 + (purb->iso_frame_count - j + 8 / i - 1) * i / 8);
+ }
+ }
+
+ elem_pool_lock(sitd_pool, TRUE);
+ pelnk = elem_pool_alloc_elems(sitd_pool, td_count);
+ elem_pool_unlock(sitd_pool, TRUE);
+ }
+
+ if (pelnk == NULL)
+ {
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ InsertTailList(&pelnk->elem_link, &td_list);
+ ListFirst(&td_list, pthis);
+ pprev = pthis;
+ purb->td_count = td_count;
+
+ //set up offset for high speed and interval == 1
+ if (pipe_content->speed_high && pipe_content->interval == 0)
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ if (i == 0)
+ purb->iso_packet_desc[i].offset = 0;
+ else
+ purb->iso_packet_desc[i].offset = purb->iso_packet_desc[i - 1].offset +
+ purb->iso_packet_desc[i].length;
+ }
+ }
+
+ i = 0, temp = 0;
+
+ while (pthis)
+ {
+ init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link));
+ if (pipe_content->speed_high)
+ {
+ LONG start_uframe, k;
+ LONG l, pk_idx, offset, start_uf, td_length;
+ PULONG pbuf;
+ ULONG phys_addr[8];
+
+ pitd = itd_from_list_entry(pthis);
+ pitdc = (PEHCI_ITD_CONTENT) pitd;
+ start_uframe = purb->iso_start_frame & 0x07;
+
+ // will be filled later
+ pitd->hw_next = EHCI_PTR_TERM;
+
+ // DWORD 9;
+ pitdc->dev_addr = pdev->dev_addr;
+ pitdc->endp_num = endp_num(purb->pendp);
+
+ pitdc->max_packet_size = endp_max_packet_size(purb->pendp);
+ pitdc->io_dir = pipe_content->trans_dir;
+ pitdc->mult = endp_mult_count(purb->pendp);
+
+ pbuf = pitd->hw_bufp;
+ RtlZeroMemory(phys_addr, sizeof(phys_addr));
+
+ if (pipe_content->interval < 3)
+ {
+ // this indicates one itd schedules more than one uframes
+ // for multiple transactions described by iso_packet_desc
+ if (i == 0)
+ k = td_count == 1 ? purb->iso_frame_count : j; // the first itd
+ else
+ k = (LONG) (purb->iso_frame_count - i) <= 8 / REAL_INTERVAL
+ ? (purb->iso_frame_count - i) : 8 / REAL_INTERVAL;
+
+ // j is the header transactions out of the interval
+ // aligned transactions per td
+ if (j > 0 && i == 0) // handle the first itd
+ start_uf = start_uframe;
+ else
+ start_uf = start_uframe % REAL_INTERVAL;
+ }
+ else
+ {
+ k = 1, start_uf = start_uframe & 0x07;
+ }
+
+
+ // calculate the data to transfer with this td
+ td_length = 0;
+ for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL)
+ {
+ td_length += purb->iso_packet_desc[pk_idx].length;
+ phys_addr[l] =
+ MmGetPhysicalAddress(&purb->data_buffer[purb->iso_packet_desc[pk_idx].offset]).LowPart;
+ }
+
+ // fill the page pointer, and offset
+ if (pipe_content->interval != 0)
+ {
+ for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL)
+ {
+ pitdc->status_slot[l].offset = phys_addr[l] & (PAGE_SIZE - 1);
+ pbuf[l >> pipe_content->interval] |= phys_addr[l] & (~(PAGE_SIZE - 1));
+ pitdc->status_slot[l].page_sel = l >> pipe_content->interval;
+ pitdc->status_slot[l].status = 0x08;
+ pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length;
+ if (PAGE_SIZE - pitdc->status_slot[l].offset <
+ (ULONG) purb->iso_packet_desc[pk_idx].length)
+ {
+ // fill the next page buf, we can not simply add
+ // PAGE_SIZE to the phys_addr[ l ].
+ pbuf[(l >> pipe_content->interval) + 1] |=
+ MmGetPhysicalAddress((PBYTE)
+ (((ULONG) & purb->
+ data_buffer[purb->iso_packet_desc[pk_idx].
+ offset]) & (~(PAGE_SIZE - 1))) +
+ PAGE_SIZE).LowPart;
+ }
+ }
+ }
+ else // interval == 0
+ {
+ LONG m, n, n2;
+ // fill the page buffer first
+ // calculate the page buffer needed
+ offset = phys_addr[0] & (PAGE_SIZE - 1);
+ if (offset != 0)
+ {
+ offset = PAGE_SIZE - offset;
+ l = 1 + (td_length - offset + PAGE_SIZE - 1) / PAGE_SIZE;
+ }
+ else
+ {
+ l = (td_length + PAGE_SIZE - 1) / PAGE_SIZE;
+ }
+
+ if (l > 7)
+ TRAP();
+
+ // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp
+ for(pk_idx = 0; pk_idx < l; pk_idx++)
+ {
+ if (pk_idx == 0)
+ {
+ offset = phys_addr[start_uf] & (~(PAGE_SIZE - 1));
+ pbuf[pk_idx] |= offset;
+ n = pk_idx;
+ pitdc->status_slot[0].page_sel = n;
+ n2 = start_uf;
+ }
+ else
+ {
+ // scan to find if the buf pointer already filled in the td
+ // since interval = 1, we do not need k * REAL_INTERVAL
+ // k is transaction count for current td,
+ // n is hw_bufp( pbuf ) index
+ // n2 is the last phys_addr index we stopped
+ for(m = n2; m < start_uf + k; m++)
+ {
+ // we can not determine the phys_addr[ x ] is piror
+ // to offset if it is less than offset.
+ // because phys_addr is discrete.
+ // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset )
+ // continue;
+
+ if ((phys_addr[m] & (~(PAGE_SIZE - 1))) == (ULONG) offset)
+ {
+ pitdc->status_slot[m].page_sel = n;
+ continue;
+ }
+ break;
+ }
+
+ if (m == start_uf + k)
+ TRAP();
+
+ offset = phys_addr[m] & (~(PAGE_SIZE - 1));
+ pbuf[pk_idx] |= offset;
+ n = pk_idx;
+ n2 = m;
+ pitdc->status_slot[m].page_sel = n;
+ }
+ }
+ // fill offset and others
+ for(l = start_uf, pk_idx = i; l < start_uf + k; l++, pk_idx++)
+ {
+ pitdc->status_slot[l].offset = (phys_addr[l] & (PAGE_SIZE - 1));
+ pitdc->status_slot[l].status = 0x08;
+ pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length;
+ }
+ // exhausted
+ }
+ i += k;
+ }
+ else // full/low speed
+ {
+ psitd = sitd_from_list_entry(pthis);
+ psitdc = (PEHCI_SITD_CONTENT) psitd;
+ psitd->hw_next = EHCI_PTR_TERM;
+
+ // DWORD 1;
+ psitdc->dev_addr = pdev->dev_addr;
+ psitdc->endp_num = endp_num(purb->pendp);
+ psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
+ psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
+ psitdc->io_dir = endp_dir(purb->pendp);
+
+ psitdc->status &= 0x80; // in DWORD 3
+
+ // DWORD 2;
+ j = (purb->iso_packet_desc[i].length + 187) / 188;
+
+ if (psitdc->io_dir == 0)
+ {
+ for(; j > 0; j--)
+ {
+ psitdc->s_mask |= (1 << (j - 1));
+ }
+ psitdc->s_mask <<= purb->iso_packet_desc[i].params.start_uframe & 0x07;
+ psitdc->c_mask = 0;
+ }
+ else
+ {
+ LONG k;
+
+ psitdc->s_mask = 1 << purb->iso_packet_desc[i].params.start_uframe & 0x07;
+ // iso split case 2b: ehci spec 1.0
+ if (j == 6)
+ j = 5;
+
+ j = j - 1 + 2; // actual complete-split count
+
+ psitdc->c_mask |= temp >> 8; // the previous sitd's complete split
+ if (temp >> 8) // link back for sitd split completion
+ {
+ psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr;
+ psitdc->status &= 0x82;
+ }
+ else
+ {
+ psitd->hw_backpointer = EHCI_PTR_TERM;
+ }
+
+ for(k = temp = 0; k < j; k++)
+ {
+ temp |= 1 << k;
+ }
+
+ temp <<= ((purb->iso_packet_desc[i].params.start_uframe & 0x07) + 2);
+
+ // only uframe zero and one have complete split for prev sitd
+ if ((temp >> 8) > 3)
+ TRAP();
+
+ psitdc->c_mask |= temp & 0xff;
+ }
+
+ // DWORD 3:
+ psitdc->c_prog_mask = 0;
+ psitdc->bytes_to_transfer = purb->iso_packet_desc[i].length;
+ psitdc->page_sel = 0;
+ psitdc->ioc = 0;
+
+ // DWORD 4;
+ j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[i].offset);
+ psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart;
+
+ // DWORD 5;
+ if (PAGE_SIZE - (j & (PAGE_SIZE - 1)) < (ULONG) purb->iso_packet_desc[i].length)
+ {
+ // need to fill another slot
+ psitdc->page1 =
+ MmGetPhysicalAddress((PVOID) ((j & ~(PAGE_SIZE - 1)) + PAGE_SIZE)).LowPart >> 12;
+ }
+
+ if (purb->iso_packet_desc[i].length > 188)
+ psitdc->trans_pos = 0x00;
+ else if (purb->iso_packet_desc[i].length <= 188)
+ psitdc->trans_pos = 0x01;
+
+ if (psitdc->io_dir == 0)
+ psitdc->trans_count = (purb->iso_packet_desc[i].length + 187) / 188;
+
+ }
+ ListNext(&td_list, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+
+ }
+
+ if (pipe_content->speed_high == 0)
+ {
+ // has an extra sitd to fill at the tail
+ if (ret)
+ {
+ ListFirstPrev(&td_list, pthis);
+ init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link));
+
+ psitd = sitd_from_list_entry(pthis);
+ psitdc = (PEHCI_SITD_CONTENT) psitd;
+ psitd->hw_next = EHCI_PTR_TERM;
+
+ // DWORD 1;
+ psitdc->dev_addr = pdev->dev_addr;
+ psitdc->endp_num = endp_num(purb->pendp);
+ psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
+ psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
+ psitdc->io_dir = endp_dir(purb->pendp);
+
+ psitdc->status &= 0x80; // in DWORD 3
+
+ // DWORD 2;
+ psitdc->s_mask = 0x04; // uframe 2, random selection
+
+ psitdc->c_mask = 0x70; // complete split at uframe 4, 5, 6
+ ListFirstPrev(pthis, pprev);
+ psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr;
+ psitdc->status &= 0x82;
+
+ // DWORD 3:
+ psitdc->c_prog_mask = 0;
+ psitdc->bytes_to_transfer = 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length;
+ psitdc->page_sel = 0;
+
+ j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[purb->iso_frame_count - 1].offset);
+ // the last byte is overridden.
+ j += purb->iso_packet_desc[purb->iso_frame_count - 1].length - 1;
+ psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart;
+ }
+
+ // set the interrupt
+ ListFirstPrev(&td_list, pthis);
+ psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis);
+ psitdc->ioc = 1;
+ }
+ else
+ {
+ // set the ioc
+ ListFirstPrev(&td_list, pthis);
+ pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis);
+ for(i = 7; i >= 0; i--)
+ {
+ if (pitdc->status_slot[i].status = 0x08)
+ {
+ pitdc->status_slot[i].ioc = 1;
+ break;
+ }
+ }
+ if (i < 0)
+ TRAP();
+ }
+
+ ListFirst(&td_list, pthis);
+ // ListFirst( &purb->trasac_list, pthis )
+ RemoveEntryList(&td_list);
+ InsertTailList(pthis, &purb->trasac_list);
+
+ while (pthis)
+ {
+ // fill the purb ptr
+ struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb;
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ //indirectly guarded by pending_endp_list_lock
+ usb_endp_busy_count_inc(purb->pendp);
+ ehci_insert_urb_to_schedule(ehci, purb, ret);
+
+ if (ret == FALSE)
+ {
+ // usb_endp_busy_count_dec( purb->pendp );
+
+ ListFirst(&purb->trasac_list, pthis);
+ RemoveEntryList(&purb->trasac_list);
+
+ elem_safe_free(pthis, FALSE);
+ ehci_claim_bandwidth(ehci, purb, FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN
+ehci_sync_insert_urb_schedule(PVOID context)
+//this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule
+{
+ PSYNC_PARAM sync_param;
+ PEHCI_DEV ehci;
+ PURB purb;
+
+ sync_param = (PSYNC_PARAM) context;
+ if (sync_param == NULL)
+ return FALSE;
+
+ ehci = sync_param->ehci;
+ purb = (PURB) sync_param->context;
+
+ if (ehci == NULL || purb == NULL)
+ return (UCHAR) sync_param->ret = FALSE;
+
+ return (UCHAR) (sync_param->ret = ehci_insert_urb_schedule(ehci, purb));
+}
+
+BOOLEAN
+ehci_sync_cancel_urb(PVOID context)
+{
+ //cancel a single purb
+ PEHCI_DEV ehci;
+ PSYNC_PARAM sync_param;
+ PURB purb2, dest_urb;
+ PLIST_ENTRY pthis, pnext;
+ BOOL found = FALSE;
+
+ if (context == NULL)
+ return FALSE;
+
+ sync_param = (PSYNC_PARAM) context;
+ ehci = sync_param->ehci;
+ dest_urb = (PURB) sync_param->context;
+
+ if (ehci == NULL || dest_urb == NULL)
+ return (UCHAR) sync_param->ret = FALSE;
+
+ ListFirst(&ehci->urb_list, pthis);
+ while (pthis)
+ {
+ purb2 = (PURB) pthis;
+ if (purb2 == dest_urb)
+ {
+ found = TRUE;
+ purb2->flags |= URB_FLAG_FORCE_CANCEL;
+ break;
+ }
+ ListNext(&ehci->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ if (found)
+ {
+ press_doorbell(ehci);
+ }
+ return (UCHAR) (sync_param->ret = found);
+}
+
+NTSTATUS
+ehci_cancel_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
+//note any fields of the purb can not be referenced unless it is found in some queue
+{
+
+ NTSTATUS status;
+ PLIST_ENTRY pthis, pnext;
+ BOOL found;
+ PURB purb2;
+
+ SYNC_PARAM sync_param;
+
+ USE_IRQL;
+
+ if (ehci == NULL || purb == NULL || pdev == NULL || pendp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_dev(pdev, FALSE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ //delegate to remove device for this job
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ if (dev_from_endp(pendp) != pdev)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
+ {
+ //it will be canceled in ehci_process_pending_endp
+ unlock_dev(pdev, FALSE);
+ return USB_STATUS_ENDPOINT_HALTED;
+ }
+
+ found = FALSE;
+ ListFirst(&pendp->urb_list, pthis);
+ while (pthis)
+ {
+ purb2 = (PURB) pthis;
+ if (purb2 == purb)
+ {
+ found = TRUE;
+ RemoveEntryList(pthis);
+ InitializeListHead(pthis);
+ break;
+ }
+ ListNext(&pendp->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+ unlock_dev(pdev, FALSE);
+
+ if (found)
+ {
+ purb->status = STATUS_CANCELLED;
+
+ ehci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, FALSE);
+ pdev->ref_count--;
+ unlock_dev(pdev, FALSE);
+ return STATUS_SUCCESS;
+ }
+
+ // search the purb in the purb-list and try to cancel
+ sync_param.ehci = ehci;
+ sync_param.context = purb;
+
+ KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urb, &sync_param);
+
+ found = sync_param.ret;
+
+ if (found)
+ return USB_STATUS_CANCELING;
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+VOID
+ehci_generic_urb_completion(PURB purb, PVOID context)
+{
+ PUSB_DEV pdev;
+ KIRQL cur_irql;
+ BOOL is_ctrl;
+ USE_IRQL;
+
+ old_irql = KeGetCurrentIrql();
+ if (old_irql > DISPATCH_LEVEL)
+ TRAP();
+
+ if (old_irql < DISPATCH_LEVEL)
+ KeRaiseIrql(DISPATCH_LEVEL, &old_irql);
+
+ pdev = purb->pdev;
+ if (purb == NULL)
+ goto LBL_LOWER_IRQL;
+
+ if (pdev == NULL)
+ goto LBL_LOWER_IRQL;
+
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ // no need to do following statistics
+ unlock_dev(pdev, TRUE);
+ goto LBL_CLIENT_PROCESS;
+ }
+ if (usb_error(purb->status))
+ {
+ pdev->error_count++;
+ }
+
+ if (purb->pendp == &pdev->default_endp)
+ {
+ if (usb_halted(purb->status))
+ {
+ pdev->time_out_count++;
+ if (pdev->time_out_count > 3)
+ {
+ dev_set_state(pdev, USB_DEV_STATE_ZOMB);
+ ehci_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
+ pdev));
+ }
+ }
+ else
+ pdev->time_out_count = 0;
+
+ }
+
+ is_ctrl = FALSE;
+ if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_CONTROL)
+ is_ctrl = TRUE;
+
+ unlock_dev(pdev, TRUE);
+
+ LBL_CLIENT_PROCESS:
+ if (!is_ctrl)
+ {
+ if (purb->completion)
+ purb->completion(purb, context);
+ }
+ else
+ {
+ PCTRL_REQ_STACK pstack;
+ if (purb->ctrl_req_context.ctrl_stack_count == 0)
+ {
+ if (purb->completion)
+ purb->completion(purb, context);
+ }
+ else
+ {
+ // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
+ // if( pstack->urb_completion )
+ // pstack->urb_completion( purb, pstack->context );
+ usb_call_ctrl_completion(purb);
+ }
+ }
+
+ LBL_LOWER_IRQL:
+ if (old_irql < DISPATCH_LEVEL)
+ KeLowerIrql(old_irql);
+
+ return;
+}
+
+NTSTATUS
+ehci_rh_submit_urb(PUSB_DEV pdev, PURB purb)
+{
+ PUSB_DEV_MANAGER dev_mgr;
+ PTIMER_SVC ptimer;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PEHCI_DEV ehci;
+ NTSTATUS status;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_PORT_STATUS ps, psret;
+ LONG i;
+ UCHAR port_count;
+
+ USE_IRQL;
+ if (pdev == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ ehci = ehci_from_hcd(pdev->hcd);
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext);
+ port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count;
+
+ switch (endp_type(purb->pendp))
+ {
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS)
+ {
+ //get-port-status
+ if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength < 4)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ ps = &hub_ext->rh_port_status[psetup->wIndex];
+
+ psret = (PUSB_PORT_STATUS) purb->data_buffer;
+ ps->wPortStatus = 0;
+
+ if (status & PORT_CCS)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (status & PORT_PE)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_ENABLE;
+ ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec
+ }
+ if (status & PORT_PR)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (status & PORT_SUSP)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (PORT_USB11(status))
+ {
+ ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+
+ //always power on
+ ps->wPortStatus |= USB_PORT_STAT_POWER;
+
+ //now set change field
+ if ((status & PORT_CSC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED))
+ {
+ ps->wPortChange |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if ((status & PORT_PEC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED))
+ {
+ ps->wPortChange |= USB_PORT_STAT_C_ENABLE;
+ }
+
+ //don't touch other fields, might be filled by
+ //other function
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
+ ps->wPortStatus, ps->wPortChange, ps));
+
+ psret->wPortChange = ps->wPortChange;
+ psret->wPortStatus = ps->wPortStatus;
+
+ purb->status = STATUS_SUCCESS;
+
+ break;
+ }
+ else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE)
+ {
+ //clear-port-feature
+ if (psetup->wIndex == 0 || psetup->wIndex > port_count)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
+ ps = &hub_ext->rh_port_status[psetup->wIndex];
+
+ purb->status = STATUS_SUCCESS;
+ switch (psetup->wValue)
+ {
+ case USB_PORT_FEAT_C_CONNECTION:
+ {
+ SET_RH2_PORTSTAT(i, USBPORTSC_CSC);
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex));
+ ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
+ break;
+ }
+ case USB_PORT_FEAT_C_ENABLE:
+ {
+ SET_RH2_PORTSTAT(i, USBPORTSC_PEC);
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex));
+ ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE;
+ break;
+ }
+ case USB_PORT_FEAT_C_RESET:
+ {
+ ps->wPortChange &= ~USB_PORT_STAT_C_RESET;
+ //the reset signal is down in rh_timer_svc_reset_port_completion
+ // enable or not is set by host controller
+ // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
+ psetup->wIndex));
+ break;
+ }
+ case USB_PORT_FEAT_ENABLE:
+ {
+ ps->wPortStatus &= ~USB_PORT_STAT_ENABLE;
+ CLR_RH2_PORTSTAT(i, USBPORTSC_PE);
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex));
+ break;
+ }
+ default:
+ purb->status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+ else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE)
+ {
+ // get bus state
+ if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength == 0)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ purb->data_buffer[0] = (status & USBPORTSC_LS);
+
+ // reverse the order
+ purb->data_buffer[0] ^= 0x3;
+ purb->status = STATUS_SUCCESS;
+ break;
+ }
+ else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_SET_FEATURE)
+ {
+ //reset port
+ if (psetup->wValue != USB_PORT_FEAT_RESET)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ ehci_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue));
+ break;
+ }
+
+ i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
+
+ ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms
+ ptimer->context = (ULONG) purb;
+ ptimer->pdev = pdev;
+ ptimer->func = rh_timer_svc_reset_port_completion;
+
+ //start the timer
+ pdev->ref_count += 2; //one for timer and one for purb
+
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status));
+ InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link);
+ purb->status = STATUS_PENDING;
+ }
+ else
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
+ ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ ptimer->threshold = RH_INTERVAL;
+ ptimer->context = (ULONG) purb;
+ ptimer->pdev = pdev;
+ ptimer->func = rh_timer_svc_int_completion;
+
+ //start the timer
+ InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link);
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count));
+ pdev->ref_count += 2; //one for timer and one for purb
+
+ purb->status = STATUS_PENDING;
+ break;
+ }
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_ISOC:
+ default:
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ unlock_dev(pdev, FALSE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return purb->status;
+}
+
+//must have rh dev_lock acquired
+BOOL
+ehci_rh_reset_port(PHCD hcd, UCHAR port_idx)
+{
+ ULONG i;
+ PEHCI_DEV ehci;
+ ULONG status;
+ UCHAR port_count;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ ehci = ehci_from_hcd(hcd);
+ port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count;
+
+ if (port_idx < 1 || port_idx > port_count)
+ return FALSE;
+
+ i = (ULONG) (EHCI_PORTSC + 4 * (port_idx - 1));
+
+ // assert the reset signal,(implicitly disable the port)
+ SET_RH2_PORTSTAT(i, PORT_PR);
+
+ usb_wait_ms_dpc(50);
+ // clear the reset signal, delay port enable till clearing port feature
+ CLR_RH2_PORTSTAT(i, PORT_PR);
+
+ // wait the port stable
+ usb_wait_ms_dpc(2);
+
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ if (!(status & PORT_PE))
+ {
+ // release the ownership from ehci to companion hc
+ status |= PORT_OWNER;
+ EHCI_WRITE_PORT_ULONG((PULONG) (ehci->port_base + i), status);
+ // the host controller will set PORTSC automatically
+ return FALSE;
+ }
+ usb_wait_us_dpc(10);
+ // SET_RH_PORTSTAT( i, PORT_PE );
+
+ //recovery time 10ms
+ usb_wait_ms_dpc(10);
+
+ // clear PORT_PEC and PORT_PCC
+ SET_RH2_PORTSTAT(i, 0x0a);
+
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM, ("ehci_rh_reset_port(): status after written=0x%x\n", status));
+ return TRUE;
+}
+
+NTSTATUS
+ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)
+{
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+ PEHCI_DEV ehci;
+
+ pdev_ext = DeviceObject->DeviceExtension;
+ ehci = pdev_ext->ehci;
+
+ dev_mgr = ehci->hcd_interf.hcd_get_dev_mgr(&ehci->hcd_interf);
+ return dev_mgr_dispatch(dev_mgr, irp);
+}
+
+//the following are for hcd interface methods
+VOID
+ehci_set_dev_mgr(PHCD hcd, PUSB_DEV_MANAGER dev_mgr)
+{
+ hcd->dev_mgr = dev_mgr;
+}
PUSB_DEV_MANAGER
-ehci_get_dev_mgr(
-PHCD hcd
-)
+ehci_get_dev_mgr(PHCD hcd)
{
- return hcd->dev_mgr;
+ return hcd->dev_mgr;
}
-ULONG
-ehci_get_type(
-PHCD hcd
-)
+ULONG
+ehci_get_type(PHCD hcd)
{
- return HCD_TYPE_EHCI; // ( hcd->flags & HCD_TYPE_MASK );
+ return HCD_TYPE_EHCI; // ( hcd->flags & HCD_TYPE_MASK );
}
VOID
-ehci_set_id(
-PHCD hcd,
-UCHAR id
-)
+ehci_set_id(PHCD hcd, UCHAR id)
{
- hcd->flags &= ~HCD_ID_MASK;
- hcd->flags |= ( HCD_ID_MASK & id );
+ hcd->flags &= ~HCD_ID_MASK;
+ hcd->flags |= (HCD_ID_MASK & id);
}
UCHAR
-ehci_get_id(
-PHCD hcd
-)
+ehci_get_id(PHCD hcd)
{
- return ( UCHAR )( hcd->flags & HCD_ID_MASK );
+ return (UCHAR) (hcd->flags & HCD_ID_MASK);
}
UCHAR
-ehci_alloc_addr(
-PHCD hcd
-)
+ehci_alloc_addr(PHCD hcd)
{
- LONG i;
- if( hcd == NULL )
- return 0;
-
- for( i = 1; i < MAX_DEVS; i ++ )
- {
- if( hcd->dev_addr_map[ i >> 3 ] & ( 1 << ( i & 7 ) ) )
- {
- continue;
- }
- else
- {
- break;
- }
- }
-
- if( i >= MAX_DEVS )
- return 0xff;
-
- hcd->dev_addr_map[ i >> 3 ] |= ( 1 << ( i & 7 ) );
- hcd->conn_count++;
- return ( BYTE )i;
+ LONG i;
+ if (hcd == NULL)
+ return 0;
+
+ for(i = 1; i < MAX_DEVS; i++)
+ {
+ if (hcd->dev_addr_map[i >> 3] & (1 << (i & 7)))
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (i >= MAX_DEVS)
+ return 0xff;
+
+ hcd->dev_addr_map[i >> 3] |= (1 << (i & 7));
+ hcd->conn_count++;
+ return (BYTE) i;
}
VOID
-ehci_free_addr(
-PHCD hcd,
-UCHAR addr
-)
-{
- if( addr & 0x80 )
- return;
-
- if( hcd == NULL )
- return;
-
- hcd->dev_addr_map[ addr >> 3 ] &= ~( 1 << ( addr & 7 ) );
- return;
-
+ehci_free_addr(PHCD hcd, UCHAR addr)
+{
+ if (addr & 0x80)
+ return;
+
+ if (hcd == NULL)
+ return;
+
+ hcd->dev_addr_map[addr >> 3] &= ~(1 << (addr & 7));
+ return;
+
}
NTSTATUS
-ehci_submit_urb2(
-PHCD hcd,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb )
+ehci_submit_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- return ehci_submit_urb( ehci_from_hcd( hcd ), pdev, pendp, purb );
+ return ehci_submit_urb(ehci_from_hcd(hcd), pdev, pendp, purb);
}
PUSB_DEV
-ehci_get_root_hub(
-PHCD hcd
-)
+ehci_get_root_hub(PHCD hcd)
{
- return ehci_from_hcd( hcd )->root_hub;
+ return ehci_from_hcd(hcd)->root_hub;
}
+
VOID
-ehci_set_root_hub(
-PHCD hcd,
-PUSB_DEV root_hub
-)
+ehci_set_root_hub(PHCD hcd, PUSB_DEV root_hub)
{
- if( hcd == NULL || root_hub == NULL )
- return;
- ehci_from_hcd( hcd )->root_hub = root_hub;
- return;
+ if (hcd == NULL || root_hub == NULL)
+ return;
+ ehci_from_hcd(hcd)->root_hub = root_hub;
+ return;
}
BOOL
-ehci_remove_device2(
-PHCD hcd,
-PUSB_DEV pdev
-)
+ehci_remove_device2(PHCD hcd, PUSB_DEV pdev)
{
- if( hcd == NULL || pdev == NULL )
- return FALSE;
+ if (hcd == NULL || pdev == NULL)
+ return FALSE;
- return ehci_remove_device( ehci_from_hcd( hcd ), pdev );
+ return ehci_remove_device(ehci_from_hcd(hcd), pdev);
}
BOOL
-ehci_hcd_release(
-PHCD hcd
-)
+ehci_hcd_release(PHCD hcd)
{
- PEHCI_DEV ehci;
- PEHCI_DEVICE_EXTENSION pdev_ext;
-
- if( hcd == NULL )
- return FALSE;
-
- ehci = ehci_from_hcd( hcd );
- pdev_ext = ehci->pdev_ext;
- return ehci_release( pdev_ext->pdev_obj );
+ PEHCI_DEV ehci;
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ ehci = ehci_from_hcd(hcd);
+ pdev_ext = ehci->pdev_ext;
+ return ehci_release(pdev_ext->pdev_obj);
}
NTSTATUS
-ehci_cancel_urb2(
-PHCD hcd,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
+ehci_cancel_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- PEHCI_DEV ehci;
- if( hcd == NULL )
- return STATUS_INVALID_PARAMETER;
-
- ehci = ehci_from_hcd( hcd );
- return ehci_cancel_urb( ehci, pdev, pendp, purb );
+ PEHCI_DEV ehci;
+ if (hcd == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ ehci = ehci_from_hcd(hcd);
+ return ehci_cancel_urb(ehci, pdev, pendp, purb);
}
+
BOOL
-ehci_rh_get_dev_change(
-PHCD hcd,
-PBYTE buf
-) //must have the rh dev_lock acquired
+ehci_rh_get_dev_change(PHCD hcd, PBYTE buf) //must have the rh dev_lock acquired
{
- PEHCI_DEV ehci;
- LONG port_count, i;
- ULONG status;
-
- if( hcd == NULL )
- return FALSE;
-
- ehci = ehci_from_hcd( hcd );
- port_count = HCS_N_PORTS( ehci->ehci_caps.hcs_params );
- for( i = 0; i < port_count; i++ )
- {
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + EHCI_PORTSC + ( i << 2 ) ) );
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_rh_get_dev_change(): erh port%d status=0x%x\n", i, status ) );
-
- if( status & ( PORT_PEC | PORT_CSC | PORT_OCC ) )
- {
- buf[ ( i + 1 ) >> 3 ] |= ( 1 << ( ( i + 1 ) & 7 ) );
- }
- }
- return TRUE;
+ PEHCI_DEV ehci;
+ LONG port_count, i;
+ ULONG status;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ ehci = ehci_from_hcd(hcd);
+ port_count = HCS_N_PORTS(ehci->ehci_caps.hcs_params);
+ for(i = 0; i < port_count; i++)
+ {
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_PORTSC + (i << 2)));
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_rh_get_dev_change(): erh port%d status=0x%x\n", i, status));
+
+ if (status & (PORT_PEC | PORT_CSC | PORT_OCC))
+ {
+ buf[(i + 1) >> 3] |= (1 << ((i + 1) & 7));
+ }
+ }
+ return TRUE;
}
NTSTATUS
-ehci_hcd_dispatch(
-PHCD hcd,
-LONG disp_code,
-PVOID param
-)
+ehci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param)
{
- PEHCI_DEV ehci;
-
- if( hcd == NULL )
- return STATUS_INVALID_PARAMETER;
- ehci = ehci_from_hcd( hcd );
- switch( disp_code )
- {
- case HCD_DISP_READ_PORT_COUNT:
- {
- if( param == NULL )
- return STATUS_INVALID_PARAMETER;
- *( ( PUCHAR )param ) = ( UCHAR )HCS_N_PORTS( ehci->ehci_caps.hcs_params );
- return STATUS_SUCCESS;
- }
- case HCD_DISP_READ_RH_DEV_CHANGE:
- {
- if( ehci_rh_get_dev_change( hcd, param ) == FALSE )
- return STATUS_INVALID_PARAMETER;
- return STATUS_SUCCESS;
- }
- }
- return STATUS_NOT_IMPLEMENTED;
+ PEHCI_DEV ehci;
+
+ if (hcd == NULL)
+ return STATUS_INVALID_PARAMETER;
+ ehci = ehci_from_hcd(hcd);
+ switch (disp_code)
+ {
+ case HCD_DISP_READ_PORT_COUNT:
+ {
+ if (param == NULL)
+ return STATUS_INVALID_PARAMETER;
+ *((PUCHAR) param) = (UCHAR) HCS_N_PORTS(ehci->ehci_caps.hcs_params);
+ return STATUS_SUCCESS;
+ }
+ case HCD_DISP_READ_RH_DEV_CHANGE:
+ {
+ if (ehci_rh_get_dev_change(hcd, param) == FALSE)
+ return STATUS_INVALID_PARAMETER;
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_NOT_IMPLEMENTED;
}
//------------------------------------------------------------------------------
-// EHCI routines follows
+// EHCI routines follows
//
-VOID
-ehci_init_int8_qh(
-PEHCI_QH_CONTENT qh
-);
+VOID ehci_init_int8_qh(PEHCI_QH_CONTENT qh);
BOOLEAN
-ehci_cal_cpu_freq(
-PVOID context
-)
+ehci_cal_cpu_freq(PVOID context)
{
- usb_cal_cpu_freq();
- return TRUE;
+ usb_cal_cpu_freq();
+ return TRUE;
}
PDEVICE_OBJECT
-ehci_probe(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-PUSB_DEV_MANAGER dev_mgr
-)
+ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr)
{
- LONG bus, i, j, ret;
- PCI_SLOT_NUMBER slot_num;
- PPCI_COMMON_CONFIG pci_config;
- PDEVICE_OBJECT pdev;
- BYTE buffer[ sizeof( PCI_COMMON_CONFIG ) ];
- PEHCI_DEVICE_EXTENSION pdev_ext;
-
- slot_num.u.AsULONG = 0;
- pci_config = ( PPCI_COMMON_CONFIG ) buffer;
- pdev = NULL;
-
- //scan the bus to find ehci controller
- for( bus = 0; bus < 2; bus++ ) /*enum only bus0 and bus1*/
- {
- for( i = 0; i < PCI_MAX_DEVICES; i++ )
- {
- slot_num.u.bits.DeviceNumber = i;
- for( j = 0; j < PCI_MAX_FUNCTIONS; j++ )
- {
- slot_num.u.bits.FunctionNumber = j;
-
- ret = HalGetBusData(
- PCIConfiguration,
- bus,
- slot_num.u.AsULONG,
- pci_config,
- PCI_COMMON_HDR_LENGTH );
-
- if( ret == 0 ) /*no this bus*/
- break;
-
- if( ret == 2 ) /*no device on the slot*/
- break;
-
- if( pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03 && pci_config->ProgIf == 0x20 )
- {
- //well, we find our usb host controller( EHCI ), create device
- pdev = ehci_alloc( drvr_obj, reg_path, ( ( bus << 8 ) | ( i << 3 ) | j ), dev_mgr );
-
- if( !pdev )
- continue;
- }
- }
-
- if( ret == 0 )
- break;
- }
- }
-
- if( pdev )
- {
- pdev_ext = pdev->DeviceExtension;
- if( pdev_ext )
- {
- // acquire higher irql to eliminate pre-empty
- KeSynchronizeExecution( pdev_ext->ehci_int, ehci_cal_cpu_freq, NULL );
- }
- }
- return NULL;
+ LONG bus, i, j, ret;
+ PCI_SLOT_NUMBER slot_num;
+ PPCI_COMMON_CONFIG pci_config;
+ PDEVICE_OBJECT pdev;
+ BYTE buffer[sizeof(PCI_COMMON_CONFIG)];
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+
+ slot_num.u.AsULONG = 0;
+ pci_config = (PPCI_COMMON_CONFIG) buffer;
+ pdev = NULL;
+
+ //scan the bus to find ehci controller
+ for(bus = 0; bus < 2; bus++) /*enum only bus0 and bus1 */
+ {
+ for(i = 0; i < PCI_MAX_DEVICES; i++)
+ {
+ slot_num.u.bits.DeviceNumber = i;
+ for(j = 0; j < PCI_MAX_FUNCTIONS; j++)
+ {
+ slot_num.u.bits.FunctionNumber = j;
+
+ ret = HalGetBusData(PCIConfiguration,
+ bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH);
+
+ if (ret == 0) /*no this bus */
+ break;
+
+ if (ret == 2) /*no device on the slot */
+ break;
+
+ if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03
+ && pci_config->ProgIf == 0x20)
+ {
+ //well, we find our usb host controller( EHCI ), create device
+ pdev = ehci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr);
+
+ if (!pdev)
+ continue;
+ }
+ }
+
+ if (ret == 0)
+ break;
+ }
+ }
+
+ if (pdev)
+ {
+ pdev_ext = pdev->DeviceExtension;
+ if (pdev_ext)
+ {
+ // acquire higher irql to eliminate pre-empty
+ KeSynchronizeExecution(pdev_ext->ehci_int, ehci_cal_cpu_freq, NULL);
+ }
+ }
+ return NULL;
}
-PDEVICE_OBJECT
-ehci_alloc(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-ULONG bus_addr,
-PUSB_DEV_MANAGER dev_mgr
-)
-{
+PDEVICE_OBJECT
+ehci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr)
+{
+
+ LONG frd_num, prd_num;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PDEVICE_OBJECT pdev;
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+ ULONG vector, addr_space;
+ LONG bus, i;
+ KIRQL irql;
+ KAFFINITY affinity;
+ UCHAR hcd_id;
+
+ DEVICE_DESCRIPTION dev_desc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd;
+ PCI_SLOT_NUMBER slot_num;
+ NTSTATUS status;
+
+
+ pdev = ehci_create_device(drvr_obj, dev_mgr);
+
+ if (pdev == NULL)
+ return NULL;
+
+ pdev_ext = pdev->DeviceExtension;
+
+ pdev_ext->pci_addr = bus_addr;
+ bus = (bus_addr >> 8);
+
+ slot_num.u.AsULONG = 0;
+ slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3);
+ slot_num.u.bits.FunctionNumber = (bus_addr & 0x07);
+
+ //now create adapter object
+ RtlZeroMemory(&dev_desc, sizeof(dev_desc));
+
+ dev_desc.Version = DEVICE_DESCRIPTION_VERSION;
+ dev_desc.Master = TRUE;
+ dev_desc.ScatterGather = TRUE;
+ dev_desc.Dma32BitAddresses = TRUE;
+ dev_desc.BusNumber = bus;
+ dev_desc.InterfaceType = PCIBus;
+ dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
+
+ pdev_ext->map_regs = 2; // we do not use it seriously
+
+ pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs);
+
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_alloc(): padapter=0x%x\n", pdev_ext->padapter));
+ if (pdev_ext->padapter == NULL)
+ {
+ //fatal error
+ ehci_delete_device(pdev);
+ return NULL;
+ }
+
+ DbgPrint("ehci_alloc(): reg_path=0x%x, \n \
+ ehci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
+ ehci_alloc(): slot_num=0x%x, &res_list=0x%x \n \
+ ehci_alloc(): adapter=0x%x \n", (DWORD) reg_path, (DWORD) PCIBus, (DWORD) bus, (DWORD) bus_addr, (DWORD) slot_num.u.AsULONG, (DWORD) & pdev_ext->res_list, pdev_ext->padapter);
+
+ //let's allocate resources for this device
+ DbgPrint("ehci_alloc(): about to assign slot res\n");
+ if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet
+ drvr_obj, NULL, //no support of another ehci controller
+ PCIBus,
+ bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS)
+ {
+ DbgPrint("ehci_alloc(): error assign slot res, 0x%x\n", status);
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ ehci_delete_device(pdev);
+ return NULL;
+ }
+
+ //parse the resource list
+ for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++)
+ {
+ for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count;
+ prd_num++)
+ {
+ pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num];
+ if (pprd->Type == CmResourceTypePort)
+ {
+ RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port));
+
+ }
+ else if (pprd->Type == CmResourceTypeInterrupt)
+ {
+ RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt));
+ }
+ else if (pprd->Type == CmResourceTypeMemory)
+ {
+ RtlCopyMemory(&pdev_ext->res_memory, &pprd->u.Memory, sizeof(pprd->u.Memory));
+ }
+ }
+ }
+
+ //for port, translate them to system address
+ addr_space = 0;
+ if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space
+ &pdev_ext->ehci->ehci_reg_base) != (BOOLEAN) TRUE)
+ {
+ DbgPrint("ehci_alloc(): error, can not translate bus address\n");
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ ehci_delete_device(pdev);
+ return NULL;
+ }
+
+ DbgPrint("ehci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
+ addr_space, pdev_ext->ehci->ehci_reg_base.u.LowPart);
+
+ if (addr_space == 0)
+ {
+ //port has been mapped to memory space
+ pdev_ext->ehci->port_mapped = TRUE;
+ pdev_ext->ehci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->ehci->ehci_reg_base,
+ pdev_ext->res_port.Length, FALSE);
+
+ //fatal error can not map the registers
+ if (pdev_ext->ehci->port_base == NULL)
+ {
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ ehci_delete_device(pdev);
+ return NULL;
+ }
+ }
+ else
+ {
+ //io space
+ pdev_ext->ehci->port_mapped = FALSE;
+ pdev_ext->ehci->port_base = (PBYTE) pdev_ext->ehci->ehci_reg_base.LowPart;
+ }
+
+ //before we connect the interrupt, we have to init ehci
+ pdev_ext->ehci->pdev_ext = pdev_ext;
+
+ //init ehci_caps
+ // i = ( ( PEHCI_HCS_CONTENT )( &pdev_ext->ehci->ehci_caps.hcs_params ) )->length;
+
+ ehci_get_capabilities(pdev_ext->ehci, pdev_ext->ehci->port_base);
+ i = pdev_ext->ehci->ehci_caps.length;
+ pdev_ext->ehci->port_base += i;
+
+ if (ehci_init_schedule(pdev_ext->ehci, pdev_ext->padapter) == FALSE)
+ {
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ ehci_delete_device(pdev);
+ return NULL;
+ }
+
+ InitializeListHead(&pdev_ext->ehci->urb_list);
+ KeInitializeSpinLock(&pdev_ext->ehci->pending_endp_list_lock);
+ InitializeListHead(&pdev_ext->ehci->pending_endp_list);
+
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_alloc(): pending_endp_list=0x%x\n",
+ &pdev_ext->ehci->pending_endp_list));
+
+ init_pending_endp_pool(&pdev_ext->ehci->pending_endp_pool);
+
+ KeInitializeTimer(&pdev_ext->ehci->reset_timer);
+
+ vector = HalGetInterruptVector(PCIBus,
+ bus,
+ pdev_ext->res_interrupt.level,
+ pdev_ext->res_interrupt.vector, &irql, &affinity);
+
+ //connect the interrupt
+ DbgPrint("ehci_alloc(): the int=0x%x\n", vector);
+ if (IoConnectInterrupt(&pdev_ext->ehci_int, ehci_isr, pdev_ext->ehci, NULL, //&pdev_ext->ehci->frame_list_lock,
+ vector, irql, irql, LevelSensitive, TRUE, //share the vector
+ affinity, FALSE) //No float save
+ != STATUS_SUCCESS)
+ {
+ ehci_release(pdev);
+ return NULL;
+ }
+
+ KeInitializeDpc(&pdev_ext->ehci_dpc, ehci_dpc_callback, (PVOID) pdev_ext->ehci);
+
+ return pdev;
+}
+
+PDEVICE_OBJECT
+ehci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr)
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT pdev;
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+
+ UNICODE_STRING dev_name;
+ UNICODE_STRING symb_name;
+
+ STRING string, another_string;
+ CHAR str_dev_name[64], str_symb_name[64];
+ UCHAR hcd_id;
+
+ if (drvr_obj == NULL)
+ return NULL;
+
+ //note: hcd count wont increment till the hcd is registered in dev_mgr
+ sprintf(str_dev_name, "%s%d", EHCI_DEVICE_NAME, dev_mgr->hcd_count);
+ sprintf(str_symb_name, "%s%d", EHCI_DOS_DEVICE_NAME, dev_mgr->hcd_count);
+
+ RtlInitString(&string, str_dev_name);
+ RtlAnsiStringToUnicodeString(&dev_name, &string, TRUE);
+
+ pdev = NULL;
+ status = IoCreateDevice(drvr_obj,
+ sizeof(EHCI_DEVICE_EXTENSION) + sizeof(EHCI_DEV),
+ &dev_name, FILE_EHCI_DEV_TYPE, 0, FALSE, &pdev);
+
+ if (status != STATUS_SUCCESS || pdev == NULL)
+ {
+ RtlFreeUnicodeString(&dev_name);
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_create_device(): error create device 0x%x\n", status));
+ return NULL;
+ }
+
+ pdev_ext = pdev->DeviceExtension;
+ RtlZeroMemory(pdev_ext, sizeof(EHCI_DEVICE_EXTENSION) + sizeof(EHCI_DEV));
+
+ pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD;
+ pdev_ext->dev_ext_hdr.dispatch = ehci_dispatch_irp;
+ pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio
+ pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
+
+ pdev_ext->pdev_obj = pdev;
+ pdev_ext->pdrvr_obj = drvr_obj;
+
+ pdev_ext->ehci = (PEHCI_DEV) & (pdev_ext[1]);
+
+ RtlInitString(&another_string, str_symb_name);
+ RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE);
+ //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME );
+
+ IoCreateSymbolicLink(&symb_name, &dev_name);
+
+ ehci_dbg_print(DBGLVL_MAXIMUM,
+ ("ehci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev,
+ pdev_ext, pdev_ext->ehci, dev_mgr));
+
+ RtlFreeUnicodeString(&dev_name);
+ RtlFreeUnicodeString(&symb_name);
+
+ //register with dev_mgr though it is not initilized
+ ehci_init_hcd_interface(pdev_ext->ehci);
+ hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->ehci->hcd_interf);
+
+ pdev_ext->ehci->hcd_interf.hcd_set_id(&pdev_ext->ehci->hcd_interf, hcd_id);
+ pdev_ext->ehci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->ehci->hcd_interf, dev_mgr);
+
+ return pdev;
+
+}
+
+VOID
+ehci_init_hcd_interface(PEHCI_DEV ehci)
+{
+ ehci->hcd_interf.hcd_set_dev_mgr = ehci_set_dev_mgr;
+ ehci->hcd_interf.hcd_get_dev_mgr = ehci_get_dev_mgr;
+ ehci->hcd_interf.hcd_get_type = ehci_get_type;
+ ehci->hcd_interf.hcd_set_id = ehci_set_id;
+ ehci->hcd_interf.hcd_get_id = ehci_get_id;
+ ehci->hcd_interf.hcd_alloc_addr = ehci_alloc_addr;
+ ehci->hcd_interf.hcd_free_addr = ehci_free_addr;
+ ehci->hcd_interf.hcd_submit_urb = ehci_submit_urb2;
+ ehci->hcd_interf.hcd_generic_urb_completion = ehci_generic_urb_completion;
+ ehci->hcd_interf.hcd_get_root_hub = ehci_get_root_hub;
+ ehci->hcd_interf.hcd_set_root_hub = ehci_set_root_hub;
+ ehci->hcd_interf.hcd_remove_device = ehci_remove_device2;
+ ehci->hcd_interf.hcd_rh_reset_port = ehci_rh_reset_port;
+ ehci->hcd_interf.hcd_release = ehci_hcd_release;
+ ehci->hcd_interf.hcd_cancel_urb = ehci_cancel_urb2;
+ ehci->hcd_interf.hcd_start = ehci_start;
+ ehci->hcd_interf.hcd_dispatch = ehci_hcd_dispatch;
+
+ ehci->hcd_interf.flags = HCD_TYPE_EHCI; //hcd types | hcd id
+}
+
+BOOL
+ehci_init_schedule(PEHCI_DEV ehci, PADAPTER_OBJECT padapter)
+{
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+ BOOL ret;
+ LONG i;
+ PEHCI_QH_CONTENT pqh_content;
+ PEHCI_QH pqh;
+ PEHCI_QTD ptd;
+ PEHCI_ELEM_LINKS pelnk;
+ PEHCI_FSTN pfstn;
+
+ if (ehci == NULL)
+ return FALSE;
+
+ pdev_ext = ehci->pdev_ext;
+ if (pdev_ext == NULL)
+ return FALSE;
+
+ // padapter = pdev_ext->padapter;
+ if (ehci->frame_count == 0)
+ ehci->frame_count = EHCI_DEFAULT_FRAMES;
+
+ // allocate pools
+ for(i = 0; i < 5; i++)
+ {
+ ret = elem_pool_init_pool(&ehci->elem_pools[i], i, padapter);
+ if (ret == FALSE)
+ break;
+ }
+
+ if (ret == FALSE)
+ {
+ i--;
+ for(; i >= 0; i--)
+ elem_pool_destroy_pool(&ehci->elem_pools[i]);
+ return FALSE;
+ }
+
+ // allocate periodic frame list
+ ehci->frame_list =
+ HalAllocateCommonBuffer(padapter,
+ sizeof(ULONG) * ehci->frame_count, &ehci->frame_list_phys_addr, FALSE);
+ if (ehci->frame_list == NULL)
+ goto ERROR_OUT;
+
+ RtlZeroMemory(ehci->frame_list, sizeof(ULONG) * ehci->frame_count);
+ ehci->frame_list_cpu = usb_alloc_mem(NonPagedPool, sizeof(LIST_HEAD) * ehci->frame_count);
+
+ if (ehci->frame_list_cpu == NULL)
+ goto ERROR_OUT;
+
+ for(i = 0; i < (LONG) ehci->frame_count; i++)
+ {
+ InitializeListHead(&ehci->frame_list_cpu[i].td_link);
+ }
+
+ for(i = 0; i < 8; i++)
+ {
+ InitializeListHead(&ehci->periodic_list_cpu[i]);
+ }
+
+ InitializeListHead(&ehci->async_list_cpu);
+
+ // init frame band budget array
+ ehci->frame_bw = usb_alloc_mem(NonPagedPool, sizeof(USHORT) * ehci->frame_count * 8);
+ if (ehci->frame_bw == NULL)
+ goto ERROR_OUT;
+
+ for(i = 0; i < (LONG) ehci->frame_count * 8; i++)
+ {
+ ehci->frame_bw[i] = EHCI_MAX_SYNC_BUS_TIME;
+ }
+ ehci->min_bw = EHCI_MAX_SYNC_BUS_TIME;
+
+ // chain the 1ms interrupt qh to the schedule
+ if ((pelnk = elem_pool_alloc_elem(&ehci->elem_pools[EHCI_QH_POOL_IDX])) == NULL)
+ goto ERROR_OUT;
- LONG frd_num, prd_num;
- UCHAR buffer[ PCI_COMMON_HDR_LENGTH ];
- PDEVICE_OBJECT pdev;
- PEHCI_DEVICE_EXTENSION pdev_ext;
- ULONG vector, addr_space;
- LONG bus, i;
- KIRQL irql;
- KAFFINITY affinity;
- UCHAR hcd_id;
-
- DEVICE_DESCRIPTION dev_desc;
- CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd;
- PCI_SLOT_NUMBER slot_num;
- NTSTATUS status;
-
-
- pdev = ehci_create_device( drvr_obj, dev_mgr );
-
- if( pdev == NULL )
- return NULL;
-
- pdev_ext = pdev->DeviceExtension;
-
- pdev_ext->pci_addr = bus_addr;
- bus = ( bus_addr >> 8 );
-
- slot_num.u.AsULONG = 0;
- slot_num.u.bits.DeviceNumber = ( ( bus_addr & 0xff ) >> 3 );
- slot_num.u.bits.FunctionNumber = ( bus_addr & 0x07 );
-
- //now create adapter object
- RtlZeroMemory( &dev_desc, sizeof( dev_desc ) );
-
- dev_desc.Version = DEVICE_DESCRIPTION_VERSION;
- dev_desc.Master = TRUE;
- dev_desc.ScatterGather = TRUE;
- dev_desc.Dma32BitAddresses = TRUE;
- dev_desc.BusNumber = bus;
- dev_desc.InterfaceType = PCIBus;
- dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
-
- pdev_ext->map_regs = 2; // we do not use it seriously
-
- pdev_ext->padapter = HalGetAdapter( &dev_desc,
- &pdev_ext->map_regs);
-
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_alloc(): padapter=0x%x\n", pdev_ext->padapter ) );
- if( pdev_ext->padapter == NULL )
- {
- //fatal error
- ehci_delete_device( pdev );
- return NULL;
- }
-
- DbgPrint("ehci_alloc(): reg_path=0x%x, \n \
- ehci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
- ehci_alloc(): slot_num=0x%x, &res_list=0x%x \n \
- ehci_alloc(): adapter=0x%x \n", \
- ( DWORD )reg_path, \
- ( DWORD )PCIBus, \
- ( DWORD )bus, \
- ( DWORD )bus_addr,\
- ( DWORD )slot_num.u.AsULONG, \
- ( DWORD )&pdev_ext->res_list, \
- pdev_ext->padapter);
-
- //let's allocate resources for this device
- DbgPrint( "ehci_alloc(): about to assign slot res\n" );
- if( ( status = HalAssignSlotResources(
- reg_path,
- NULL, //no class name yet
- drvr_obj,
- NULL, //no support of another ehci controller
- PCIBus,
- bus,
- slot_num.u.AsULONG,
- &pdev_ext->res_list ) )
- != STATUS_SUCCESS )
- {
- DbgPrint( "ehci_alloc(): error assign slot res, 0x%x\n", status );
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- ehci_delete_device( pdev );
- return NULL;
- }
-
- //parse the resource list
- for( frd_num = 0; frd_num < ( LONG )pdev_ext->res_list->Count; frd_num ++ )
- {
- for( prd_num = 0; prd_num < ( LONG )pdev_ext->res_list->List[ frd_num ].PartialResourceList.Count; prd_num ++ )
- {
- pprd = &pdev_ext->res_list->List[ frd_num ].PartialResourceList.PartialDescriptors[ prd_num ];
- if( pprd->Type == CmResourceTypePort )
- {
- RtlCopyMemory( &pdev_ext->res_port, &pprd->u.Port, sizeof( pprd->u.Port ) );
-
- }
- else if( pprd->Type == CmResourceTypeInterrupt )
- {
- RtlCopyMemory( &pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof( pprd->u.Interrupt ) );
- }
- else if( pprd->Type == CmResourceTypeMemory )
- {
- RtlCopyMemory( &pdev_ext->res_memory, &pprd->u.Memory, sizeof( pprd->u.Memory ) );
- }
- }
- }
-
- //for port, translate them to system address
- addr_space = 0;
- if( HalTranslateBusAddress(
- PCIBus,
- bus,
- pdev_ext->res_port.Start,
- &addr_space, //io space
- &pdev_ext->ehci->ehci_reg_base
- )
- != ( BOOLEAN )TRUE )
- {
- DbgPrint( "ehci_alloc(): error, can not translate bus address\n" );
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- ehci_delete_device( pdev );
- return NULL;
- }
-
- DbgPrint( "ehci_alloc(): address space=0x%x\n, reg_base=0x%x\n", \
- addr_space, pdev_ext->ehci->ehci_reg_base.u.LowPart );
-
- if( addr_space == 0 )
- {
- //port has been mapped to memory space
- pdev_ext->ehci->port_mapped = TRUE;
- pdev_ext->ehci->port_base = ( PBYTE )MmMapIoSpace(
- pdev_ext->ehci->ehci_reg_base,
- pdev_ext->res_port.Length,
- FALSE );
-
- //fatal error can not map the registers
- if( pdev_ext->ehci->port_base == NULL )
- {
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- ehci_delete_device( pdev );
- return NULL;
- }
- }
- else
- {
- //io space
- pdev_ext->ehci->port_mapped = FALSE;
- pdev_ext->ehci->port_base = ( PBYTE )pdev_ext->ehci->ehci_reg_base.LowPart;
- }
-
- //before we connect the interrupt, we have to init ehci
- pdev_ext->ehci->pdev_ext = pdev_ext;
-
- //init ehci_caps
- // i = ( ( PEHCI_HCS_CONTENT )( &pdev_ext->ehci->ehci_caps.hcs_params ) )->length;
-
- ehci_get_capabilities( pdev_ext->ehci, pdev_ext->ehci->port_base );
- i = pdev_ext->ehci->ehci_caps.length;
- pdev_ext->ehci->port_base += i;
-
- if( ehci_init_schedule( pdev_ext->ehci, pdev_ext->padapter ) == FALSE )
- {
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- ehci_delete_device( pdev );
- return NULL;
- }
-
- InitializeListHead( &pdev_ext->ehci->urb_list );
- KeInitializeSpinLock( &pdev_ext->ehci->pending_endp_list_lock );
- InitializeListHead( &pdev_ext->ehci->pending_endp_list );
-
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_alloc(): pending_endp_list=0x%x\n", \
- &pdev_ext->ehci->pending_endp_list ) );
-
- init_pending_endp_pool( &pdev_ext->ehci->pending_endp_pool );
-
- KeInitializeTimer( &pdev_ext->ehci->reset_timer );
-
- vector = HalGetInterruptVector(
- PCIBus,
- bus,
- pdev_ext->res_interrupt.level,
- pdev_ext->res_interrupt.vector,
- &irql,
- &affinity);
-
- //connect the interrupt
- DbgPrint( "ehci_alloc(): the int=0x%x\n", vector );
- if( IoConnectInterrupt(
- &pdev_ext->ehci_int,
- ehci_isr,
- pdev_ext->ehci,
- NULL, //&pdev_ext->ehci->frame_list_lock,
- vector,
- irql,
- irql,
- LevelSensitive,
- TRUE, //share the vector
- affinity,
- FALSE ) //No float save
- != STATUS_SUCCESS )
- {
- ehci_release( pdev );
- return NULL;
- }
-
- KeInitializeDpc( &pdev_ext->ehci_dpc,
- ehci_dpc_callback,
- ( PVOID )pdev_ext->ehci );
-
- return pdev;
-}
+ pqh_content = (PEHCI_QH_CONTENT) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ ehci_init_int8_qh(pqh_content);
-PDEVICE_OBJECT
-ehci_create_device(
-PDRIVER_OBJECT drvr_obj,
-PUSB_DEV_MANAGER dev_mgr
-)
-{
- NTSTATUS status;
- PDEVICE_OBJECT pdev;
- PEHCI_DEVICE_EXTENSION pdev_ext;
-
- UNICODE_STRING dev_name;
- UNICODE_STRING symb_name;
-
- STRING string, another_string;
- CHAR str_dev_name[ 64 ], str_symb_name[ 64 ];
- UCHAR hcd_id;
-
- if( drvr_obj == NULL )
- return NULL;
-
- //note: hcd count wont increment till the hcd is registered in dev_mgr
- sprintf( str_dev_name, "%s%d", EHCI_DEVICE_NAME, dev_mgr->hcd_count );
- sprintf( str_symb_name, "%s%d",EHCI_DOS_DEVICE_NAME, dev_mgr->hcd_count );
-
- RtlInitString( &string, str_dev_name );
- RtlAnsiStringToUnicodeString( &dev_name, &string, TRUE );
-
- pdev = NULL;
- status = IoCreateDevice(
- drvr_obj,
- sizeof( EHCI_DEVICE_EXTENSION ) + sizeof( EHCI_DEV ),
- &dev_name,
- FILE_EHCI_DEV_TYPE,
- 0,
- FALSE,
- &pdev);
-
- if( status != STATUS_SUCCESS || pdev == NULL )
- {
- RtlFreeUnicodeString( &dev_name );
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_create_device(): error create device 0x%x\n", status ) );
- return NULL;
- }
-
- pdev_ext = pdev->DeviceExtension;
- RtlZeroMemory(
- pdev_ext,
- sizeof( EHCI_DEVICE_EXTENSION )
- + sizeof( EHCI_DEV) );
-
- pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD;
- pdev_ext->dev_ext_hdr.dispatch = ehci_dispatch_irp;
- pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio
- pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
-
- pdev_ext->pdev_obj = pdev;
- pdev_ext->pdrvr_obj = drvr_obj;
-
- pdev_ext->ehci = ( PEHCI_DEV ) &( pdev_ext[ 1 ] );
-
- RtlInitString( &another_string, str_symb_name );
- RtlAnsiStringToUnicodeString( &symb_name, &another_string, TRUE );
- //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME );
-
- IoCreateSymbolicLink( &symb_name, &dev_name );
-
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", \
- pdev,\
- pdev_ext,\
- pdev_ext->ehci, \
- dev_mgr ) );
-
- RtlFreeUnicodeString( &dev_name );
- RtlFreeUnicodeString( &symb_name );
-
- //register with dev_mgr though it is not initilized
- ehci_init_hcd_interface( pdev_ext->ehci );
- hcd_id = dev_mgr_register_hcd( dev_mgr, &pdev_ext->ehci->hcd_interf );
-
- pdev_ext->ehci->hcd_interf.hcd_set_id( &pdev_ext->ehci->hcd_interf, hcd_id );
- pdev_ext->ehci->hcd_interf.hcd_set_dev_mgr( &pdev_ext->ehci->hcd_interf, dev_mgr );
-
- return pdev;
+ // chain qh to the shadow list
+ InsertTailList(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], &pelnk->sched_link);
-}
+ // chain it to the periodic schedule, we use it as a docking point
+ // for req of 8- uframes request
+ pqh = (PEHCI_QH) pqh_content;
-VOID
-ehci_init_hcd_interface(
-PEHCI_DEV ehci
-)
-{
- ehci->hcd_interf.hcd_set_dev_mgr = ehci_set_dev_mgr;
- ehci->hcd_interf.hcd_get_dev_mgr = ehci_get_dev_mgr;
- ehci->hcd_interf.hcd_get_type = ehci_get_type;
- ehci->hcd_interf.hcd_set_id = ehci_set_id;
- ehci->hcd_interf.hcd_get_id = ehci_get_id;
- ehci->hcd_interf.hcd_alloc_addr = ehci_alloc_addr;
- ehci->hcd_interf.hcd_free_addr = ehci_free_addr;
- ehci->hcd_interf.hcd_submit_urb = ehci_submit_urb2;
- ehci->hcd_interf.hcd_generic_urb_completion = ehci_generic_urb_completion;
- ehci->hcd_interf.hcd_get_root_hub = ehci_get_root_hub;
- ehci->hcd_interf.hcd_set_root_hub = ehci_set_root_hub;
- ehci->hcd_interf.hcd_remove_device = ehci_remove_device2;
- ehci->hcd_interf.hcd_rh_reset_port = ehci_rh_reset_port;
- ehci->hcd_interf.hcd_release = ehci_hcd_release;
- ehci->hcd_interf.hcd_cancel_urb = ehci_cancel_urb2;
- ehci->hcd_interf.hcd_start = ehci_start;
- ehci->hcd_interf.hcd_dispatch = ehci_hcd_dispatch;
-
- ehci->hcd_interf.flags = HCD_TYPE_EHCI; //hcd types | hcd id
-}
+ for(i = 0; i < (LONG) ehci->frame_count; i++)
+ {
+ ehci->frame_list[i] = pqh->phys_addr;
+ }
-BOOL
-ehci_init_schedule(
-PEHCI_DEV ehci,
-PADAPTER_OBJECT padapter
-)
-{
- PEHCI_DEVICE_EXTENSION pdev_ext;
- BOOL ret;
- LONG i;
- PEHCI_QH_CONTENT pqh_content;
- PEHCI_QH pqh;
- PEHCI_QTD ptd;
- PEHCI_ELEM_LINKS pelnk;
- PEHCI_FSTN pfstn;
-
- if( ehci == NULL )
- return FALSE;
-
- pdev_ext = ehci->pdev_ext;
- if( pdev_ext == NULL )
- return FALSE;
-
- // padapter = pdev_ext->padapter;
- if( ehci->frame_count == 0 )
- ehci->frame_count = EHCI_DEFAULT_FRAMES;
-
- // allocate pools
- for( i = 0; i < 5; i++ )
- {
- ret = elem_pool_init_pool( &ehci->elem_pools[ i ], i, padapter );
- if( ret == FALSE )
- break;
- }
-
- if( ret == FALSE )
- {
- i--;
- for( ; i >= 0; i-- )
- elem_pool_destroy_pool( &ehci->elem_pools[ i ] );
- return FALSE;
- }
-
- // allocate periodic frame list
- ehci->frame_list = \
- HalAllocateCommonBuffer(
- padapter,
- sizeof(ULONG) * ehci->frame_count,
- &ehci->frame_list_phys_addr,
- FALSE);
- if( ehci->frame_list == NULL )
- goto ERROR_OUT;
-
- RtlZeroMemory( ehci->frame_list, sizeof( ULONG ) * ehci->frame_count );
- ehci->frame_list_cpu = usb_alloc_mem( NonPagedPool, sizeof( LIST_HEAD ) * ehci->frame_count );
-
- if( ehci->frame_list_cpu == NULL )
- goto ERROR_OUT;
-
- for( i = 0; i < ( LONG )ehci->frame_count; i++ )
- {
- InitializeListHead( &ehci->frame_list_cpu[ i ].td_link );
- }
-
- for( i = 0; i < 8; i++ )
- {
- InitializeListHead( &ehci->periodic_list_cpu[ i ] );
- }
-
- InitializeListHead( &ehci->async_list_cpu );
-
- // init frame band budget array
- ehci->frame_bw = usb_alloc_mem( NonPagedPool, sizeof( USHORT ) * ehci->frame_count * 8 );
- if( ehci->frame_bw == NULL )
- goto ERROR_OUT;
-
- for( i = 0; i < ( LONG )ehci->frame_count * 8; i++ )
- {
- ehci->frame_bw[ i ] = EHCI_MAX_SYNC_BUS_TIME;
- }
- ehci->min_bw = EHCI_MAX_SYNC_BUS_TIME;
-
- // chain the 1ms interrupt qh to the schedule
- if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_QH_POOL_IDX ] ) ) == NULL )
- goto ERROR_OUT;
-
- pqh_content = ( PEHCI_QH_CONTENT )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- ehci_init_int8_qh( pqh_content );
-
- // chain qh to the shadow list
- InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], &pelnk->sched_link );
-
- // chain it to the periodic schedule, we use it as a docking point
- // for req of 8- uframes request
- pqh = ( PEHCI_QH )pqh_content;
-
- for( i = 0; i < ( LONG )ehci->frame_count; i++ )
- {
- ehci->frame_list[ i ] = pqh->phys_addr;
- }
-
- // allocate fstn
- /*if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) ) == NULL )
- goto ERROR_OUT;
-
- pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- pfstn->hw_next = EHCI_PTR_TERM;
- pfstn->hw_prev = EHCI_PTR_TERM | ( INIT_LIST_FLAG_QH << 1 );
- InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ], &pelnk->sched_link );
- pqh->hw_next = pfstn->phys_addr;*/
-
- // allocate for async list head
- if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_QH_POOL_IDX ] ) ) == NULL )
- goto ERROR_OUT;
-
- // init the async list head
- pqh = ( PEHCI_QH )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
- pqh_content = ( PEHCI_QH_CONTENT )pqh;
- ehci_init_int8_qh( pqh_content );
- pqh->hw_next = pqh->phys_addr;
- pqh_content->s_mask = 0;
- pqh_content->is_async_head = 1;
- pqh_content->endp_addr = 0;
- ehci->skel_async_qh = pqh;
- InsertTailList( &ehci->async_list_cpu, &pqh->elem_head_link->sched_link );
- return TRUE;
-
-ERROR_OUT:
- ehci_destroy_schedule( ehci );
- return FALSE;
+ // allocate fstn
+ /*if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) ) == NULL )
+ goto ERROR_OUT;
+
+ pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
+ pfstn->hw_next = EHCI_PTR_TERM;
+ pfstn->hw_prev = EHCI_PTR_TERM | ( INIT_LIST_FLAG_QH << 1 );
+ InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ], &pelnk->sched_link );
+ pqh->hw_next = pfstn->phys_addr; */
+
+ // allocate for async list head
+ if ((pelnk = elem_pool_alloc_elem(&ehci->elem_pools[EHCI_QH_POOL_IDX])) == NULL)
+ goto ERROR_OUT;
+
+ // init the async list head
+ pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
+ pqh_content = (PEHCI_QH_CONTENT) pqh;
+ ehci_init_int8_qh(pqh_content);
+ pqh->hw_next = pqh->phys_addr;
+ pqh_content->s_mask = 0;
+ pqh_content->is_async_head = 1;
+ pqh_content->endp_addr = 0;
+ ehci->skel_async_qh = pqh;
+ InsertTailList(&ehci->async_list_cpu, &pqh->elem_head_link->sched_link);
+ return TRUE;
+
+ ERROR_OUT:
+ ehci_destroy_schedule(ehci);
+ return FALSE;
}
BOOL
-ehci_destroy_schedule(
-PEHCI_DEV ehci
-)
+ehci_destroy_schedule(PEHCI_DEV ehci)
{
- LONG i;
- if( ehci == NULL )
- return FALSE;
-
- if( ehci->frame_bw )
- usb_free_mem( ehci->frame_bw );
- ehci->frame_bw = NULL;
-
- if( ehci->frame_list_cpu )
- usb_free_mem( ehci->frame_list_cpu );
- ehci->frame_list_cpu = NULL;
-
- if( ehci->frame_list )
- HalFreeCommonBuffer( \
- ehci->pdev_ext->padapter,
- sizeof(ULONG) * ehci->frame_count,
- ehci->frame_list_phys_addr,
- ehci->frame_list,
- FALSE );
-
- ehci->frame_list = NULL;
- ehci->frame_list_phys_addr.LowPart = 0;
- ehci->frame_list_phys_addr.HighPart = 0;
-
- for( i = 0; i < 5; i++ )
- elem_pool_destroy_pool( &ehci->elem_pools[ i ] );
-
- return TRUE;
+ LONG i;
+ if (ehci == NULL)
+ return FALSE;
+
+ if (ehci->frame_bw)
+ usb_free_mem(ehci->frame_bw);
+ ehci->frame_bw = NULL;
+
+ if (ehci->frame_list_cpu)
+ usb_free_mem(ehci->frame_list_cpu);
+ ehci->frame_list_cpu = NULL;
+
+ if (ehci->frame_list)
+ HalFreeCommonBuffer(ehci->pdev_ext->padapter,
+ sizeof(ULONG) * ehci->frame_count,
+ ehci->frame_list_phys_addr, ehci->frame_list, FALSE);
+
+ ehci->frame_list = NULL;
+ ehci->frame_list_phys_addr.LowPart = 0;
+ ehci->frame_list_phys_addr.HighPart = 0;
+
+ for(i = 0; i < 5; i++)
+ elem_pool_destroy_pool(&ehci->elem_pools[i]);
+
+ return TRUE;
}
VOID
-ehci_init_int8_qh(
-PEHCI_QH_CONTENT qh
-)
+ehci_init_int8_qh(PEHCI_QH_CONTENT qh)
{
- if( qh == NULL )
- return;
- // DWORD 0
- qh->terminal = EHCI_PTR_TERM;
- qh->ptr_type = 0;
- qh->reserved = 0;
- qh->next_link = 0;
-
- // DWORD 1
- qh->dev_addr = 126; // a fake addr
- qh->inactive = 0;
- qh->endp_addr = 1; // a fake endp
- qh->endp_spd = USB_SPEED_HIGH;
- qh->data_toggle = 0;
- qh->is_async_head = 0;
- qh->max_packet_size = 64;
- qh->is_ctrl_endp = 0;
- qh->reload_counter = 0;
-
- // DWORD 2
- qh->s_mask = 0x80; // we are interrupt qh
- qh->c_mask = 0;
- qh->hub_addr = 0;
- qh->port_idx = 0;
- qh->mult = 1;
-
- // DWORD 3
- qh->cur_qtd_ptr = 0; // a terminal
-
- // overlay
- // !active and !halted
- RtlZeroMemory( &qh->cur_qtd, get_elem_phys_part_size( INIT_LIST_FLAG_QTD ) );
- qh->cur_qtd.alt_terminal = 1; // don't use this
- qh->cur_qtd.terminal = 1;
- qh->cur_qtd.status = QTD_STS_HALT;
+ if (qh == NULL)
+ return;
+ // DWORD 0
+ qh->terminal = EHCI_PTR_TERM;
+ qh->ptr_type = 0;
+ qh->reserved = 0;
+ qh->next_link = 0;
+
+ // DWORD 1
+ qh->dev_addr = 126; // a fake addr
+ qh->inactive = 0;
+ qh->endp_addr = 1; // a fake endp
+ qh->endp_spd = USB_SPEED_HIGH;
+ qh->data_toggle = 0;
+ qh->is_async_head = 0;
+ qh->max_packet_size = 64;
+ qh->is_ctrl_endp = 0;
+ qh->reload_counter = 0;
+
+ // DWORD 2
+ qh->s_mask = 0x80; // we are interrupt qh
+ qh->c_mask = 0;
+ qh->hub_addr = 0;
+ qh->port_idx = 0;
+ qh->mult = 1;
+
+ // DWORD 3
+ qh->cur_qtd_ptr = 0; // a terminal
+
+ // overlay
+ // !active and !halted
+ RtlZeroMemory(&qh->cur_qtd, get_elem_phys_part_size(INIT_LIST_FLAG_QTD));
+ qh->cur_qtd.alt_terminal = 1; // don't use this
+ qh->cur_qtd.terminal = 1;
+ qh->cur_qtd.status = QTD_STS_HALT;
}
VOID
-ehci_get_capabilities(
-PEHCI_DEV ehci,
-PBYTE base
-)
+ehci_get_capabilities(PEHCI_DEV ehci, PBYTE base)
// fetch capabilities register from ehci
{
- NTSTATUS status;
- PEHCI_CAPS pcap;
- PEHCI_HCS_CONTENT phcs;
- LONG i;
-
- if( ehci == NULL )
- return;
-
- pcap = &ehci->ehci_caps;
- pcap->length = EHCI_READ_PORT_UCHAR( ( PUCHAR )( base + 0 ) );
- pcap->reserved = EHCI_READ_PORT_UCHAR( ( PUCHAR )( base + 1 ) );
- pcap->hci_version = EHCI_READ_PORT_USHORT( ( PUSHORT )( base + 2 ) );
- pcap->hcs_params = EHCI_READ_PORT_ULONG( ( PULONG )( base + 4 ) );
- pcap->hcc_params = EHCI_READ_PORT_ULONG( ( PULONG )( base + 8 ) );
-
- phcs = ( PEHCI_HCS_CONTENT )&pcap->hcs_params;
- if( phcs->port_rout_rules )
- {
- for( i = 0; i < 8; i++ )
- pcap->portroute [ i ] = EHCI_READ_PORT_UCHAR( ( PUCHAR )( base + 12 + i ) );
- }
- return;
+ NTSTATUS status;
+ PEHCI_CAPS pcap;
+ PEHCI_HCS_CONTENT phcs;
+ LONG i;
+
+ if (ehci == NULL)
+ return;
+
+ pcap = &ehci->ehci_caps;
+ pcap->length = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 0));
+ pcap->reserved = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 1));
+ pcap->hci_version = EHCI_READ_PORT_USHORT((PUSHORT) (base + 2));
+ pcap->hcs_params = EHCI_READ_PORT_ULONG((PULONG) (base + 4));
+ pcap->hcc_params = EHCI_READ_PORT_ULONG((PULONG) (base + 8));
+
+ phcs = (PEHCI_HCS_CONTENT) & pcap->hcs_params;
+ if (phcs->port_rout_rules)
+ {
+ for(i = 0; i < 8; i++)
+ pcap->portroute[i] = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 12 + i));
+ }
+ return;
}
BOOL
-ehci_delete_device(
-PDEVICE_OBJECT pdev
-)
+ehci_delete_device(PDEVICE_OBJECT pdev)
{
- STRING string;
- UNICODE_STRING symb_name;
- CHAR str_symb_name[ 64 ];
- PEHCI_DEVICE_EXTENSION pdev_ext;
-
- if( pdev == NULL )
- return FALSE;
-
- pdev_ext = pdev->DeviceExtension;
-
- sprintf( str_symb_name,
- "%s%d",
- EHCI_DOS_DEVICE_NAME,
- pdev_ext->ehci->hcd_interf.hcd_get_id( &pdev_ext->ehci->hcd_interf ) );
-
- RtlInitString( &string, str_symb_name );
- RtlAnsiStringToUnicodeString( &symb_name, &string, TRUE );
- IoDeleteSymbolicLink( &symb_name );
- RtlFreeUnicodeString( &symb_name );
-
- if( pdev_ext->res_list )
- ExFreePool( pdev_ext->res_list ); // not allocated by usb_alloc_mem
-
- IoDeleteDevice( pdev );
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_delete_device(): device deleted\n" ) );
- return TRUE;
+ STRING string;
+ UNICODE_STRING symb_name;
+ CHAR str_symb_name[64];
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+
+ if (pdev == NULL)
+ return FALSE;
+
+ pdev_ext = pdev->DeviceExtension;
+
+ sprintf(str_symb_name,
+ "%s%d", EHCI_DOS_DEVICE_NAME, pdev_ext->ehci->hcd_interf.hcd_get_id(&pdev_ext->ehci->hcd_interf));
+
+ RtlInitString(&string, str_symb_name);
+ RtlAnsiStringToUnicodeString(&symb_name, &string, TRUE);
+ IoDeleteSymbolicLink(&symb_name);
+ RtlFreeUnicodeString(&symb_name);
+
+ if (pdev_ext->res_list)
+ ExFreePool(pdev_ext->res_list); // not allocated by usb_alloc_mem
+
+ IoDeleteDevice(pdev);
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_delete_device(): device deleted\n"));
+ return TRUE;
}
VOID
-ehci_stop(
-PEHCI_DEV ehci
-)
+ehci_stop(PEHCI_DEV ehci)
{
- PBYTE base;
- PEHCI_USBCMD_CONTENT usbcmd;
- LONG tmp;
-
- base = ehci->port_base;
- // turn off all the interrupt
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBINTR ), 0 );
- tmp = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ) );
- usbcmd = ( PEHCI_USBCMD_CONTENT )&tmp;
- usbcmd->run_stop = 0;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
+ PBYTE base;
+ PEHCI_USBCMD_CONTENT usbcmd;
+ LONG tmp;
+
+ base = ehci->port_base;
+ // turn off all the interrupt
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR), 0);
+ tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
+ usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
+ usbcmd->run_stop = 0;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
}
BOOL
-ehci_release(
-PDEVICE_OBJECT pdev
-)
+ehci_release(PDEVICE_OBJECT pdev)
{
- PEHCI_DEVICE_EXTENSION pdev_ext;
- PEHCI_DEV ehci;
- KIRQL disp_level;
- KIRQL old_level;
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+ PEHCI_DEV ehci;
+ KIRQL disp_level;
+ KIRQL old_level;
- if( pdev == NULL )
- return FALSE;
+ if (pdev == NULL)
+ return FALSE;
- pdev_ext = pdev->DeviceExtension;
+ pdev_ext = pdev->DeviceExtension;
- if( pdev_ext == NULL )
- return FALSE;
+ if (pdev_ext == NULL)
+ return FALSE;
- ehci = pdev_ext->ehci;
- if( ehci == NULL )
- return FALSE;
+ ehci = pdev_ext->ehci;
+ if (ehci == NULL)
+ return FALSE;
- ehci_stop( ehci );
+ ehci_stop(ehci);
- if( pdev_ext->ehci_int )
+ if (pdev_ext->ehci_int)
{
- IoDisconnectInterrupt( pdev_ext->ehci_int );
- pdev_ext->ehci_int = NULL;
+ IoDisconnectInterrupt(pdev_ext->ehci_int);
+ pdev_ext->ehci_int = NULL;
}
- else
- TRAP();
- destroy_pending_endp_pool( &pdev_ext->ehci->pending_endp_pool );
+ else
+ TRAP();
+ destroy_pending_endp_pool(&pdev_ext->ehci->pending_endp_pool);
- ehci_destroy_schedule( ehci );
+ ehci_destroy_schedule(ehci);
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
- ehci_delete_device( pdev );
+ ehci_delete_device(pdev);
- return FALSE;
+ return FALSE;
}
BOOL
-ehci_start(
-PHCD hcd
-)
+ehci_start(PHCD hcd)
{
- ULONG tmp;
- PBYTE base;
- LONG i;
- PEHCI_USBCMD_CONTENT usbcmd;
- LARGE_INTEGER interval;
- PEHCI_DEV ehci;
-
- if( hcd == NULL )
- return FALSE;
-
- ehci = struct_ptr( hcd, EHCI_DEV, hcd_interf );
- base = ehci->port_base;
-
- // stop the controller
- tmp = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ) );
- usbcmd = ( PEHCI_USBCMD_CONTENT )&tmp;
- usbcmd->run_stop = 0;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
-
- // wait the controller stop( ehci spec, 16 microframe )
- usb_wait_ms_dpc( 2 );
-
- // reset the controller
- usbcmd = ( PEHCI_USBCMD_CONTENT )&tmp;
- usbcmd->hcreset = TRUE;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
-
- for(;;)
- {
- // interval.QuadPart = -100 * 10000; // 10 ms
- // KeDelayExecutionThread( KernelMode, FALSE, &interval );
- KeStallExecutionProcessor( 10 );
- tmp = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ) );
- if( !usbcmd->hcreset )
- break;
- }
-
- // prepare the registers
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_CTRLDSSEGMENT ), 0 );
-
- // turn on all the int
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBINTR ), \
- EHCI_USBINTR_INTE | \
- EHCI_USBINTR_ERR | \
- EHCI_USBINTR_ASYNC | \
- EHCI_USBINTR_HSERR
- // EHCI_USBINTR_FLROVR | \ // it is noisy
- // EHCI_USBINTR_PC | // we detect it by polling
- );
- // write the list base reg
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_PERIODICLISTBASE ), \
- ehci->frame_list_phys_addr.LowPart );
-
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_ASYNCLISTBASE ), \
- ehci->skel_async_qh->phys_addr & ~( 0x1f ) );
-
- usbcmd->int_threshold = 1;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
-
- // let's rock
- usbcmd->run_stop = 1;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
-
- // set the configuration flag
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_CONFIGFLAG ), 1 );
-
- // enable the list traversaling
- usbcmd->async_enable = 1;
- usbcmd->periodic_enable = 1;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
-
- return TRUE;
+ ULONG tmp;
+ PBYTE base;
+ LONG i;
+ PEHCI_USBCMD_CONTENT usbcmd;
+ LARGE_INTEGER interval;
+ PEHCI_DEV ehci;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ ehci = struct_ptr(hcd, EHCI_DEV, hcd_interf);
+ base = ehci->port_base;
+
+ // stop the controller
+ tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
+ usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
+ usbcmd->run_stop = 0;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+
+ // wait the controller stop( ehci spec, 16 microframe )
+ usb_wait_ms_dpc(2);
+
+ // reset the controller
+ usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
+ usbcmd->hcreset = TRUE;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+
+ for(;;)
+ {
+ // interval.QuadPart = -100 * 10000; // 10 ms
+ // KeDelayExecutionThread( KernelMode, FALSE, &interval );
+ KeStallExecutionProcessor(10);
+ tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
+ if (!usbcmd->hcreset)
+ break;
+ }
+
+ // prepare the registers
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CTRLDSSEGMENT), 0);
+
+ // turn on all the int
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR),
+ EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
+ // EHCI_USBINTR_FLROVR | \ // it is noisy
+ // EHCI_USBINTR_PC | // we detect it by polling
+ );
+ // write the list base reg
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_PERIODICLISTBASE), ehci->frame_list_phys_addr.LowPart);
+
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_ASYNCLISTBASE), ehci->skel_async_qh->phys_addr & ~(0x1f));
+
+ usbcmd->int_threshold = 1;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+
+ // let's rock
+ usbcmd->run_stop = 1;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+
+ // set the configuration flag
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CONFIGFLAG), 1);
+
+ // enable the list traversaling
+ usbcmd->async_enable = 1;
+ usbcmd->periodic_enable = 1;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+
+ return TRUE;
}
VOID
-ehci_run_stop(
-PEHCI_DEV ehci,
-BOOL start
-)
+ehci_run_stop(PEHCI_DEV ehci, BOOL start)
{
- PEHCI_USBCMD_CONTENT usbcmd;
- PEHCI_USBSTS_CONTENT usbsts;
- ULONG tmp;
- PBYTE base;
-
- if( ehci == NULL )
- return;
-
- base = ehci->port_base;
- usbcmd = ( PEHCI_USBCMD_CONTENT )&tmp;
- usbsts = ( PEHCI_USBSTS_CONTENT )&tmp;
-
- tmp = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_USBSTS ) );
- if( start && usbsts->hc_halted == 0 )
- {
- TRAP();
- usb_dbg_print( DBGLVL_MEDIUM, ( "ehci_run_stop(): WARNING: hc running, can not start again\n" ) );
- return;
- }
- tmp = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ) );
- usbcmd->run_stop = start ? 1 : 0;
- EHCI_WRITE_PORT_ULONG( ( PULONG )( base + EHCI_USBCMD ), tmp );
- if( start )
- usb_wait_ms_dpc( 2 ); //ehci spec 16 microframes
+ PEHCI_USBCMD_CONTENT usbcmd;
+ PEHCI_USBSTS_CONTENT usbsts;
+ ULONG tmp;
+ PBYTE base;
+
+ if (ehci == NULL)
+ return;
+
+ base = ehci->port_base;
+ usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
+ usbsts = (PEHCI_USBSTS_CONTENT) & tmp;
+
+ tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBSTS));
+ if (start && usbsts->hc_halted == 0)
+ {
+ TRAP();
+ usb_dbg_print(DBGLVL_MEDIUM, ("ehci_run_stop(): WARNING: hc running, can not start again\n"));
+ return;
+ }
+ tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
+ usbcmd->run_stop = start ? 1 : 0;
+ EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
+ if (start)
+ usb_wait_ms_dpc(2); //ehci spec 16 microframes
}
VOID
-ehci_find_min_bandwidth(
-PEHCI_DEV ehci
-)
+ehci_find_min_bandwidth(PEHCI_DEV ehci)
{
- LONG i;
- if( ehci == NULL )
- return;
-
- for( i = 0; i < ( LONG )( ehci->frame_count << 3 ); i++ )
- {
- ehci->min_bw = ehci->min_bw < ehci->frame_bw[ i ] ? ehci->min_bw : ehci->frame_bw[ i ] ;
- }
- return;
+ LONG i;
+ if (ehci == NULL)
+ return;
+
+ for(i = 0; i < (LONG) (ehci->frame_count << 3); i++)
+ {
+ ehci->min_bw = ehci->min_bw < ehci->frame_bw[i] ? ehci->min_bw : ehci->frame_bw[i];
+ }
+ return;
}
BOOL
-ehci_claim_bw_for_int(
-PEHCI_DEV ehci,
-PURB purb,
-BOOL release
-)
+ehci_claim_bw_for_int(PEHCI_DEV ehci, PURB purb, BOOL release)
// should have pending_endp_list_lock acquired, and purb->pipe prepared
{
- PURB_HS_PIPE_CONTENT pipe_content;
- LONG i, j;
- ULONG interval, bus_time, ss_time, cs_time;
- BOOL bw_avail;
- ULONG max_packet_size;
-
- if( ehci == NULL || purb == NULL )
- return FALSE;
-
- if( purb->pipe == 0 )
- return FALSE;
-
- bw_avail = FALSE;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = REAL_INTERVAL;
- if( pipe_content->speed_high == 0 )
- {
- // translate to high speed uframe count
- interval <<= 3;
- }
-
- if( interval > ( ehci->frame_count << 3 ) )
- interval = ( ehci->frame_count << 3 );
-
- max_packet_size = ( 1 << pipe_content->max_packet_size );
- if( pipe_content->speed_high )
- {
- // this is a high speed endp
-
- bus_time = usb_calc_bus_time(
- USB_SPEED_HIGH,
- ( pipe_content->trans_dir ) << 7,
- FALSE,
- min( purb->data_length, ( LONG )max_packet_size )
- );
-
- // multiple transactions per uframe
- if( purb->data_length > ( LONG )max_packet_size )
- {
- bus_time *= ( purb->data_length ) / max_packet_size;
- bus_time += usb_calc_bus_time(
- USB_SPEED_HIGH,
- ( pipe_content->trans_dir ) << 7,
- FALSE,
- purb->data_length % max_packet_size
- );
- }
- bus_time = ( bus_time + 1 ) >> 1;
-
- if( release )
- {
- for( i = pipe_content->start_uframe + ( purb->int_start_frame << 3 ); i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] += ( USHORT )bus_time;
- }
- goto LBL_OUT;
- }
- if( bus_time < ehci->min_bw )
- {
- // start the poll from uframe zero of each frame
- bw_avail = TRUE;
- pipe_content->start_uframe = 0;
- for( i = 0; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] -= ( USHORT )bus_time;
- if( ehci->frame_bw[ i ] < ehci->min_bw )
- ehci->min_bw = ehci->frame_bw[ i ];
- }
- }
- else // bother to find a pattern
- {
- for( j = 0; j < ( LONG )interval; j++ )
- {
- for( i = j; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- if( ehci->frame_bw[ i ] < bus_time )
- break;
- }
- if( i > ( LONG )( ehci->frame_count << 3 ) )
- {
- bw_avail = TRUE;
- break;
- }
- }
- if( bw_avail )
- {
- for( i = j; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] -= ( USHORT )bus_time;
- if( ehci->frame_bw[ i ] < ehci->min_bw )
- ehci->min_bw = ehci->frame_bw[ i ];
- }
- pipe_content->start_uframe = j & 7;
- purb->int_start_frame = j >> 3;
- }
- }
- }
- else // full/low speed pipe
- {
- // split condition is considered
- if( pipe_content->trans_dir )
- {
- // an input interrupt, with handshake
- // 55 is 144 - 90 + 1, turnaround time is one byte not the worst case 90 bytes,
- // refer to ehci-1.0 table 4-5 p64
- ss_time = 231 * 25 / 12;
- // cs_time = ( 55 * 8 + ( LONG )( ( ( 19 + 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
- cs_time = ( 55 * 8 + ( LONG )( ( ( 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
- }
- else
- {
- // according to ehci-1.0 table 4-5 p64
- ss_time = ( 49 * 8 + ( LONG )( ( ( 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
- // 287 = 237 + 48( handshake ) + 8( turn around time )
- cs_time = 287 * 25 / 12;
- }
- ss_time >>=1, cs_time >>=1;
- if( release )
- {
- for( i = pipe_content->start_uframe + ( purb->int_start_frame << 3 ); i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] += ( USHORT )ss_time;
- ehci->frame_bw[ i + 2 ] += ( USHORT )cs_time;
- ehci->frame_bw[ i + 3 ] += ( USHORT )cs_time;
- if( ( i & 0x07 ) != 0x06 )
- ehci->frame_bw[ i + 4 ] += ( USHORT )cs_time;
- }
- goto LBL_OUT;
- }
- if( ss_time < ehci->min_bw && cs_time < ehci->min_bw )
- {
- pipe_content->start_uframe = 0;
- bw_avail = TRUE;
- for( i = 0; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] -= ( USHORT )ss_time;
- ehci->min_bw = min( ehci->frame_bw[ i ], ehci->min_bw );
- ehci->frame_bw[ i + 2 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 2 ], ehci->min_bw );
- ehci->frame_bw[ i + 3 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 3 ], ehci->min_bw );
- if( ( i & 0x07 ) != 0x06 )
- {
- ehci->frame_bw[ i + 4 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 4 ], ehci->min_bw );
- }
- }
- }
- else
- {
- for( j = 0; j < ( LONG )interval; j++ )
- {
- if( ( j & 0x7 )== 7 ) // start-split not allowed at this uframe
- continue;
-
- for( i = j; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- if( ehci->frame_bw[ i ] < ss_time )
- break;
- if( ehci->frame_bw[ i + 2 ] < cs_time )
- break;
- if( ehci->frame_bw[ i + 3 ] < cs_time )
- break;
- if( ( i & 0x7 ) != 6 )
- if( ehci->frame_bw[ i + 4 ] < cs_time )
- break;
- }
- if( i > ( LONG )( ehci->frame_count << 3 ) )
- {
- bw_avail = TRUE;
- break;
- }
- }
-
- pipe_content->start_uframe = j & 7;
- purb->int_start_frame = j >> 3;
-
- for( i = j; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ehci->frame_bw[ i ] -= ( USHORT )ss_time;
- ehci->min_bw = min( ehci->frame_bw[ i ], ehci->min_bw );
- ehci->frame_bw[ i + 2 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 2 ], ehci->min_bw );
- ehci->frame_bw[ i + 3 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 3 ], ehci->min_bw );
- if( ( i & 0x7 ) != 6 )
- {
- ehci->frame_bw[ i + 4 ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ i + 4 ], ehci->min_bw );
- }
- }
- }
- }
-
-LBL_OUT:
- if( !release )
- return bw_avail;
- else
- {
- ehci_find_min_bandwidth( ehci );
- return TRUE;
- }
+ PURB_HS_PIPE_CONTENT pipe_content;
+ LONG i, j;
+ ULONG interval, bus_time, ss_time, cs_time;
+ BOOL bw_avail;
+ ULONG max_packet_size;
+
+ if (ehci == NULL || purb == NULL)
+ return FALSE;
+
+ if (purb->pipe == 0)
+ return FALSE;
+
+ bw_avail = FALSE;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = REAL_INTERVAL;
+ if (pipe_content->speed_high == 0)
+ {
+ // translate to high speed uframe count
+ interval <<= 3;
+ }
+
+ if (interval > (ehci->frame_count << 3))
+ interval = (ehci->frame_count << 3);
+
+ max_packet_size = (1 << pipe_content->max_packet_size);
+ if (pipe_content->speed_high)
+ {
+ // this is a high speed endp
+
+ bus_time = usb_calc_bus_time(USB_SPEED_HIGH,
+ (pipe_content->trans_dir) << 7,
+ FALSE, min(purb->data_length, (LONG) max_packet_size));
+
+ // multiple transactions per uframe
+ if (purb->data_length > (LONG) max_packet_size)
+ {
+ bus_time *= (purb->data_length) / max_packet_size;
+ bus_time += usb_calc_bus_time(USB_SPEED_HIGH,
+ (pipe_content->trans_dir) << 7,
+ FALSE, purb->data_length % max_packet_size);
+ }
+ bus_time = (bus_time + 1) >> 1;
+
+ if (release)
+ {
+ for(i = pipe_content->start_uframe + (purb->int_start_frame << 3);
+ i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] += (USHORT) bus_time;
+ }
+ goto LBL_OUT;
+ }
+ if (bus_time < ehci->min_bw)
+ {
+ // start the poll from uframe zero of each frame
+ bw_avail = TRUE;
+ pipe_content->start_uframe = 0;
+ for(i = 0; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] -= (USHORT) bus_time;
+ if (ehci->frame_bw[i] < ehci->min_bw)
+ ehci->min_bw = ehci->frame_bw[i];
+ }
+ }
+ else // bother to find a pattern
+ {
+ for(j = 0; j < (LONG) interval; j++)
+ {
+ for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ if (ehci->frame_bw[i] < bus_time)
+ break;
+ }
+ if (i > (LONG) (ehci->frame_count << 3))
+ {
+ bw_avail = TRUE;
+ break;
+ }
+ }
+ if (bw_avail)
+ {
+ for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] -= (USHORT) bus_time;
+ if (ehci->frame_bw[i] < ehci->min_bw)
+ ehci->min_bw = ehci->frame_bw[i];
+ }
+ pipe_content->start_uframe = j & 7;
+ purb->int_start_frame = j >> 3;
+ }
+ }
+ }
+ else // full/low speed pipe
+ {
+ // split condition is considered
+ if (pipe_content->trans_dir)
+ {
+ // an input interrupt, with handshake
+ // 55 is 144 - 90 + 1, turnaround time is one byte not the worst case 90 bytes,
+ // refer to ehci-1.0 table 4-5 p64
+ ss_time = 231 * 25 / 12;
+ // cs_time = ( 55 * 8 + ( LONG )( ( ( 19 + 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
+ cs_time = (55 * 8 + (LONG) (((7 * 8 * purb->data_length) / 6))) * 25 / 12;
+ }
+ else
+ {
+ // according to ehci-1.0 table 4-5 p64
+ ss_time = (49 * 8 + (LONG) (((7 * 8 * purb->data_length) / 6))) * 25 / 12;
+ // 287 = 237 + 48( handshake ) + 8( turn around time )
+ cs_time = 287 * 25 / 12;
+ }
+ ss_time >>= 1, cs_time >>= 1;
+ if (release)
+ {
+ for(i = pipe_content->start_uframe + (purb->int_start_frame << 3);
+ i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] += (USHORT) ss_time;
+ ehci->frame_bw[i + 2] += (USHORT) cs_time;
+ ehci->frame_bw[i + 3] += (USHORT) cs_time;
+ if ((i & 0x07) != 0x06)
+ ehci->frame_bw[i + 4] += (USHORT) cs_time;
+ }
+ goto LBL_OUT;
+ }
+ if (ss_time < ehci->min_bw && cs_time < ehci->min_bw)
+ {
+ pipe_content->start_uframe = 0;
+ bw_avail = TRUE;
+ for(i = 0; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] -= (USHORT) ss_time;
+ ehci->min_bw = min(ehci->frame_bw[i], ehci->min_bw);
+ ehci->frame_bw[i + 2] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 2], ehci->min_bw);
+ ehci->frame_bw[i + 3] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 3], ehci->min_bw);
+ if ((i & 0x07) != 0x06)
+ {
+ ehci->frame_bw[i + 4] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 4], ehci->min_bw);
+ }
+ }
+ }
+ else
+ {
+ for(j = 0; j < (LONG) interval; j++)
+ {
+ if ((j & 0x7) == 7) // start-split not allowed at this uframe
+ continue;
+
+ for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ if (ehci->frame_bw[i] < ss_time)
+ break;
+ if (ehci->frame_bw[i + 2] < cs_time)
+ break;
+ if (ehci->frame_bw[i + 3] < cs_time)
+ break;
+ if ((i & 0x7) != 6)
+ if (ehci->frame_bw[i + 4] < cs_time)
+ break;
+ }
+ if (i > (LONG) (ehci->frame_count << 3))
+ {
+ bw_avail = TRUE;
+ break;
+ }
+ }
+
+ pipe_content->start_uframe = j & 7;
+ purb->int_start_frame = j >> 3;
+
+ for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ehci->frame_bw[i] -= (USHORT) ss_time;
+ ehci->min_bw = min(ehci->frame_bw[i], ehci->min_bw);
+ ehci->frame_bw[i + 2] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 2], ehci->min_bw);
+ ehci->frame_bw[i + 3] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 3], ehci->min_bw);
+ if ((i & 0x7) != 6)
+ {
+ ehci->frame_bw[i + 4] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[i + 4], ehci->min_bw);
+ }
+ }
+ }
+ }
+
+ LBL_OUT:
+ if (!release)
+ return bw_avail;
+ else
+ {
+ ehci_find_min_bandwidth(ehci);
+ return TRUE;
+ }
}
LONG
-ehci_get_cache_policy(
-PEHCI_DEV ehci
-)
+ehci_get_cache_policy(PEHCI_DEV ehci)
{
- PEHCI_HCC_CONTENT hcc_content;
+ PEHCI_HCC_CONTENT hcc_content;
- hcc_content = ( PEHCI_HCC_CONTENT ) &ehci->ehci_caps;
- if( hcc_content->iso_sched_threshold >= 8 )
- return 16;
- if( hcc_content->iso_sched_threshold == 0 )
- return 2;
+ hcc_content = (PEHCI_HCC_CONTENT) & ehci->ehci_caps;
+ if (hcc_content->iso_sched_threshold >= 8)
+ return 16;
+ if (hcc_content->iso_sched_threshold == 0)
+ return 2;
return hcc_content->iso_sched_threshold + 2;
}
#define iso_uframes_data_load( dir, data_load, uf_cnt )
BOOL
-ehci_claim_bw_for_iso(
-PEHCI_DEV ehci,
-PURB purb,
-BOOL release
-)
+ehci_claim_bw_for_iso(PEHCI_DEV ehci, PURB purb, BOOL release)
{
- PURB_HS_PIPE_CONTENT pipe_content;
- LONG i, j, k;
- ULONG interval, bus_time, ss_time, cs_time, remainder;
- BOOL bw_avail;
- ULONG cur_uframe, start_uframe, max_time, max_packet_size;
- PBYTE base;
- if( ehci == NULL || purb == NULL )
- return FALSE;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- base = ehci->port_base;
- cur_uframe = EHCI_READ_PORT_ULONG( ( PULONG )( base + EHCI_FRINDEX ) ) + 1;
- bw_avail = FALSE;
-
- max_packet_size = purb->params[ 0 ]; //( 1 << pipe_content->max_packet_size );
-
- if( pipe_content->speed_high )
- {
- interval = REAL_INTERVAL;
- if( purb->iso_frame_count == 0 || purb->iso_frame_count + 2 * 8 > ( LONG )( ehci->frame_count << 3 ) )
- return FALSE;
-
- for( i = 0, max_time = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- bus_time = usb_calc_bus_time(
- USB_SPEED_HIGH,
- ( pipe_content->trans_dir ) << 7,
- TRUE,
- min( purb->iso_packet_desc[ i ].length, ( LONG )max_packet_size )
- );
- // NOTE: we did not use endp_mult_count here, because the comparison is enough
- // to calculate the bandwidth
- if( purb->iso_packet_desc[ i ].length > ( LONG )max_packet_size )
- {
- // multiple transactions per uframe
- bus_time *= purb->iso_packet_desc[ i ].length / max_packet_size;
- bus_time += usb_calc_bus_time(
- USB_SPEED_HIGH,
- ( pipe_content->trans_dir ) << 7,
- TRUE,
- purb->iso_packet_desc[ i ].length % max_packet_size
- );
- }
- bus_time = ( bus_time + 1 ) >> 1;
- max_time = max( bus_time, max_time );
- purb->iso_packet_desc[ i ].bus_time = bus_time;
- }
-
- if( release )
- {
- // it is a release operation
- for( i = purb->iso_start_frame, k = 0; k < ( LONG )purb->iso_frame_count; k++, i = ( i + interval ) % ( ehci->frame_count << 3 ) )
- {
- ehci->frame_bw[ i ] += ( USHORT )purb->iso_packet_desc[ k ].bus_time;
- }
- ehci_find_min_bandwidth( ehci );
- return TRUE;
- }
-
- if( max_time < ehci->min_bw )
- {
- start_uframe = cur_uframe + ehci_get_cache_policy( ehci ); // avoid cache
- for( i = start_uframe, j = 0; j < ( LONG )purb->iso_frame_count; i = ( i + interval ) % ( ehci->frame_count << 3 ), j++ )
- {
- ehci->frame_bw[ i ] -= ( USHORT )purb->iso_packet_desc[ j ].bus_time;
- ehci->min_bw = min( ehci->frame_bw[ j ], ehci->min_bw );
- }
- purb->iso_start_frame = start_uframe;
- return TRUE;
- }
- else // max_time >= ehci->min_bw
- {
- for( j = 0; j < ( LONG )interval; j++ )
- {
- start_uframe = cur_uframe + ehci_get_cache_policy( ehci ) + j;
- for( i = start_uframe, k = 0; k < ( LONG )purb->iso_frame_count; k++, i = ( i + interval ) % ( ehci->frame_count << 3 ) )
- {
- if( ehci->frame_bw[ i ] < ( USHORT )purb->iso_packet_desc[ k ].bus_time )
- {
- break;
- }
- }
-
- if( k < ( LONG )purb->iso_frame_count )
- continue;
- bw_avail = TRUE;
- break;
- }
- if( bw_avail )
- {
- // allocate the bandwidth
- for( i = start_uframe, k = 0; k < ( LONG )purb->iso_frame_count; k++, i = ( i + interval ) % ( ehci->frame_count << 3 ) )
- {
- ehci->frame_bw[ i ] -= ( USHORT )purb->iso_packet_desc[ k ].bus_time;
- ehci->min_bw = min( ehci->min_bw, ehci->frame_bw[ i ] );
- }
- purb->iso_start_frame = start_uframe;
- }
- }
- }
- else // not high speed endpoint
- {
- // split transfer
- if( purb->iso_frame_count == 0 || purb->iso_frame_count + 2 > ( LONG )ehci->frame_count )
- return FALSE;
-
- if( max_packet_size > 1023 )
- return FALSE;
-
- remainder = 0;
-
- //
- // calculate for each frame
- // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
- // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
- // bit-stuffing is for high speed bus transfer
- //
-
- if( pipe_content->trans_dir )
- {
- // an input transfer, no handshake
- ss_time = 231 * 25 / 12;
- // cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
- cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
- }
- else
- {
- // an output transfer according to ehci-1.0 table 4-5 p64
- // ss_time = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
- ss_time = ( 49 * 8 + ( LONG )( ( ( 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
- cs_time = 0;
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- // remainder = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12;
- remainder = ( 49 * 8 + ( LONG )( ( ( 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12;
- remainder >>= 1;
- purb->iso_packet_desc[ i ].params.bus_time = ( USHORT )remainder;
- }
- }
-
- ss_time >>= 1;
- cs_time >>= 1;
- cur_uframe = ( cur_uframe + 7 ) & ( ~0x07 );
-
- j = ehci->frame_count << 3;
- if( release )
- {
- if( pipe_content->trans_dir )
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- ehci->frame_bw[ purb->iso_packet_desc[ i ].params.start_uframe ] += ( USHORT )ss_time;
- for( k = 0; k < ( purb->iso_packet_desc[ i ].length + 187 ) / 188; k++ )
- {
- ehci->frame_bw[ ( cur_uframe + 0x12 + ( i << 3 ) + k ) % j ] += ( USHORT )cs_time;
- }
-
- // two extra complete-split
- ehci->frame_bw[ ( cur_uframe + 0x12 + ( i << 3 ) + k ) % j ] += ( USHORT )cs_time;
- ehci->frame_bw[ ( cur_uframe + 0x13 + ( i << 3 ) + k ) % j ] += ( USHORT )cs_time;
- }
- }
- else
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- for( k = 0; k < ( purb->iso_packet_desc[ i ].length + 187 ) / 188; k++ )
- {
- ehci->frame_bw[ ( cur_uframe + 0x10 + ( i << 3 ) + k ) % j ] += ( USHORT )ss_time;
- }
- }
- }
- ehci_find_min_bandwidth( ehci );
- }
-
- // search for available bw
- if( ss_time < ehci->min_bw && cs_time < ehci->min_bw )
- {
- if( pipe_content->trans_dir )
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- ehci->frame_bw[ ( cur_uframe + 0x10 + ( i << 3 ) ) % j ] -= ( USHORT )ss_time;
- ehci->min_bw = min( ehci->frame_bw[ ( cur_uframe + 0x10 + ( i << 3 ) ) % j ], ehci->min_bw );
-
- for( k = 0; k < ( purb->iso_packet_desc[ i ].length + 187 ) / 188; k++ )
- {
- ehci->frame_bw[ ( cur_uframe + 0x12 + ( i << 3 ) + k ) % j ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ ( cur_uframe + 0x12 + ( i << 3 ) + k ) %j ], ehci->min_bw );
- }
-
- // two extra complete-split
- ehci->frame_bw[ ( cur_uframe + 0x12 + ( i << 3 ) + k ) % j ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ cur_uframe + 0x12 + ( i << 3 ) + k ], ehci->min_bw );
- ehci->frame_bw[ ( cur_uframe + 0x13 + ( i << 3 ) + k ) % j ] -= ( USHORT )cs_time;
- ehci->min_bw = min( ehci->frame_bw[ cur_uframe + 0x13 + ( i << 3 ) + k ], ehci->min_bw );
- }
- }
- else // iso output
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- for( k = 0; k < ( purb->iso_packet_desc[ i ].length + 187 ) / 188; k++ )
- {
- ehci->frame_bw[ ( cur_uframe + 0x10 + ( i << 3 ) + k ) % j ] -= ( USHORT )ss_time;
- ehci->min_bw = min( ehci->frame_bw[ ( cur_uframe + 0x11 + ( i << 3 ) + k ) %j ], ehci->min_bw );
- }
- }
- }
- purb->iso_start_frame = 0;
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- if( i == 0 )
- purb->iso_packet_desc[ i ].params.start_uframe = ( USHORT )( cur_uframe + 0x10 );
- else
- purb->iso_packet_desc[ i ].params.start_uframe = purb->iso_packet_desc[ i - 1 ].params.start_uframe + 0x8;
- }
- bw_avail = TRUE;
- }
- else // take the pain to find one
- {
- BOOL large;
- long temp, base;
-
- for( j = ( cur_uframe >> 3 ) + 2; j != ( LONG )( cur_uframe >> 3 ); j = ( j + 1 ) % ehci->frame_count )
- {
- temp = 0;
-
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- large = purb->iso_packet_desc[ i ].length > 579;
- base = ( purb->iso_packet_desc[ i ].length + 187 ) / 188;
-
- if( base > 6 )
- return FALSE;
-
- if( pipe_content->trans_dir )
- {
- // input split iso, for those large than 579, schedule it at the uframe boundary
- for( temp = 0; temp < ( large == FALSE ) ? ( 8 - base - 1 ) : 1; temp++ )
- {
- k = ( ( ( j + i ) << 3 ) + temp ) % ( ehci->frame_count << 3 );
- if( ehci->frame_bw[ k ] > ss_time )
- continue;
-
- k = base;
- while( k != 0 )
- {
- if( ehci->frame_bw[ ( ( ( j + i ) << 3 ) + 1 + temp + k ) % ( ehci->frame_count << 3 ) ] < cs_time )
- break;
- k--;
- }
- if( k > 0 ) // not available
- continue;
-
- // the first following extra cs
- k = ( ( ( j + i ) << 3 ) + 2 + temp + base ) % ( ehci->frame_count << 3 );
- if( ehci->frame_bw[ k ] < cs_time )
- continue;
-
- if( base < 6 )
- {
- // very large one does not have this second extra cs
- if( ehci->frame_bw[ ( k + 1 ) % ( ehci->frame_count << 3 ) ] < cs_time )
- continue;
- }
- }
-
- if( temp == 8 - 1 - base ) // no bandwidth for ss
- break;
- }
- else // output
- {
- // note: 8 - 1 - base has different meaning from the above
- // it is to avoid the ss on H-Frame 7, but the above one is
- // the latency of the classic bus.
- for( temp = 0; temp < 8 - 1 - base; temp++ )
- {
- if( ehci->frame_bw[ ( ( j + i ) << 3 ) % ( ehci->frame_count << 3 ) + temp ] > ss_time )
- continue;
-
- for( k = temp; k < temp + base; k++ )
- {
- if( ehci->frame_bw[ ( ( j + i ) << 3 ) % ( ehci->frame_count << 3 ) + k ] < ss_time )
- break;
- }
- }
-
- if( temp == 8 - 1 - base )
- break;
- }
-
- purb->iso_packet_desc[ i ].params.start_uframe = ( USHORT )( ( ( ( j + i ) << 3 ) + temp ) % ( ehci->frame_count << 3 ) );
- // next frame
- }
- if( i < ( LONG )purb->iso_frame_count )
- {
- // skip to the next section
- j = ( j + i ) % ( ehci->frame_count << 3 );
- continue;
- }
- bw_avail = TRUE;
- break;
- }
- // FIXME: Should we claim bw for the last complete split sitd? this is not done
- // yet.
- if( bw_avail )
- {
- if( pipe_content->trans_dir )
- {
- // input iso
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- j = purb->iso_packet_desc[ i ].length;
- temp = ( purb->iso_packet_desc[ i ].params.start_uframe ) % ( ehci->frame_count << 3 );
- ehci->frame_bw[ temp ] -= ( USHORT )ss_time;
- for( k = 0; k < ( j + 187 ) / 188; j++ )
- {
- ehci->frame_bw[ temp + 2 + k ] -= ( USHORT )cs_time;
- }
- ehci->frame_bw[ temp + 2 + k ] -= ( USHORT )cs_time;
- if( ( j + 187 ) / 188 < 6 ) //ehci restriction
- {
- ehci->frame_bw[ temp + 3 + k ] -= ( USHORT )cs_time;
- }
- }
- }
- else //output iso
- {
- for( i = 0; i < ( LONG )purb->iso_frame_count; i++ )
- {
- j = purb->iso_packet_desc[ i ].length;
- temp =( purb->iso_packet_desc[ i ].params.start_uframe ) % ( ehci->frame_count << 3 );
- for( k = 0; k < j / 188; j++ )
- {
- ehci->frame_bw[ temp + k ] -= ( USHORT )ss_time;
- }
- if( j % 188 )
- ehci->frame_bw[ temp + k ] -= purb->iso_packet_desc[ i ].params.bus_time;
- }
- }
- }
- }
- }
- return bw_avail;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ LONG i, j, k;
+ ULONG interval, bus_time, ss_time, cs_time, remainder;
+ BOOL bw_avail;
+ ULONG cur_uframe, start_uframe, max_time, max_packet_size;
+ PBYTE base;
+ if (ehci == NULL || purb == NULL)
+ return FALSE;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ base = ehci->port_base;
+ cur_uframe = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_FRINDEX)) + 1;
+ bw_avail = FALSE;
+
+ max_packet_size = purb->params[0]; //( 1 << pipe_content->max_packet_size );
+
+ if (pipe_content->speed_high)
+ {
+ interval = REAL_INTERVAL;
+ if (purb->iso_frame_count == 0 || purb->iso_frame_count + 2 * 8 > (LONG) (ehci->frame_count << 3))
+ return FALSE;
+
+ for(i = 0, max_time = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ bus_time = usb_calc_bus_time(USB_SPEED_HIGH,
+ (pipe_content->trans_dir) << 7,
+ TRUE, min(purb->iso_packet_desc[i].length, (LONG) max_packet_size));
+ // NOTE: we did not use endp_mult_count here, because the comparison is enough
+ // to calculate the bandwidth
+ if (purb->iso_packet_desc[i].length > (LONG) max_packet_size)
+ {
+ // multiple transactions per uframe
+ bus_time *= purb->iso_packet_desc[i].length / max_packet_size;
+ bus_time += usb_calc_bus_time(USB_SPEED_HIGH,
+ (pipe_content->trans_dir) << 7,
+ TRUE, purb->iso_packet_desc[i].length % max_packet_size);
+ }
+ bus_time = (bus_time + 1) >> 1;
+ max_time = max(bus_time, max_time);
+ purb->iso_packet_desc[i].bus_time = bus_time;
+ }
+
+ if (release)
+ {
+ // it is a release operation
+ for(i = purb->iso_start_frame, k = 0; k < (LONG) purb->iso_frame_count;
+ k++, i = (i + interval) % (ehci->frame_count << 3))
+ {
+ ehci->frame_bw[i] += (USHORT) purb->iso_packet_desc[k].bus_time;
+ }
+ ehci_find_min_bandwidth(ehci);
+ return TRUE;
+ }
+
+ if (max_time < ehci->min_bw)
+ {
+ start_uframe = cur_uframe + ehci_get_cache_policy(ehci); // avoid cache
+ for(i = start_uframe, j = 0; j < (LONG) purb->iso_frame_count;
+ i = (i + interval) % (ehci->frame_count << 3), j++)
+ {
+ ehci->frame_bw[i] -= (USHORT) purb->iso_packet_desc[j].bus_time;
+ ehci->min_bw = min(ehci->frame_bw[j], ehci->min_bw);
+ }
+ purb->iso_start_frame = start_uframe;
+ return TRUE;
+ }
+ else // max_time >= ehci->min_bw
+ {
+ for(j = 0; j < (LONG) interval; j++)
+ {
+ start_uframe = cur_uframe + ehci_get_cache_policy(ehci) + j;
+ for(i = start_uframe, k = 0; k < (LONG) purb->iso_frame_count;
+ k++, i = (i + interval) % (ehci->frame_count << 3))
+ {
+ if (ehci->frame_bw[i] < (USHORT) purb->iso_packet_desc[k].bus_time)
+ {
+ break;
+ }
+ }
+
+ if (k < (LONG) purb->iso_frame_count)
+ continue;
+ bw_avail = TRUE;
+ break;
+ }
+ if (bw_avail)
+ {
+ // allocate the bandwidth
+ for(i = start_uframe, k = 0; k < (LONG) purb->iso_frame_count;
+ k++, i = (i + interval) % (ehci->frame_count << 3))
+ {
+ ehci->frame_bw[i] -= (USHORT) purb->iso_packet_desc[k].bus_time;
+ ehci->min_bw = min(ehci->min_bw, ehci->frame_bw[i]);
+ }
+ purb->iso_start_frame = start_uframe;
+ }
+ }
+ }
+ else // not high speed endpoint
+ {
+ // split transfer
+ if (purb->iso_frame_count == 0 || purb->iso_frame_count + 2 > (LONG) ehci->frame_count)
+ return FALSE;
+
+ if (max_packet_size > 1023)
+ return FALSE;
+
+ remainder = 0;
+
+ //
+ // calculate for each frame
+ // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
+ // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
+ // bit-stuffing is for high speed bus transfer
+ //
+
+ if (pipe_content->trans_dir)
+ {
+ // an input transfer, no handshake
+ ss_time = 231 * 25 / 12;
+ // cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
+ cs_time = (231 + 8 + 67 + (LONG) (((7 * 8 * 188) / 6))) * 25 / 12;
+ }
+ else
+ {
+ // an output transfer according to ehci-1.0 table 4-5 p64
+ // ss_time = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
+ ss_time = (49 * 8 + (LONG) (((7 * 8 * 188) / 6))) * 25 / 12;
+ cs_time = 0;
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ // remainder = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12;
+ remainder =
+ (49 * 8 + (LONG) (((7 * 8 * (purb->iso_packet_desc[i].length % 188)) / 6))) * 25 / 12;
+ remainder >>= 1;
+ purb->iso_packet_desc[i].params.bus_time = (USHORT) remainder;
+ }
+ }
+
+ ss_time >>= 1;
+ cs_time >>= 1;
+ cur_uframe = (cur_uframe + 7) & (~0x07);
+
+ j = ehci->frame_count << 3;
+ if (release)
+ {
+ if (pipe_content->trans_dir)
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ ehci->frame_bw[purb->iso_packet_desc[i].params.start_uframe] += (USHORT) ss_time;
+ for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++)
+ {
+ ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] += (USHORT) cs_time;
+ }
+
+ // two extra complete-split
+ ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] += (USHORT) cs_time;
+ ehci->frame_bw[(cur_uframe + 0x13 + (i << 3) + k) % j] += (USHORT) cs_time;
+ }
+ }
+ else
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++)
+ {
+ ehci->frame_bw[(cur_uframe + 0x10 + (i << 3) + k) % j] += (USHORT) ss_time;
+ }
+ }
+ }
+ ehci_find_min_bandwidth(ehci);
+ }
+
+ // search for available bw
+ if (ss_time < ehci->min_bw && cs_time < ehci->min_bw)
+ {
+ if (pipe_content->trans_dir)
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ ehci->frame_bw[(cur_uframe + 0x10 + (i << 3)) % j] -= (USHORT) ss_time;
+ ehci->min_bw = min(ehci->frame_bw[(cur_uframe + 0x10 + (i << 3)) % j], ehci->min_bw);
+
+ for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++)
+ {
+ ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] -= (USHORT) cs_time;
+ ehci->min_bw =
+ min(ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j], ehci->min_bw);
+ }
+
+ // two extra complete-split
+ ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[cur_uframe + 0x12 + (i << 3) + k], ehci->min_bw);
+ ehci->frame_bw[(cur_uframe + 0x13 + (i << 3) + k) % j] -= (USHORT) cs_time;
+ ehci->min_bw = min(ehci->frame_bw[cur_uframe + 0x13 + (i << 3) + k], ehci->min_bw);
+ }
+ }
+ else // iso output
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++)
+ {
+ ehci->frame_bw[(cur_uframe + 0x10 + (i << 3) + k) % j] -= (USHORT) ss_time;
+ ehci->min_bw =
+ min(ehci->frame_bw[(cur_uframe + 0x11 + (i << 3) + k) % j], ehci->min_bw);
+ }
+ }
+ }
+ purb->iso_start_frame = 0;
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ if (i == 0)
+ purb->iso_packet_desc[i].params.start_uframe = (USHORT) (cur_uframe + 0x10);
+ else
+ purb->iso_packet_desc[i].params.start_uframe =
+ purb->iso_packet_desc[i - 1].params.start_uframe + 0x8;
+ }
+ bw_avail = TRUE;
+ }
+ else // take the pain to find one
+ {
+ BOOL large;
+ long temp, base;
+
+ for(j = (cur_uframe >> 3) + 2; j != (LONG) (cur_uframe >> 3); j = (j + 1) % ehci->frame_count)
+ {
+ temp = 0;
+
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ large = purb->iso_packet_desc[i].length > 579;
+ base = (purb->iso_packet_desc[i].length + 187) / 188;
+
+ if (base > 6)
+ return FALSE;
+
+ if (pipe_content->trans_dir)
+ {
+ // input split iso, for those large than 579, schedule it at the uframe boundary
+ for(temp = 0; temp < (large == FALSE) ? (8 - base - 1) : 1; temp++)
+ {
+ k = (((j + i) << 3) + temp) % (ehci->frame_count << 3);
+ if (ehci->frame_bw[k] > ss_time)
+ continue;
+
+ k = base;
+ while (k != 0)
+ {
+ if (ehci->
+ frame_bw[(((j + i) << 3) + 1 + temp + k) % (ehci->frame_count << 3)] <
+ cs_time)
+ break;
+ k--;
+ }
+ if (k > 0) // not available
+ continue;
+
+ // the first following extra cs
+ k = (((j + i) << 3) + 2 + temp + base) % (ehci->frame_count << 3);
+ if (ehci->frame_bw[k] < cs_time)
+ continue;
+
+ if (base < 6)
+ {
+ // very large one does not have this second extra cs
+ if (ehci->frame_bw[(k + 1) % (ehci->frame_count << 3)] < cs_time)
+ continue;
+ }
+ }
+
+ if (temp == 8 - 1 - base) // no bandwidth for ss
+ break;
+ }
+ else // output
+ {
+ // note: 8 - 1 - base has different meaning from the above
+ // it is to avoid the ss on H-Frame 7, but the above one is
+ // the latency of the classic bus.
+ for(temp = 0; temp < 8 - 1 - base; temp++)
+ {
+ if (ehci->frame_bw[((j + i) << 3) % (ehci->frame_count << 3) + temp] > ss_time)
+ continue;
+
+ for(k = temp; k < temp + base; k++)
+ {
+ if (ehci->frame_bw[((j + i) << 3) % (ehci->frame_count << 3) + k] < ss_time)
+ break;
+ }
+ }
+
+ if (temp == 8 - 1 - base)
+ break;
+ }
+
+ purb->iso_packet_desc[i].params.start_uframe =
+ (USHORT) ((((j + i) << 3) + temp) % (ehci->frame_count << 3));
+ // next frame
+ }
+ if (i < (LONG) purb->iso_frame_count)
+ {
+ // skip to the next section
+ j = (j + i) % (ehci->frame_count << 3);
+ continue;
+ }
+ bw_avail = TRUE;
+ break;
+ }
+ // FIXME: Should we claim bw for the last complete split sitd? this is not done
+ // yet.
+ if (bw_avail)
+ {
+ if (pipe_content->trans_dir)
+ {
+ // input iso
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ j = purb->iso_packet_desc[i].length;
+ temp = (purb->iso_packet_desc[i].params.start_uframe) % (ehci->frame_count << 3);
+ ehci->frame_bw[temp] -= (USHORT) ss_time;
+ for(k = 0; k < (j + 187) / 188; j++)
+ {
+ ehci->frame_bw[temp + 2 + k] -= (USHORT) cs_time;
+ }
+ ehci->frame_bw[temp + 2 + k] -= (USHORT) cs_time;
+ if ((j + 187) / 188 < 6) //ehci restriction
+ {
+ ehci->frame_bw[temp + 3 + k] -= (USHORT) cs_time;
+ }
+ }
+ }
+ else //output iso
+ {
+ for(i = 0; i < (LONG) purb->iso_frame_count; i++)
+ {
+ j = purb->iso_packet_desc[i].length;
+ temp = (purb->iso_packet_desc[i].params.start_uframe) % (ehci->frame_count << 3);
+ for(k = 0; k < j / 188; j++)
+ {
+ ehci->frame_bw[temp + k] -= (USHORT) ss_time;
+ }
+ if (j % 188)
+ ehci->frame_bw[temp + k] -= purb->iso_packet_desc[i].params.bus_time;
+ }
+ }
+ }
+ }
+ }
+ return bw_avail;
}
BOOL
-ehci_claim_bandwidth(
-PEHCI_DEV ehci,
-PURB purb,
-BOOL claim_bw )//true to claim band-width, false to free band-width
+ehci_claim_bandwidth(PEHCI_DEV ehci, PURB purb, BOOL claim_bw) //true to claim band-width, false to free band-width
// should have pending_endp_list_lock acquired, and purb->pipe prepared
{
- PURB_HS_PIPE_CONTENT pipe_content;
- BOOL ret;
-
- if( ehci == NULL || purb == NULL )
- return FALSE;
-
- ret = FALSE;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC )
- {
- ret = ehci_claim_bw_for_iso( ehci, purb, claim_bw ? FALSE : TRUE );
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_INT )
- {
- ret = ehci_claim_bw_for_int( ehci, purb, claim_bw ? FALSE : TRUE );
- }
- else
- TRAP();
- return ret;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ BOOL ret;
+
+ if (ehci == NULL || purb == NULL)
+ return FALSE;
+
+ ret = FALSE;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC)
+ {
+ ret = ehci_claim_bw_for_iso(ehci, purb, claim_bw ? FALSE : TRUE);
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT)
+ {
+ ret = ehci_claim_bw_for_int(ehci, purb, claim_bw ? FALSE : TRUE);
+ }
+ else
+ TRAP();
+ return ret;
}
BOOL
-ehci_can_remove(
-PURB purb,
-BOOL door_bell_rings,
-ULONG cur_frame
-)
+ehci_can_remove(PURB purb, BOOL door_bell_rings, ULONG cur_frame)
// test if the purb can be removed from the schedule, by current frame index and
// purb states
{
- PURB_HS_PIPE_CONTENT pipe_content;
- ULONG interval;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = REAL_INTERVAL;
-
- switch( purb->flags & URB_FLAG_STATE_MASK )
- {
- case URB_FLAG_STATE_PENDING:
- {
- // not impossible
- TRAP();
- break;
- }
- case URB_FLAG_STATE_IN_PROCESS:
- {
- break;
- }
- case URB_FLAG_STATE_DOORBELL:
- {
- if( ( pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL ) && \
- door_bell_rings == TRUE )
- {
- return TRUE;
- }
- else if( ( pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL ) )
- {
- break;
- }
- else
- {
- TRAP();
- break;
- }
- }
- case URB_FLAG_STATE_WAIT_FRAME:
- {
- // need more processing
- if( ( purb->flags & URB_FLAG_FORCE_CANCEL ) == 0 )
- {
- TRAP();
- break;
- }
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_INT )
- {
- return door_bell_rings;
- }
- else // isochronous can not be canceled
- {
- TRAP();
- break;
- }
- }
- }
- return FALSE;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ ULONG interval;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = REAL_INTERVAL;
+
+ switch (purb->flags & URB_FLAG_STATE_MASK)
+ {
+ case URB_FLAG_STATE_PENDING:
+ {
+ // not impossible
+ TRAP();
+ break;
+ }
+ case URB_FLAG_STATE_IN_PROCESS:
+ {
+ break;
+ }
+ case URB_FLAG_STATE_DOORBELL:
+ {
+ if ((pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL) && door_bell_rings == TRUE)
+ {
+ return TRUE;
+ }
+ else if ((pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL))
+ {
+ break;
+ }
+ else
+ {
+ TRAP();
+ break;
+ }
+ }
+ case URB_FLAG_STATE_WAIT_FRAME:
+ {
+ // need more processing
+ if ((purb->flags & URB_FLAG_FORCE_CANCEL) == 0)
+ {
+ TRAP();
+ break;
+ }
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT)
+ {
+ return door_bell_rings;
+ }
+ else // isochronous can not be canceled
+ {
+ TRAP();
+ break;
+ }
+ }
+ }
+ return FALSE;
}
-NTSTATUS
-ehci_remove_urb_from_schedule(
-PEHCI_DEV ehci,
-PURB purb
-);
+NTSTATUS ehci_remove_urb_from_schedule(PEHCI_DEV ehci, PURB purb);
static VOID
-ehci_deactivate_urb(
-PURB purb
-)
+ehci_deactivate_urb(PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content;
- PLIST_ENTRY pthis, pnext;
- PEHCI_QH_CONTENT pqh_content;
- PEHCI_QTD_CONTENT pqtd_content;
-
- if( purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- switch( pipe_content->trans_type )
- {
- case USB_ENDPOINT_XFER_CONTROL:
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- {
- ListFirst( &purb->trasac_list, pthis );
- pqh_content = ( PEHCI_QH_CONTENT )qh_from_list_entry( pthis );
- ListNext( &purb->trasac_list, pthis, pnext );
- do
- {
- pqtd_content = ( PEHCI_QTD_CONTENT )qtd_from_list_entry( pthis );
- if( pqtd_content->status & QTD_STS_ACTIVE )
- {
- pqtd_content->status &= ~QTD_STS_ACTIVE;
- }
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
-
- }while( pthis );
- break;
- }
- case USB_ENDPOINT_XFER_ISOC:
- {
- // fall through
- }
- default:
- TRAP();
- }
- return;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PLIST_ENTRY pthis, pnext;
+ PEHCI_QH_CONTENT pqh_content;
+ PEHCI_QTD_CONTENT pqtd_content;
+
+ if (purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ switch (pipe_content->trans_type)
+ {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ {
+ ListFirst(&purb->trasac_list, pthis);
+ pqh_content = (PEHCI_QH_CONTENT) qh_from_list_entry(pthis);
+ ListNext(&purb->trasac_list, pthis, pnext);
+ do
+ {
+ pqtd_content = (PEHCI_QTD_CONTENT) qtd_from_list_entry(pthis);
+ if (pqtd_content->status & QTD_STS_ACTIVE)
+ {
+ pqtd_content->status &= ~QTD_STS_ACTIVE;
+ }
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+
+ }
+ while (pthis);
+ break;
+ }
+ case USB_ENDPOINT_XFER_ISOC:
+ {
+ // fall through
+ }
+ default:
+ TRAP();
+ }
+ return;
}
static VOID
-ehci_insert_bulk_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_insert_bulk_schedule(PEHCI_DEV ehci, PURB purb)
// list head is only a handle, the qh and qtd are following it.
{
- PLIST_ENTRY list_head;
- PEHCI_QH pqh, pqhprev, pqhnext;
- PEHCI_QTD ptd;
- PLIST_ENTRY pthis, pprev, pnext;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- list_head = &purb->trasac_list;
- ListFirst( list_head, pthis );
- if( pthis == NULL )
- return;
-
- if( elem_type_list_entry( pthis ) != INIT_LIST_FLAG_QH )
- return;
-
- pqh = qh_from_list_entry( pthis );
- // the last qh
- ListFirstPrev( &ehci->async_list_cpu, pprev );
- pqhprev = qh_from_schedule( pprev );
-
- // the first qh
- ListFirst( &ehci->async_list_cpu, pnext );
- pqhnext = qh_from_schedule( pnext );
-
- if( pprev == &ehci->async_list_cpu )
- {
- // always a qh in async list
- TRAP();
- return;
- }
- pqh->hw_next = pqhnext->phys_addr;
- InsertTailList( &ehci->async_list_cpu, &pqh->elem_head_link->sched_link );
- pqhprev->hw_next = pqh->phys_addr;
- return;
+ PLIST_ENTRY list_head;
+ PEHCI_QH pqh, pqhprev, pqhnext;
+ PEHCI_QTD ptd;
+ PLIST_ENTRY pthis, pprev, pnext;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ list_head = &purb->trasac_list;
+ ListFirst(list_head, pthis);
+ if (pthis == NULL)
+ return;
+
+ if (elem_type_list_entry(pthis) != INIT_LIST_FLAG_QH)
+ return;
+
+ pqh = qh_from_list_entry(pthis);
+ // the last qh
+ ListFirstPrev(&ehci->async_list_cpu, pprev);
+ pqhprev = qh_from_schedule(pprev);
+
+ // the first qh
+ ListFirst(&ehci->async_list_cpu, pnext);
+ pqhnext = qh_from_schedule(pnext);
+
+ if (pprev == &ehci->async_list_cpu)
+ {
+ // always a qh in async list
+ TRAP();
+ return;
+ }
+ pqh->hw_next = pqhnext->phys_addr;
+ InsertTailList(&ehci->async_list_cpu, &pqh->elem_head_link->sched_link);
+ pqhprev->hw_next = pqh->phys_addr;
+ return;
}
static VOID
-ehci_remove_bulk_from_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_remove_bulk_from_schedule(PEHCI_DEV ehci, PURB purb)
// executed in isr, and have frame_list_lock acquired, so
// never try to acquire any spin-lock
// remove the bulk purb from schedule, and mark it not in
// the schedule
{
- PLIST_ENTRY list_head;
- PEHCI_QH pqh, pqhprev, pqhnext;
- PEHCI_QTD ptd;
- PEHCI_QH_CONTENT pqhc;
- PLIST_ENTRY pthis, pprev, pnext;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- list_head = &purb->trasac_list;
- ListFirst( list_head, pthis );
- if( pthis == NULL )
- {
- TRAP();
- return;
- }
- pqh = qh_from_list_entry( pthis );
- pqhc = ( PEHCI_QH_CONTENT) pqh;
-
- if( pqhc->is_async_head )
- TRAP();
-
- ListFirst( &pqh->elem_head_link->sched_link, pnext );
- ListFirstPrev( &pqh->elem_head_link->sched_link, pprev );
-
- if( pprev == &ehci->async_list_cpu )
- {
- // we will at least have a qh with H-bit 1 in the async-list
- TRAP();
- }
- else if( pnext == &ehci->async_list_cpu )
- {
- // remove the last one
- pqhprev = qh_from_schedule( pprev );
- ListFirst( &ehci->async_list_cpu, pnext );
- pqhnext = qh_from_schedule( pnext );
- pqhprev->hw_next = pqhnext->phys_addr;
- }
- else
- {
- pqhprev = qh_from_schedule( pprev );
- pqhnext = qh_from_schedule( pnext );
- pqhprev->hw_next = pqhnext->phys_addr;
- }
- RemoveEntryList( &pqh->elem_head_link->sched_link );
- return;
+ PLIST_ENTRY list_head;
+ PEHCI_QH pqh, pqhprev, pqhnext;
+ PEHCI_QTD ptd;
+ PEHCI_QH_CONTENT pqhc;
+ PLIST_ENTRY pthis, pprev, pnext;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ list_head = &purb->trasac_list;
+ ListFirst(list_head, pthis);
+ if (pthis == NULL)
+ {
+ TRAP();
+ return;
+ }
+ pqh = qh_from_list_entry(pthis);
+ pqhc = (PEHCI_QH_CONTENT) pqh;
+
+ if (pqhc->is_async_head)
+ TRAP();
+
+ ListFirst(&pqh->elem_head_link->sched_link, pnext);
+ ListFirstPrev(&pqh->elem_head_link->sched_link, pprev);
+
+ if (pprev == &ehci->async_list_cpu)
+ {
+ // we will at least have a qh with H-bit 1 in the async-list
+ TRAP();
+ }
+ else if (pnext == &ehci->async_list_cpu)
+ {
+ // remove the last one
+ pqhprev = qh_from_schedule(pprev);
+ ListFirst(&ehci->async_list_cpu, pnext);
+ pqhnext = qh_from_schedule(pnext);
+ pqhprev->hw_next = pqhnext->phys_addr;
+ }
+ else
+ {
+ pqhprev = qh_from_schedule(pprev);
+ pqhnext = qh_from_schedule(pnext);
+ pqhprev->hw_next = pqhnext->phys_addr;
+ }
+ RemoveEntryList(&pqh->elem_head_link->sched_link);
+ return;
}
static VOID
-ehci_insert_fstn_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_insert_fstn_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content, pc;
- PLIST_ENTRY pthis, list_head, pnext, pprev;
- PEHCI_ELEM_LINKS elem_link;
- PEHCI_QH pqh, pqhprev, pqhnext;
- PEHCI_FSTN pfstn;
- PURB purb1;
-
- ULONG interval, start_frame, start_uframe;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = ( 1 << ( pipe_content->interval + 3 ) );
- list_head = &purb->trasac_list;
- start_frame = purb->int_start_frame;
- start_uframe = ( start_frame << 3 ) + 1; //( start_frame << 3 ) + pipe_content->start_uframe;
-
- if( ( start_frame << 3 ) >= interval )
- TRAP();
-
- ListFirstPrev( list_head, pprev );
-
- if( elem_type_list_entry( pprev ) != INIT_LIST_FLAG_FSTN )
- {
- TRAP();
- return;
- }
-
- pfstn = fstn_from_list_entry( pprev );
-
- if( interval == 8 )
- {
- ListFirst( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], pthis );
-
- // skip the first one
- ListNext( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], pthis, pnext );
- pprev = pthis;
- pthis = pnext;
-
- while( pthis )
- {
- purb1 = qh_from_schedule( pthis )->elem_head_link->purb;
- pc = ( PURB_HS_PIPE_CONTENT )&purb1->pipe;
- if( pc->speed_high )
- {
- TRAP();
- return;
- }
- if( ( 1 << ( pc->interval + 3 ) ) > ( LONG )interval )
- {
- TRAP();
- continue;
- }
- else if( ( 1 << ( pc->interval + 3 ) < ( LONG )interval ) )
- {
- break;
- }
- else if( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN )
- {
- ListNext( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- }
- else if( pc->start_uframe <= 1 )
- {
- ListNext( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- }
- break;
- }
- if( pprev == NULL )
- {
- TRAP();
- return;
- }
- if( pthis == NULL )
- {
- //the last one
- InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ], \
- &pfstn->elem_head_link->sched_link );
- }
- else
- {
- if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_FSTN )
- {
- InsertHeadList( &fstn_from_schedule( pprev )->elem_head_link->sched_link, \
- &pfstn->elem_head_link->sched_link );
- }
- else
- {
- InsertHeadList( &qh_from_schedule( pprev )->elem_head_link->sched_link, \
- &pfstn->elem_head_link->sched_link );
- }
- }
- pfstn->hw_next = qh_from_schedule( pprev )->hw_next;
- qh_from_schedule( pprev )->hw_next = pfstn->phys_addr;
- }
- else
- {
- start_frame++;
- for( i = start_frame; i < ( LONG )start_frame + 1; i += ( interval >> 3 ) )
- {
- list_head = &ehci->frame_list_cpu[ i ].td_link;
- ListFirst( list_head, pthis );
-
- pprev = list_head;
- while( pthis )
- {
- // skip itds and sitds
- if( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_ITD ||
- elem_type( pthis, FALSE ) == INIT_LIST_FLAG_SITD )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- break;
- }
-
- while( pthis )
- {
- // find the insertion point
- ULONG u;
-
- pqhnext = qh_from_schedule( pthis );
- if( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN )
- purb1 = fstn_from_schedule( pthis )->elem_head_link->purb;
- else
- purb1 = pqhnext->elem_head_link->purb;
-
- if( purb1 == NULL )
- TRAP();
-
- pc = ( PURB_HS_PIPE_CONTENT )&purb1->pipe;
- u = 1 << ( pc->speed_high ? ( 1 << pc->interval ) : ( 1 << ( pc->interval + 3 ) ) );
-
- if( u > interval )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- else if( u == interval )
- {
- if( start_uframe >= \
- ( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN ? \
- 1 : pc->start_uframe ) + ( purb1->int_start_frame << 3 ) )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- else
- break;
- }
- else if( u < interval )
- {
- break;
- }
- }
-
- if( pprev == list_head )
- {
- // insert to the list head
- pnext = pfstn->elem_head_link->sched_link.Flink = list_head->Flink;
- list_head->Flink = &pfstn->elem_head_link->sched_link;
- pfstn->hw_next = ehci->frame_list[ i ]; // point to following node
- ehci->frame_list[ i ] = pfstn->phys_addr;
- }
- else
- {
- pnext = pfstn->elem_head_link->sched_link.Flink = pprev->Flink;
- pprev->Flink = &pfstn->elem_head_link->sched_link;
-
- // fstn can be handled correctly
- pfstn->hw_next = qh_from_schedule( pprev )->hw_next;
- qh_from_schedule( pprev )->hw_next = pfstn->phys_addr;
- }
- }
- // the pointer to next node of this fstn is alway same across the frame list.
- for( i = start_frame + ( interval >> 3 ); i < ( LONG )ehci->frame_count; i += ( interval >> 3 ) )
- {
- pprev = list_head = &ehci->frame_list_cpu[ i ].td_link;
- ListFirst( list_head, pthis );
-
- while( pthis )
- {
- if( pthis == pnext )
- {
- break;
- }
- pprev = pthis;
- ListNext( list_head, pthis, pthis );
- }
-
- pprev->Flink = &pfstn->elem_head_link->sched_link;
- if( pprev == list_head )
- ehci->frame_list[ i ] = pfstn->phys_addr;
- else
- qh_from_schedule( pprev )->hw_next = pfstn->phys_addr;
- }
- }
+ PURB_HS_PIPE_CONTENT pipe_content, pc;
+ PLIST_ENTRY pthis, list_head, pnext, pprev;
+ PEHCI_ELEM_LINKS elem_link;
+ PEHCI_QH pqh, pqhprev, pqhnext;
+ PEHCI_FSTN pfstn;
+ PURB purb1;
+
+ ULONG interval, start_frame, start_uframe;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = (1 << (pipe_content->interval + 3));
+ list_head = &purb->trasac_list;
+ start_frame = purb->int_start_frame;
+ start_uframe = (start_frame << 3) + 1; //( start_frame << 3 ) + pipe_content->start_uframe;
+
+ if ((start_frame << 3) >= interval)
+ TRAP();
+
+ ListFirstPrev(list_head, pprev);
+
+ if (elem_type_list_entry(pprev) != INIT_LIST_FLAG_FSTN)
+ {
+ TRAP();
+ return;
+ }
+
+ pfstn = fstn_from_list_entry(pprev);
+
+ if (interval == 8)
+ {
+ ListFirst(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis);
+
+ // skip the first one
+ ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+
+ while (pthis)
+ {
+ purb1 = qh_from_schedule(pthis)->elem_head_link->purb;
+ pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe;
+ if (pc->speed_high)
+ {
+ TRAP();
+ return;
+ }
+ if ((1 << (pc->interval + 3)) > (LONG) interval)
+ {
+ TRAP();
+ continue;
+ }
+ else if ((1 << (pc->interval + 3) < (LONG) interval))
+ {
+ break;
+ }
+ else if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN)
+ {
+ ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ }
+ else if (pc->start_uframe <= 1)
+ {
+ ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ }
+ break;
+ }
+ if (pprev == NULL)
+ {
+ TRAP();
+ return;
+ }
+ if (pthis == NULL)
+ {
+ //the last one
+ InsertTailList(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX],
+ &pfstn->elem_head_link->sched_link);
+ }
+ else
+ {
+ if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN)
+ {
+ InsertHeadList(&fstn_from_schedule(pprev)->elem_head_link->sched_link,
+ &pfstn->elem_head_link->sched_link);
+ }
+ else
+ {
+ InsertHeadList(&qh_from_schedule(pprev)->elem_head_link->sched_link,
+ &pfstn->elem_head_link->sched_link);
+ }
+ }
+ pfstn->hw_next = qh_from_schedule(pprev)->hw_next;
+ qh_from_schedule(pprev)->hw_next = pfstn->phys_addr;
+ }
+ else
+ {
+ start_frame++;
+ for(i = start_frame; i < (LONG) start_frame + 1; i += (interval >> 3))
+ {
+ list_head = &ehci->frame_list_cpu[i].td_link;
+ ListFirst(list_head, pthis);
+
+ pprev = list_head;
+ while (pthis)
+ {
+ // skip itds and sitds
+ if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_ITD ||
+ elem_type(pthis, FALSE) == INIT_LIST_FLAG_SITD)
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ break;
+ }
+
+ while (pthis)
+ {
+ // find the insertion point
+ ULONG u;
+
+ pqhnext = qh_from_schedule(pthis);
+ if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN)
+ purb1 = fstn_from_schedule(pthis)->elem_head_link->purb;
+ else
+ purb1 = pqhnext->elem_head_link->purb;
+
+ if (purb1 == NULL)
+ TRAP();
+
+ pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe;
+ u = 1 << (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3)));
+
+ if (u > interval)
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ else if (u == interval)
+ {
+ if (start_uframe >=
+ (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ?
+ 1 : pc->start_uframe) + (purb1->int_start_frame << 3))
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ else
+ break;
+ }
+ else if (u < interval)
+ {
+ break;
+ }
+ }
+
+ if (pprev == list_head)
+ {
+ // insert to the list head
+ pnext = pfstn->elem_head_link->sched_link.Flink = list_head->Flink;
+ list_head->Flink = &pfstn->elem_head_link->sched_link;
+ pfstn->hw_next = ehci->frame_list[i]; // point to following node
+ ehci->frame_list[i] = pfstn->phys_addr;
+ }
+ else
+ {
+ pnext = pfstn->elem_head_link->sched_link.Flink = pprev->Flink;
+ pprev->Flink = &pfstn->elem_head_link->sched_link;
+
+ // fstn can be handled correctly
+ pfstn->hw_next = qh_from_schedule(pprev)->hw_next;
+ qh_from_schedule(pprev)->hw_next = pfstn->phys_addr;
+ }
+ }
+ // the pointer to next node of this fstn is alway same across the frame list.
+ for(i = start_frame + (interval >> 3); i < (LONG) ehci->frame_count; i += (interval >> 3))
+ {
+ pprev = list_head = &ehci->frame_list_cpu[i].td_link;
+ ListFirst(list_head, pthis);
+
+ while (pthis)
+ {
+ if (pthis == pnext)
+ {
+ break;
+ }
+ pprev = pthis;
+ ListNext(list_head, pthis, pthis);
+ }
+
+ pprev->Flink = &pfstn->elem_head_link->sched_link;
+ if (pprev == list_head)
+ ehci->frame_list[i] = pfstn->phys_addr;
+ else
+ qh_from_schedule(pprev)->hw_next = pfstn->phys_addr;
+ }
+ }
}
static VOID
-ehci_remove_fstn_from_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_remove_fstn_from_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content;
- PLIST_ENTRY pthis, list_head, pnext, pprev;
- PEHCI_FSTN pfstn;
- PURB purb1;
-
- ULONG interval, start_frame, start_uframe;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = ( 1 << ( pipe_content->interval + 3 ) );
- list_head = &purb->trasac_list;
- start_frame = purb->int_start_frame;
- start_uframe = 1;
-
- if( ( start_frame << 3 ) >= interval )
- TRAP();
- start_frame++;
-
- ListFirstPrev( list_head, pprev );
- if( elem_type_list_entry( pprev ) != INIT_LIST_FLAG_FSTN )
- {
- TRAP();
- return;
- }
-
- pfstn = fstn_from_list_entry( pprev );
- if( interval < 8 )
- {
- TRAP();
- return;
- }
- if( interval == 8 )
- {
- ListFirstPrev( &pfstn->elem_head_link->sched_link, pprev );
- qh_from_schedule( pprev )->hw_next = pfstn->hw_next;
- RemoveEntryList( &pfstn->elem_head_link->sched_link );
- }
- else
- {
- for( i = start_frame; i < ( LONG )ehci->frame_count; i++ )
- {
- ListFirst( &ehci->frame_list_cpu[ i ].td_link, pthis );
- if( pthis == NULL )
- {
- TRAP();
- return;
- }
- pprev = &ehci->frame_list_cpu[ i ].td_link;
- while( pthis && pthis != &pfstn->elem_head_link->sched_link )
- {
- pprev = pthis;
- ListNext( &ehci->frame_list_cpu[ i ].td_link, pthis, pnext );
- pthis = pnext;
- }
- if( pthis == NULL )
- {
- TRAP();
- return;
- }
- qh_from_schedule( pprev )->hw_next = pfstn->hw_next;
- pprev->Flink = pfstn->elem_head_link->sched_link.Flink;
- }
- }
- return;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PLIST_ENTRY pthis, list_head, pnext, pprev;
+ PEHCI_FSTN pfstn;
+ PURB purb1;
+
+ ULONG interval, start_frame, start_uframe;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = (1 << (pipe_content->interval + 3));
+ list_head = &purb->trasac_list;
+ start_frame = purb->int_start_frame;
+ start_uframe = 1;
+
+ if ((start_frame << 3) >= interval)
+ TRAP();
+ start_frame++;
+
+ ListFirstPrev(list_head, pprev);
+ if (elem_type_list_entry(pprev) != INIT_LIST_FLAG_FSTN)
+ {
+ TRAP();
+ return;
+ }
+
+ pfstn = fstn_from_list_entry(pprev);
+ if (interval < 8)
+ {
+ TRAP();
+ return;
+ }
+ if (interval == 8)
+ {
+ ListFirstPrev(&pfstn->elem_head_link->sched_link, pprev);
+ qh_from_schedule(pprev)->hw_next = pfstn->hw_next;
+ RemoveEntryList(&pfstn->elem_head_link->sched_link);
+ }
+ else
+ {
+ for(i = start_frame; i < (LONG) ehci->frame_count; i++)
+ {
+ ListFirst(&ehci->frame_list_cpu[i].td_link, pthis);
+ if (pthis == NULL)
+ {
+ TRAP();
+ return;
+ }
+ pprev = &ehci->frame_list_cpu[i].td_link;
+ while (pthis && pthis != &pfstn->elem_head_link->sched_link)
+ {
+ pprev = pthis;
+ ListNext(&ehci->frame_list_cpu[i].td_link, pthis, pnext);
+ pthis = pnext;
+ }
+ if (pthis == NULL)
+ {
+ TRAP();
+ return;
+ }
+ qh_from_schedule(pprev)->hw_next = pfstn->hw_next;
+ pprev->Flink = pfstn->elem_head_link->sched_link.Flink;
+ }
+ }
+ return;
}
static VOID
-ehci_insert_int_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_insert_int_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content, pc;
- PLIST_ENTRY pthis, list_head, pnext, pprev;
- PEHCI_ELEM_LINKS elem_link;
- PEHCI_QH pqh, pqhprev, pqhnext;
- PURB purb1;
-
- ULONG interval, u, start_frame, start_uframe;
- LONG i;
- UCHAR need_fstn;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = REAL_INTERVAL;
- start_uframe = ( purb->int_start_frame << 3 ) + pipe_content->start_uframe;
- start_frame = purb->int_start_frame;
- need_fstn = FALSE;
- list_head = &purb->trasac_list;
-
- ListFirst( list_head, pthis );
- if( pthis == NULL )
- return;
-
- pqh = qh_from_list_entry( pthis );
-
- if( !pipe_content->speed_high )
- {
- interval = ( interval << 3 );
- ListFirstPrev( list_head, pprev );
- if( elem_type_list_entry( pprev ) == INIT_LIST_FLAG_FSTN )
- need_fstn = TRUE;
- }
-
- if( interval < 16 )
- {
- pqhprev = pqhnext = NULL;
- if( interval == 1 )
- {
- list_head = &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ];
- ListFirst( list_head, pthis );
- InsertTailList( list_head, &pqh->elem_head_link->sched_link );
- ListFirstPrev( &pqh->elem_head_link->sched_link, pprev );
- pqh->hw_next = EHCI_PTR_TERM;
- if( pprev == pthis )
- {
- fstn_from_schedule( pthis )->hw_next = pqh->phys_addr;
- }
- else
- {
- qh_from_schedule( pthis )->hw_next = pqh->phys_addr;
- }
- }
- else // interval == 2 or 4 or 8
- {
- list_head = &ehci->periodic_list_cpu[ EHCI_SCHED_INT8_INDEX ];
- ListFirst( list_head, pthis );
- pprev = NULL;
- while( pthis )
- {
- elem_link = struct_ptr( pthis, EHCI_ELEM_LINKS, sched_link );
- purb1 = elem_link->purb;
- pc = ( PURB_HS_PIPE_CONTENT )purb1->pipe;
- u = ( pc->speed_high ? ( 1 << pc->interval ) : ( 1 << ( pc->interval + 3 ) ) );
-
- if( interval < u )
- {
- ListFirstPrev( pthis, pprev );
- break;
- }
- else if( interval > u )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- // FIXME: is this right to fix fstn's start_uf 1???
- else if( start_uframe <= \
- ( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN ? \
- 1 : pc->start_uframe ) + ( purb1->int_start_frame << 3 ) )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- else // interval is equal, and start_uframe is greater
- {
- ListFirstPrev( pthis, pprev );
- break;
- }
- }
- if( pprev == NULL )
- {
- // at least one dummy qh is there
- TRAP();
- }
- else if( pnext == NULL )
- {
- // the last one in this chain, fstn can be handled correctly
- InsertTailList( list_head, &pqh->elem_head_link->sched_link );
- pqhprev = qh_from_schedule( pprev );
- pqh->hw_next = pqhprev->hw_next;
- pqhprev->hw_next = pqh->phys_addr;
- }
- else
- { pqhprev = qh_from_schedule( pprev );
- if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_QH )
- {
- InsertHeadList( &pqhprev->elem_head_link->sched_link, &pqh->elem_head_link->sched_link );
- }
- else if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_FSTN )
- {
- InsertHeadList( &fstn_from_schedule( pprev )->elem_head_link->sched_link, &pqh->elem_head_link->sched_link );
- }
- pqh->hw_next = pqhprev->hw_next;
- pqhprev->hw_next = pqh->phys_addr;
- }
- }
- }
- else // interval >= 16
- {
- if( ( start_frame << 3 ) >= interval )
- TRAP();
-
- for( i = start_frame; i < ( LONG )start_frame + 1; i += ( interval >> 3 ) )
- {
- list_head = &ehci->frame_list_cpu[ i ].td_link;
- ListFirst( list_head, pthis );
-
- pprev = list_head;
- while( pthis )
- {
- // skip itds and sitds
- if( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_ITD ||
- elem_type( pthis, FALSE ) == INIT_LIST_FLAG_SITD )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- break;
- }
-
- while( pthis )
- {
- // find the insertion point
-
- pqhnext = qh_from_schedule( pthis );
- if( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN )
- purb1 = fstn_from_schedule( pthis )->elem_head_link->purb;
- else
- purb1 = pqhnext->elem_head_link->purb;
-
- if( purb1 == NULL )
- TRAP();
-
- pc = ( PURB_HS_PIPE_CONTENT )&purb1->pipe;
- u = 1 << ( pc->speed_high ? ( 1 << pc->interval ) : ( 1 << ( pc->interval + 3 ) ) );
-
- if( u > interval )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- else if( u == interval )
- {
- if( start_uframe >= \
- ( elem_type( pthis, FALSE ) == INIT_LIST_FLAG_FSTN ? \
- 1 : pc->start_uframe ) + ( purb1->int_start_frame << 3 ) )
- {
- ListNext( list_head, pthis, pnext );
- pprev = pthis;
- pthis = pnext;
- continue;
- }
- else
- break;
- }
- else if( u < interval )
- {
- break;
- }
- }
- if( pprev == list_head )
- {
- // insert to the list head
- pnext = pqh->elem_head_link->sched_link.Flink = list_head->Flink;
- list_head->Flink = &pqh->elem_head_link->sched_link;
- pqh->hw_next = ehci->frame_list[ i ]; // point to following node
- ehci->frame_list[ i ] = pqh->phys_addr;
- }
- else
- {
- pnext = pqh->elem_head_link->sched_link.Flink = pprev->Flink;
- pprev->Flink = &pqh->elem_head_link->sched_link;
-
- // fstn can be handled correctly
- pqh->hw_next = qh_from_schedule( pprev )->hw_next;
- qh_from_schedule( pprev )->hw_next = pqh->phys_addr;
- }
- }
- for( i = start_frame + ( interval >> 3 ); i < ( LONG )ehci->frame_count; i += ( interval >> 3 ) )
- {
- pprev = list_head = &ehci->frame_list_cpu[ i ].td_link;
- ListFirst( list_head, pthis );
-
- while( pthis )
- {
- if( pthis == pnext )
- {
- break;
- }
- pprev = pthis;
- ListNext( list_head, pthis, pthis );
- }
-
- pprev->Flink = &pqh->elem_head_link->sched_link;
- if( pprev == list_head )
- ehci->frame_list[ i ] = pqh->phys_addr;
- else
- qh_from_schedule( pprev )->hw_next = pqh->phys_addr;
- }
- }
-
- if( need_fstn )
- ehci_insert_fstn_schedule( ehci, purb );
-
- return;
+ PURB_HS_PIPE_CONTENT pipe_content, pc;
+ PLIST_ENTRY pthis, list_head, pnext, pprev;
+ PEHCI_ELEM_LINKS elem_link;
+ PEHCI_QH pqh, pqhprev, pqhnext;
+ PURB purb1;
+
+ ULONG interval, u, start_frame, start_uframe;
+ LONG i;
+ UCHAR need_fstn;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = REAL_INTERVAL;
+ start_uframe = (purb->int_start_frame << 3) + pipe_content->start_uframe;
+ start_frame = purb->int_start_frame;
+ need_fstn = FALSE;
+ list_head = &purb->trasac_list;
+
+ ListFirst(list_head, pthis);
+ if (pthis == NULL)
+ return;
+
+ pqh = qh_from_list_entry(pthis);
+
+ if (!pipe_content->speed_high)
+ {
+ interval = (interval << 3);
+ ListFirstPrev(list_head, pprev);
+ if (elem_type_list_entry(pprev) == INIT_LIST_FLAG_FSTN)
+ need_fstn = TRUE;
+ }
+
+ if (interval < 16)
+ {
+ pqhprev = pqhnext = NULL;
+ if (interval == 1)
+ {
+ list_head = &ehci->periodic_list_cpu[EHCI_SCHED_FSTN_INDEX];
+ ListFirst(list_head, pthis);
+ InsertTailList(list_head, &pqh->elem_head_link->sched_link);
+ ListFirstPrev(&pqh->elem_head_link->sched_link, pprev);
+ pqh->hw_next = EHCI_PTR_TERM;
+ if (pprev == pthis)
+ {
+ fstn_from_schedule(pthis)->hw_next = pqh->phys_addr;
+ }
+ else
+ {
+ qh_from_schedule(pthis)->hw_next = pqh->phys_addr;
+ }
+ }
+ else // interval == 2 or 4 or 8
+ {
+ list_head = &ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX];
+ ListFirst(list_head, pthis);
+ pprev = NULL;
+ while (pthis)
+ {
+ elem_link = struct_ptr(pthis, EHCI_ELEM_LINKS, sched_link);
+ purb1 = elem_link->purb;
+ pc = (PURB_HS_PIPE_CONTENT) purb1->pipe;
+ u = (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3)));
+
+ if (interval < u)
+ {
+ ListFirstPrev(pthis, pprev);
+ break;
+ }
+ else if (interval > u)
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ // FIXME: is this right to fix fstn's start_uf 1???
+ else if (start_uframe <=
+ (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ?
+ 1 : pc->start_uframe) + (purb1->int_start_frame << 3))
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ else // interval is equal, and start_uframe is greater
+ {
+ ListFirstPrev(pthis, pprev);
+ break;
+ }
+ }
+ if (pprev == NULL)
+ {
+ // at least one dummy qh is there
+ TRAP();
+ }
+ else if (pnext == NULL)
+ {
+ // the last one in this chain, fstn can be handled correctly
+ InsertTailList(list_head, &pqh->elem_head_link->sched_link);
+ pqhprev = qh_from_schedule(pprev);
+ pqh->hw_next = pqhprev->hw_next;
+ pqhprev->hw_next = pqh->phys_addr;
+ }
+ else
+ {
+ pqhprev = qh_from_schedule(pprev);
+ if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_QH)
+ {
+ InsertHeadList(&pqhprev->elem_head_link->sched_link, &pqh->elem_head_link->sched_link);
+ }
+ else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN)
+ {
+ InsertHeadList(&fstn_from_schedule(pprev)->elem_head_link->sched_link,
+ &pqh->elem_head_link->sched_link);
+ }
+ pqh->hw_next = pqhprev->hw_next;
+ pqhprev->hw_next = pqh->phys_addr;
+ }
+ }
+ }
+ else // interval >= 16
+ {
+ if ((start_frame << 3) >= interval)
+ TRAP();
+
+ for(i = start_frame; i < (LONG) start_frame + 1; i += (interval >> 3))
+ {
+ list_head = &ehci->frame_list_cpu[i].td_link;
+ ListFirst(list_head, pthis);
+
+ pprev = list_head;
+ while (pthis)
+ {
+ // skip itds and sitds
+ if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_ITD ||
+ elem_type(pthis, FALSE) == INIT_LIST_FLAG_SITD)
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ break;
+ }
+
+ while (pthis)
+ {
+ // find the insertion point
+
+ pqhnext = qh_from_schedule(pthis);
+ if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN)
+ purb1 = fstn_from_schedule(pthis)->elem_head_link->purb;
+ else
+ purb1 = pqhnext->elem_head_link->purb;
+
+ if (purb1 == NULL)
+ TRAP();
+
+ pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe;
+ u = 1 << (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3)));
+
+ if (u > interval)
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ else if (u == interval)
+ {
+ if (start_uframe >=
+ (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ?
+ 1 : pc->start_uframe) + (purb1->int_start_frame << 3))
+ {
+ ListNext(list_head, pthis, pnext);
+ pprev = pthis;
+ pthis = pnext;
+ continue;
+ }
+ else
+ break;
+ }
+ else if (u < interval)
+ {
+ break;
+ }
+ }
+ if (pprev == list_head)
+ {
+ // insert to the list head
+ pnext = pqh->elem_head_link->sched_link.Flink = list_head->Flink;
+ list_head->Flink = &pqh->elem_head_link->sched_link;
+ pqh->hw_next = ehci->frame_list[i]; // point to following node
+ ehci->frame_list[i] = pqh->phys_addr;
+ }
+ else
+ {
+ pnext = pqh->elem_head_link->sched_link.Flink = pprev->Flink;
+ pprev->Flink = &pqh->elem_head_link->sched_link;
+
+ // fstn can be handled correctly
+ pqh->hw_next = qh_from_schedule(pprev)->hw_next;
+ qh_from_schedule(pprev)->hw_next = pqh->phys_addr;
+ }
+ }
+ for(i = start_frame + (interval >> 3); i < (LONG) ehci->frame_count; i += (interval >> 3))
+ {
+ pprev = list_head = &ehci->frame_list_cpu[i].td_link;
+ ListFirst(list_head, pthis);
+
+ while (pthis)
+ {
+ if (pthis == pnext)
+ {
+ break;
+ }
+ pprev = pthis;
+ ListNext(list_head, pthis, pthis);
+ }
+
+ pprev->Flink = &pqh->elem_head_link->sched_link;
+ if (pprev == list_head)
+ ehci->frame_list[i] = pqh->phys_addr;
+ else
+ qh_from_schedule(pprev)->hw_next = pqh->phys_addr;
+ }
+ }
+
+ if (need_fstn)
+ ehci_insert_fstn_schedule(ehci, purb);
+
+ return;
}
static VOID
-ehci_remove_int_from_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_remove_int_from_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content, pc;
- PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
- PEHCI_ELEM_LINKS elem_link;
- PEHCI_QH pqh, pqhprev, pqhnext;
- PURB purb1;
-
- ULONG interval, start_frame, start_uframe, u;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- interval = REAL_INTERVAL;
- start_uframe = ( purb->int_start_frame << 3 ) + pipe_content->start_uframe;
- start_frame = purb->int_start_frame;
-
- ListFirst( &purb->trasac_list, pthis );
- if( pthis == NULL )
- return;
-
- pqh = qh_from_list_entry( pthis );
- list_head = &purb->trasac_list;
-
- if( IsListEmpty( list_head ) )
- {
- TRAP();
- return;
- }
-
- if( !pipe_content->speed_high )
- {
- interval = ( interval << 3 );
- }
-
- if( interval >= 256 * 8 )
- return;
-
- if( interval < 16 )
- {
- ListFirstPrev( &pqh->elem_head_link->sched_link, pprev );
- RemoveEntryList( &pqh->elem_head_link->sched_link );
- if( interval > 1 )
- {
- pqhprev = qh_from_schedule( pprev );
- pqhprev->hw_next = pqh->hw_next;
- }
- else
- {
- ListFirst( &ehci->frame_list_cpu[ EHCI_SCHED_FSTN_INDEX ].td_link, list_head );
- if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_FSTN )
- {
- fstn_from_schedule( list_head )->hw_next = pqh->hw_next;
- }
- else
- {
- qh_from_schedule( pprev )->hw_next = pqh->hw_next;
- }
- }
- }
- else if( interval >= 16 )
- {
- ListFirst( list_head, pthis );
- pthis = &pqh->elem_head_link->sched_link;
-
- for( i = start_uframe; i < ( LONG )( ehci->frame_count << 3 ); i += interval )
- {
- ListFirst( &ehci->frame_list_cpu[ i ].td_link, pcur );
- pprev = NULL;
- while( pthis != pcur && pcur )
- {
- ListNext( &ehci->frame_list_cpu[ i ].td_link, pcur, pnext );
- pprev = pcur;
- pcur = pnext;
- }
-
- if( pcur == NULL )
- {
- TRAP();
- continue;
- }
- else if( pprev == NULL )
- {
- // the first one in the frame list
- ehci->frame_list_cpu[ i ].td_link.Flink = pthis->Flink;
- ehci->frame_list[ i ] = qh_from_schedule( pthis )->hw_next;
- }
- else
- {
- if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_QH )
- {
- qh_from_schedule( pprev )->elem_head_link->sched_link.Flink = pqh->elem_head_link->sched_link.Flink;
- qh_from_schedule( pprev )->hw_next = pqh->hw_next;
- }
- else if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_ITD )
- {
- itd_from_schedule( pprev )->elem_head_link->sched_link.Flink = pqh->elem_head_link->sched_link.Flink;
- itd_from_schedule( pprev )->hw_next = pqh->hw_next;
- }
- else if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_SITD )
- {
- sitd_from_schedule( pprev )->elem_head_link->sched_link.Flink = pqh->elem_head_link->sched_link.Flink;
- sitd_from_schedule( pprev )->hw_next = pqh->hw_next;
- }
- else if( elem_type( pprev, FALSE ) == INIT_LIST_FLAG_FSTN )
- {
- fstn_from_schedule( pprev )->elem_head_link->sched_link.Flink = pqh->elem_head_link->sched_link.Flink;
- fstn_from_schedule( pprev )->hw_next = pqh->hw_next;
- }
- else
- TRAP();
- }
- }
- }
-
- ListFirstPrev( &purb->trasac_list, pprev );
- if( elem_type_list_entry( pprev ) == INIT_LIST_FLAG_FSTN )
- ehci_remove_fstn_from_schedule( ehci, purb );
- return;
+ PURB_HS_PIPE_CONTENT pipe_content, pc;
+ PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
+ PEHCI_ELEM_LINKS elem_link;
+ PEHCI_QH pqh, pqhprev, pqhnext;
+ PURB purb1;
+
+ ULONG interval, start_frame, start_uframe, u;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ interval = REAL_INTERVAL;
+ start_uframe = (purb->int_start_frame << 3) + pipe_content->start_uframe;
+ start_frame = purb->int_start_frame;
+
+ ListFirst(&purb->trasac_list, pthis);
+ if (pthis == NULL)
+ return;
+
+ pqh = qh_from_list_entry(pthis);
+ list_head = &purb->trasac_list;
+
+ if (IsListEmpty(list_head))
+ {
+ TRAP();
+ return;
+ }
+
+ if (!pipe_content->speed_high)
+ {
+ interval = (interval << 3);
+ }
+
+ if (interval >= 256 * 8)
+ return;
+
+ if (interval < 16)
+ {
+ ListFirstPrev(&pqh->elem_head_link->sched_link, pprev);
+ RemoveEntryList(&pqh->elem_head_link->sched_link);
+ if (interval > 1)
+ {
+ pqhprev = qh_from_schedule(pprev);
+ pqhprev->hw_next = pqh->hw_next;
+ }
+ else
+ {
+ ListFirst(&ehci->frame_list_cpu[EHCI_SCHED_FSTN_INDEX].td_link, list_head);
+ if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN)
+ {
+ fstn_from_schedule(list_head)->hw_next = pqh->hw_next;
+ }
+ else
+ {
+ qh_from_schedule(pprev)->hw_next = pqh->hw_next;
+ }
+ }
+ }
+ else if (interval >= 16)
+ {
+ ListFirst(list_head, pthis);
+ pthis = &pqh->elem_head_link->sched_link;
+
+ for(i = start_uframe; i < (LONG) (ehci->frame_count << 3); i += interval)
+ {
+ ListFirst(&ehci->frame_list_cpu[i].td_link, pcur);
+ pprev = NULL;
+ while (pthis != pcur && pcur)
+ {
+ ListNext(&ehci->frame_list_cpu[i].td_link, pcur, pnext);
+ pprev = pcur;
+ pcur = pnext;
+ }
+
+ if (pcur == NULL)
+ {
+ TRAP();
+ continue;
+ }
+ else if (pprev == NULL)
+ {
+ // the first one in the frame list
+ ehci->frame_list_cpu[i].td_link.Flink = pthis->Flink;
+ ehci->frame_list[i] = qh_from_schedule(pthis)->hw_next;
+ }
+ else
+ {
+ if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_QH)
+ {
+ qh_from_schedule(pprev)->elem_head_link->sched_link.Flink =
+ pqh->elem_head_link->sched_link.Flink;
+ qh_from_schedule(pprev)->hw_next = pqh->hw_next;
+ }
+ else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_ITD)
+ {
+ itd_from_schedule(pprev)->elem_head_link->sched_link.Flink =
+ pqh->elem_head_link->sched_link.Flink;
+ itd_from_schedule(pprev)->hw_next = pqh->hw_next;
+ }
+ else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_SITD)
+ {
+ sitd_from_schedule(pprev)->elem_head_link->sched_link.Flink =
+ pqh->elem_head_link->sched_link.Flink;
+ sitd_from_schedule(pprev)->hw_next = pqh->hw_next;
+ }
+ else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN)
+ {
+ fstn_from_schedule(pprev)->elem_head_link->sched_link.Flink =
+ pqh->elem_head_link->sched_link.Flink;
+ fstn_from_schedule(pprev)->hw_next = pqh->hw_next;
+ }
+ else
+ TRAP();
+ }
+ }
+ }
+
+ ListFirstPrev(&purb->trasac_list, pprev);
+ if (elem_type_list_entry(pprev) == INIT_LIST_FLAG_FSTN)
+ ehci_remove_fstn_from_schedule(ehci, purb);
+ return;
}
static VOID
-ehci_insert_iso_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_insert_iso_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content;
- PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
-
- ULONG interval, start_frame;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
-
- interval = 8;
- if( pipe_content->speed_high )
- interval = REAL_INTERVAL;
-
- start_frame = purb->iso_start_frame;
-
- ListFirst( &purb->trasac_list, pthis );
- if( pthis == NULL )
- {
- TRAP();
- return;
- }
-
- list_head = &purb->trasac_list;
- if( IsListEmpty( list_head ) )
- {
- TRAP();
- return;
- }
-
- i = start_frame;
- while( pthis )
- {
- if( pipe_content->speed_high )
- {
- itd_from_list_entry( pthis )->elem_head_link->sched_link.Flink = ehci->frame_list_cpu[ i ].td_link.Flink;
- itd_from_list_entry( pthis )->hw_next = ehci->frame_list[ i ];
-
- ehci->frame_list[ i ] = itd_from_list_entry( pthis )->phys_addr;
- ehci->frame_list_cpu[ i ].td_link.Flink = pthis;
- }
- else
- {
- sitd_from_list_entry( pthis )->elem_head_link->sched_link.Flink = ehci->frame_list_cpu[ i ].td_link.Flink;
- sitd_from_list_entry( pthis )->hw_next = ehci->frame_list[ i ];
-
- ehci->frame_list[ i ] = sitd_from_list_entry( pthis )->phys_addr;
- ehci->frame_list_cpu[ i ].td_link.Flink = pthis;
- }
-
- ListNext( list_head, pthis, pnext );
- pthis = pnext;
-
- if( interval <= 8 )
- i++;
- else
- i += ( interval >> 3 );
- }
- return;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
+
+ ULONG interval, start_frame;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+
+ interval = 8;
+ if (pipe_content->speed_high)
+ interval = REAL_INTERVAL;
+
+ start_frame = purb->iso_start_frame;
+
+ ListFirst(&purb->trasac_list, pthis);
+ if (pthis == NULL)
+ {
+ TRAP();
+ return;
+ }
+
+ list_head = &purb->trasac_list;
+ if (IsListEmpty(list_head))
+ {
+ TRAP();
+ return;
+ }
+
+ i = start_frame;
+ while (pthis)
+ {
+ if (pipe_content->speed_high)
+ {
+ itd_from_list_entry(pthis)->elem_head_link->sched_link.Flink =
+ ehci->frame_list_cpu[i].td_link.Flink;
+ itd_from_list_entry(pthis)->hw_next = ehci->frame_list[i];
+
+ ehci->frame_list[i] = itd_from_list_entry(pthis)->phys_addr;
+ ehci->frame_list_cpu[i].td_link.Flink = pthis;
+ }
+ else
+ {
+ sitd_from_list_entry(pthis)->elem_head_link->sched_link.Flink =
+ ehci->frame_list_cpu[i].td_link.Flink;
+ sitd_from_list_entry(pthis)->hw_next = ehci->frame_list[i];
+
+ ehci->frame_list[i] = sitd_from_list_entry(pthis)->phys_addr;
+ ehci->frame_list_cpu[i].td_link.Flink = pthis;
+ }
+
+ ListNext(list_head, pthis, pnext);
+ pthis = pnext;
+
+ if (interval <= 8)
+ i++;
+ else
+ i += (interval >> 3);
+ }
+ return;
}
static VOID
-ehci_remove_iso_from_schedule(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_remove_iso_from_schedule(PEHCI_DEV ehci, PURB purb)
{
- PURB_HS_PIPE_CONTENT pipe_content;
- PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
-
- ULONG interval, start_frame;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
-
- interval = 8;
- if( pipe_content->speed_high )
- interval = REAL_INTERVAL;
-
- start_frame = purb->iso_start_frame;
-
- ListFirst( &purb->trasac_list, pthis );
- if( pthis == NULL )
- {
- TRAP();
- return;
- }
-
- list_head = &purb->trasac_list;
- if( IsListEmpty( list_head ) )
- {
- TRAP();
- return;
- }
-
- i = start_frame;
- while( pthis )
- {
- // for the possible existance of sitd back pointer, we can not use for(...)
- ListFirst( &ehci->frame_list_cpu[ i ].td_link, pcur );
- pprev = &ehci->frame_list_cpu[ i ].td_link;
- while( pcur )
- {
- if( pcur != pthis )
- {
- ListNext( &ehci->frame_list_cpu[ i ].td_link, pcur, pnext );
- pprev = pcur;
- pcur = pnext;
- continue;
- }
- break;
- }
-
- if( pcur == NULL )
- {
- TRAP();
- }
- pprev->Flink = pcur->Flink;
- if( pprev != &ehci->frame_list_cpu[ i ].td_link )
- qh_from_schedule( pprev )->hw_next = qh_from_schedule( pcur )->hw_next;
- else
- ehci->frame_list[ i ] = qh_from_schedule( pcur )->hw_next;
-
- ListNext( list_head, pthis, pnext );
- pthis = pnext;
-
- if( interval <= 8 )
- i++;
- else
- i += ( interval >> 3 );
- }
- return;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PLIST_ENTRY pthis, list_head, pnext, pprev, pcur;
+
+ ULONG interval, start_frame;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+
+ interval = 8;
+ if (pipe_content->speed_high)
+ interval = REAL_INTERVAL;
+
+ start_frame = purb->iso_start_frame;
+
+ ListFirst(&purb->trasac_list, pthis);
+ if (pthis == NULL)
+ {
+ TRAP();
+ return;
+ }
+
+ list_head = &purb->trasac_list;
+ if (IsListEmpty(list_head))
+ {
+ TRAP();
+ return;
+ }
+
+ i = start_frame;
+ while (pthis)
+ {
+ // for the possible existance of sitd back pointer, we can not use for(...)
+ ListFirst(&ehci->frame_list_cpu[i].td_link, pcur);
+ pprev = &ehci->frame_list_cpu[i].td_link;
+ while (pcur)
+ {
+ if (pcur != pthis)
+ {
+ ListNext(&ehci->frame_list_cpu[i].td_link, pcur, pnext);
+ pprev = pcur;
+ pcur = pnext;
+ continue;
+ }
+ break;
+ }
+
+ if (pcur == NULL)
+ {
+ TRAP();
+ }
+ pprev->Flink = pcur->Flink;
+ if (pprev != &ehci->frame_list_cpu[i].td_link)
+ qh_from_schedule(pprev)->hw_next = qh_from_schedule(pcur)->hw_next;
+ else
+ ehci->frame_list[i] = qh_from_schedule(pcur)->hw_next;
+
+ ListNext(list_head, pthis, pnext);
+ pthis = pnext;
+
+ if (interval <= 8)
+ i++;
+ else
+ i += (interval >> 3);
+ }
+ return;
}
NTSTATUS
-ehci_isr_removing_urb(
-PEHCI_DEV ehci,
-PURB purb,
-BOOL doorbell_rings,
-ULONG cur_frame
-)
+ehci_isr_removing_urb(PEHCI_DEV ehci, PURB purb, BOOL doorbell_rings, ULONG cur_frame)
{
- UCHAR type;
- PLIST_ENTRY pthis, plast;
- PURB_HS_PIPE_CONTENT pipe_content;
- PEHCI_ITD_CONTENT pitd_content;
- PEHCI_SITD_CONTENT psitd_content;
- PEHCI_QH_CONTENT pqh_content;
- PEHCI_QTD_CONTENT pqtd_content;
- LONG i;
+ UCHAR type;
+ PLIST_ENTRY pthis, plast;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PEHCI_ITD_CONTENT pitd_content;
+ PEHCI_SITD_CONTENT psitd_content;
+ PEHCI_QH_CONTENT pqh_content;
+ PEHCI_QTD_CONTENT pqtd_content;
+ LONG i;
- if( purb == NULL || ehci == NULL )
- return STATUS_INVALID_PARAMETER;
+ if (purb == NULL || ehci == NULL)
+ return STATUS_INVALID_PARAMETER;
- if( ( purb->flags & URB_FLAG_STATE_MASK ) == URB_FLAG_STATE_FINISHED )
- return STATUS_SUCCESS;
+ if ((purb->flags & URB_FLAG_STATE_MASK) == URB_FLAG_STATE_FINISHED)
+ return STATUS_SUCCESS;
type = 0;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
-
- switch( purb->flags & URB_FLAG_STATE_MASK )
- {
- case URB_FLAG_STATE_IN_PROCESS:
- {
- // determine the removal type: complete, error or cancel
- ListFirst( &purb->trasac_list, pthis );
- if( purb->flags & URB_FLAG_FORCE_CANCEL )
- {
- type = 3;
- }
- else
- {
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_INT || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL )
- {
- pqh_content = ( PEHCI_QH_CONTENT )( ( ULONG )struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link )->phys_part & PHYS_PART_ADDR_MASK );
- if( EHCI_QH_ERROR( pqh_content ) )
- {
- purb->status = pqh_content->cur_qtd.status;
- type = 2;
- }
- else
- {
- pqtd_content = &pqh_content->cur_qtd;
- if( pqtd_content->terminal && \
- ( ( pqtd_content->status & QTD_STS_ACTIVE ) == 0 ) )
- {
- type = 1;
- }
- // else, not finished
- }
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC )
- {
- // FIXME: do we need to check if current frame falls out of the
- // frame range of iso transfer
- // inspect the last td to determine if finished
- ListFirstPrev( &purb->trasac_list, pthis );
- if( pthis )
- {
- if( pipe_content->speed_high )
- {
- pitd_content = ( PEHCI_ITD_CONTENT )( ( ULONG )struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link )->phys_part & PHYS_PART_ADDR_MASK );
- for( i = 0; i < 8; i++ )
- {
- if( pitd_content->status_slot[ i ].trans_length && \
- pitd_content->status_slot[ i ].status & 0x08 )
- {
- break;
- }
- }
- if( i == 8 )
- {
- // the itds are all inactive
- type = 1;
- }
- }
- else
- {
- psitd_content = ( PEHCI_SITD_CONTENT )( ( ULONG )struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link )->phys_part & PHYS_PART_ADDR_MASK );
- if( ( psitd_content->status & 0x80 ) == 0 )
- {
- type = 1;
- }
- }
- }
- else // empty transaction list in purb
- TRAP();
- }
- else // unknown transfer type
- TRAP();
-
- } // end of not force cancel
-
- if( type == 0 )
- return STATUS_SUCCESS;
-
- switch( type )
- {
- case 1:
- {
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_BULK )
- {
- ehci_remove_bulk_from_schedule( ehci, purb );
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_DOORBELL;
- purb->status = 0;
- press_doorbell( ehci );
- return STATUS_SUCCESS;
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC )
- {
- ehci_remove_iso_from_schedule( ehci, purb );
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_INT )
- {
- ehci_remove_int_from_schedule( ehci, purb );
- }
- else // unknown transfer type
- TRAP();
-
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_FINISHED;
-
- // notify dpc the purb can be completed;
- purb->flags &= ~URB_FLAG_IN_SCHEDULE;
- purb->status = 0;
-
- return STATUS_SUCCESS;
- }
- case 2:
- {
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_BULK )
- {
- ehci_deactivate_urb( purb );
- ehci_remove_bulk_from_schedule( ehci, purb );
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_DOORBELL;
- press_doorbell( ehci );
- }
- else if( pipe_content->trans_type == USB_ENDPOINT_XFER_INT )
- {
- ehci_remove_int_from_schedule( ehci, purb );
-
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_FINISHED;
- purb->flags &= ~URB_FLAG_IN_SCHEDULE;
- }
- else // unknown transfer or iso transfer
- TRAP();
- return STATUS_SUCCESS;
- }
- case 3:
- {
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_INT )
- {
- ehci_deactivate_urb( purb );
- if( pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || \
- pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL )
- ehci_remove_bulk_from_schedule( ehci, purb );
- else
- ehci_remove_int_from_schedule( ehci, purb );
-
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_DOORBELL;
-
- press_doorbell( ehci );
-
- }
- else // unknown transfer or iso transfer
- DO_NOTHING;
- purb->status = 0;
- return STATUS_SUCCESS;
- }
- default:
- TRAP();
- }
- }
- case URB_FLAG_STATE_DOORBELL:
- {
- if( doorbell_rings == FALSE )
- return STATUS_SUCCESS;
-
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_FINISHED;
- purb->flags &= ~URB_FLAG_IN_SCHEDULE;
- return STATUS_SUCCESS;
- }
- }
- return STATUS_SUCCESS;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+
+ switch (purb->flags & URB_FLAG_STATE_MASK)
+ {
+ case URB_FLAG_STATE_IN_PROCESS:
+ {
+ // determine the removal type: complete, error or cancel
+ ListFirst(&purb->trasac_list, pthis);
+ if (purb->flags & URB_FLAG_FORCE_CANCEL)
+ {
+ type = 3;
+ }
+ else
+ {
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_INT ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL)
+ {
+ pqh_content =
+ (PEHCI_QH_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->
+ phys_part & PHYS_PART_ADDR_MASK);
+ if (EHCI_QH_ERROR(pqh_content))
+ {
+ purb->status = pqh_content->cur_qtd.status;
+ type = 2;
+ }
+ else
+ {
+ pqtd_content = &pqh_content->cur_qtd;
+ if (pqtd_content->terminal && ((pqtd_content->status & QTD_STS_ACTIVE) == 0))
+ {
+ type = 1;
+ }
+ // else, not finished
+ }
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC)
+ {
+ // FIXME: do we need to check if current frame falls out of the
+ // frame range of iso transfer
+ // inspect the last td to determine if finished
+ ListFirstPrev(&purb->trasac_list, pthis);
+ if (pthis)
+ {
+ if (pipe_content->speed_high)
+ {
+ pitd_content =
+ (PEHCI_ITD_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->
+ phys_part & PHYS_PART_ADDR_MASK);
+ for(i = 0; i < 8; i++)
+ {
+ if (pitd_content->status_slot[i].trans_length &&
+ pitd_content->status_slot[i].status & 0x08)
+ {
+ break;
+ }
+ }
+ if (i == 8)
+ {
+ // the itds are all inactive
+ type = 1;
+ }
+ }
+ else
+ {
+ psitd_content =
+ (PEHCI_SITD_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->
+ phys_part & PHYS_PART_ADDR_MASK);
+ if ((psitd_content->status & 0x80) == 0)
+ {
+ type = 1;
+ }
+ }
+ }
+ else // empty transaction list in purb
+ TRAP();
+ }
+ else // unknown transfer type
+ TRAP();
+
+ } // end of not force cancel
+
+ if (type == 0)
+ return STATUS_SUCCESS;
+
+ switch (type)
+ {
+ case 1:
+ {
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_BULK)
+ {
+ ehci_remove_bulk_from_schedule(ehci, purb);
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_DOORBELL;
+ purb->status = 0;
+ press_doorbell(ehci);
+ return STATUS_SUCCESS;
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC)
+ {
+ ehci_remove_iso_from_schedule(ehci, purb);
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT)
+ {
+ ehci_remove_int_from_schedule(ehci, purb);
+ }
+ else // unknown transfer type
+ TRAP();
+
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_FINISHED;
+
+ // notify dpc the purb can be completed;
+ purb->flags &= ~URB_FLAG_IN_SCHEDULE;
+ purb->status = 0;
+
+ return STATUS_SUCCESS;
+ }
+ case 2:
+ {
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_BULK)
+ {
+ ehci_deactivate_urb(purb);
+ ehci_remove_bulk_from_schedule(ehci, purb);
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_DOORBELL;
+ press_doorbell(ehci);
+ }
+ else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT)
+ {
+ ehci_remove_int_from_schedule(ehci, purb);
+
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_FINISHED;
+ purb->flags &= ~URB_FLAG_IN_SCHEDULE;
+ }
+ else // unknown transfer or iso transfer
+ TRAP();
+ return STATUS_SUCCESS;
+ }
+ case 3:
+ {
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_INT)
+ {
+ ehci_deactivate_urb(purb);
+ if (pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
+ pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL)
+ ehci_remove_bulk_from_schedule(ehci, purb);
+ else
+ ehci_remove_int_from_schedule(ehci, purb);
+
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_DOORBELL;
+
+ press_doorbell(ehci);
+
+ }
+ else // unknown transfer or iso transfer
+ DO_NOTHING;
+ purb->status = 0;
+ return STATUS_SUCCESS;
+ }
+ default:
+ TRAP();
+ }
+ }
+ case URB_FLAG_STATE_DOORBELL:
+ {
+ if (doorbell_rings == FALSE)
+ return STATUS_SUCCESS;
+
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_FINISHED;
+ purb->flags &= ~URB_FLAG_IN_SCHEDULE;
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_SUCCESS;
}
static ULONG
-ehci_scan_iso_error(
-PEHCI_DEV ehci,
-PURB purb
-)
+ehci_scan_iso_error(PEHCI_DEV ehci, PURB purb)
// we only report the first error of the ITDs, purb->status is the status code
// return the raw status for ehci_set_error_code
{
- PURB_HS_PIPE_CONTENT pipe_content;
- PEHCI_SITD_CONTENT psitd_content;
- PEHCI_ITD_CONTENT pitd_content;
- PLIST_ENTRY pthis, pnext;
- LONG i;
-
- if( ehci == NULL || purb == NULL )
- return 0;
-
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->pipe;
- if( pipe_content->trans_type != USB_ENDPOINT_XFER_ISOC )
- {
- return 0;
- }
-
- ListFirst( &purb->trasac_list, pthis );
- if( pipe_content->speed_high )
- {
- while( pthis )
- {
- pitd_content = ( PEHCI_ITD_CONTENT )itd_from_list_entry( pthis );
- for( i = 0; i < 8; i++ )
- {
- if( pitd_content->status_slot[ i ].status & ITD_ANY_ERROR )
- break;
- }
- if( i < 8 )
- {
- // error occured
- return purb->status = pitd_content->status_slot[ i ].status;
- }
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
- }
- else
- {
- while( pthis )
- {
- psitd_content = ( PEHCI_SITD_CONTENT )sitd_from_list_entry( pthis );
- if( psitd_content->status & SITD_ANY_ERROR )
- {
- // error occured
- if( psitd_content->s_mask == 0x04 && \
- psitd_content->c_mask == 0x70 && \
- psitd_content->bytes_to_transfer == 1 )
- return purb->status = 0;
-
- return purb->status = psitd_content->status;
- }
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
- }
- return 0;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PEHCI_SITD_CONTENT psitd_content;
+ PEHCI_ITD_CONTENT pitd_content;
+ PLIST_ENTRY pthis, pnext;
+ LONG i;
+
+ if (ehci == NULL || purb == NULL)
+ return 0;
+
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
+ if (pipe_content->trans_type != USB_ENDPOINT_XFER_ISOC)
+ {
+ return 0;
+ }
+
+ ListFirst(&purb->trasac_list, pthis);
+ if (pipe_content->speed_high)
+ {
+ while (pthis)
+ {
+ pitd_content = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis);
+ for(i = 0; i < 8; i++)
+ {
+ if (pitd_content->status_slot[i].status & ITD_ANY_ERROR)
+ break;
+ }
+ if (i < 8)
+ {
+ // error occured
+ return purb->status = pitd_content->status_slot[i].status;
+ }
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+ }
+ else
+ {
+ while (pthis)
+ {
+ psitd_content = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis);
+ if (psitd_content->status & SITD_ANY_ERROR)
+ {
+ // error occured
+ if (psitd_content->s_mask == 0x04 &&
+ psitd_content->c_mask == 0x70 && psitd_content->bytes_to_transfer == 1)
+ return purb->status = 0;
+
+ return purb->status = psitd_content->status;
+ }
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+ }
+ return 0;
}
BOOLEAN
-ehci_isr(
-PKINTERRUPT interrupt,
-PVOID context
-)
+ehci_isr(PKINTERRUPT interrupt, PVOID context)
// we can not use endp here for it is within the dev scope, and
// we can not acquire the dev-lock, fortunately we saved some
// info in purb->pipe in ehci_internal_submit_XXX.
{
- PEHCI_DEV ehci;
- ULONG status, urb_count;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- BOOL door_bell_rings;
- ULONG cur_frame;
- /*
- * Read the interrupt status, and write it back to clear the
- * interrupt cause
- */
- ehci = ( PEHCI_DEV )context;
- if( ehci == NULL )
- return FALSE;
-
- status = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + EHCI_USBSTS ) );
- cur_frame = EHCI_READ_PORT_ULONG( ( PULONG )( ehci->port_base + EHCI_FRINDEX ) );
-
- status &= ( EHCI_ERROR_INT | STS_INT | STS_IAA );
- if( !status ) /* shared interrupt, not mine */
- {
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_isr(): not our int\n" ) );
- return FALSE;
- }
-
- /* clear it*/
- EHCI_WRITE_PORT_ULONG( ( PULONG )( ehci->port_base + EHCI_USBSTS ), status );
-
- if( status & EHCI_ERROR_INT )
- {
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_isr(): current ehci status=0x%x\n", status ) );
- }
- else
- {
- ehci_dbg_print( DBGLVL_MAXIMUM, ( "ehci_isr(): congratulations, no error occurs\n" ) );
- }
-
-
- if ( status & STS_FATAL )
- {
- DbgPrint( "ehci_isr(): host system error, PCI problems?\n");
- for( ; ; );
-
- }
-
- if ( status & STS_HALT ) //&& !ehci->is_suspended
- {
- DbgPrint( "ehci_isr(): host controller halted. very bad\n");
- /* FIXME: Reset the controller, fix the offending TD */
- // reset is performed in dpc
- }
-
-
- door_bell_rings = ( ( status & STS_IAA ) != 0 );
-
- // scan to remove those due
+ PEHCI_DEV ehci;
+ ULONG status, urb_count;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ BOOL door_bell_rings;
+ ULONG cur_frame;
+ /*
+ * Read the interrupt status, and write it back to clear the
+ * interrupt cause
+ */
+ ehci = (PEHCI_DEV) context;
+ if (ehci == NULL)
+ return FALSE;
+
+ status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_USBSTS));
+ cur_frame = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_FRINDEX));
+
+ status &= (EHCI_ERROR_INT | STS_INT | STS_IAA);
+ if (!status) /* shared interrupt, not mine */
+ {
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): not our int\n"));
+ return FALSE;
+ }
+
+ /* clear it */
+ EHCI_WRITE_PORT_ULONG((PULONG) (ehci->port_base + EHCI_USBSTS), status);
+
+ if (status & EHCI_ERROR_INT)
+ {
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): current ehci status=0x%x\n", status));
+ }
+ else
+ {
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): congratulations, no error occurs\n"));
+ }
+
+
+ if (status & STS_FATAL)
+ {
+ DbgPrint("ehci_isr(): host system error, PCI problems?\n");
+ for(;;);
+
+ }
+
+ if (status & STS_HALT) //&& !ehci->is_suspended
+ {
+ DbgPrint("ehci_isr(): host controller halted. very bad\n");
+ /* FIXME: Reset the controller, fix the offending TD */
+ // reset is performed in dpc
+ }
+
+
+ door_bell_rings = ((status & STS_IAA) != 0);
+
+ // scan to remove those due
#ifdef DBG
- urb_count = dbg_count_list( &ehci->urb_list );
- ehci_dbg_print( DBGLVL_MAXIMUM, ("ehci_isr(): urb# in process is %d\n", urb_count ) );
+ urb_count = dbg_count_list(&ehci->urb_list);
+ ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): urb# in process is %d\n", urb_count));
#endif
- ListFirst( &ehci->urb_list, pthis );
- while( pthis )
- {
- purb = ( PURB )pthis;
- ehci_isr_removing_urb( ehci, purb, door_bell_rings, cur_frame );
- ListNext( &ehci->urb_list, pthis, pnext );
- pthis = pnext;
- }
-
- KeInsertQueueDpc( &ehci->pdev_ext->ehci_dpc, ( PVOID )status, 0 );
- return TRUE;
+ ListFirst(&ehci->urb_list, pthis);
+ while (pthis)
+ {
+ purb = (PURB) pthis;
+ ehci_isr_removing_urb(ehci, purb, door_bell_rings, cur_frame);
+ ListNext(&ehci->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ KeInsertQueueDpc(&ehci->pdev_ext->ehci_dpc, (PVOID) status, 0);
+ return TRUE;
}
#ifndef INCLUDE_EHCI
VOID
-ehci_unload(
-IN PDRIVER_OBJECT DriverObject
-)
+ehci_unload(IN PDRIVER_OBJECT DriverObject)
{
- PDEVICE_OBJECT pdev;
- PEHCI_DEVICE_EXTENSION pdev_ext;
- PUSB_DEV_MANAGER dev_mgr;
- LONG i;
-
- pdev = DriverObject->DeviceObject;
-
- if( pdev == NULL )
- return;
-
- pdev_ext = pdev->DeviceExtension;
- if( pdev_ext == NULL )
- return;
-
- dev_mgr = &g_dev_mgr;
- if( dev_mgr == NULL )
- return;
- //
- // set the termination flag
- //
- dev_mgr->term_flag = TRUE;
+ PDEVICE_OBJECT pdev;
+ PEHCI_DEVICE_EXTENSION pdev_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+ LONG i;
+
+ pdev = DriverObject->DeviceObject;
+
+ if (pdev == NULL)
+ return;
+
+ pdev_ext = pdev->DeviceExtension;
+ if (pdev_ext == NULL)
+ return;
+
+ dev_mgr = &g_dev_mgr;
+ if (dev_mgr == NULL)
+ return;
+ //
+ // set the termination flag
+ //
+ dev_mgr->term_flag = TRUE;
+ //
+ // wake up the thread if it is
//
- // wake up the thread if it is
- //
- KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE );
- KeWaitForSingleObject(
- dev_mgr->pthread,
- Executive,
- KernelMode,
- TRUE,
- NULL);
- ObDereferenceObject( dev_mgr->pthread );
- dev_mgr->pthread = NULL;
-
- dev_mgr_release_hcd( dev_mgr );
- return;
+ KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
+ KeWaitForSingleObject(dev_mgr->pthread, Executive, KernelMode, TRUE, NULL);
+ ObDereferenceObject(dev_mgr->pthread);
+ dev_mgr->pthread = NULL;
+
+ dev_mgr_release_hcd(dev_mgr);
+ return;
}
NTSTATUS
-generic_dispatch_irp(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- PDEVEXT_HEADER dev_ext;
-
- dev_ext = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
-
- if( dev_ext && dev_ext->dispatch )
- return dev_ext->dispatch( dev_obj, irp );
-
- irp->IoStatus.Information = 0;
-
- EXIT_DISPATCH( STATUS_UNSUCCESSFUL, irp );
+ PDEVEXT_HEADER dev_ext;
+
+ dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+
+ if (dev_ext && dev_ext->dispatch)
+ return dev_ext->dispatch(dev_obj, irp);
+
+ irp->IoStatus.Information = 0;
+
+ EXIT_DISPATCH(STATUS_UNSUCCESSFUL, irp);
}
VOID
-generic_start_io(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+generic_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- PDEVEXT_HEADER dev_ext;
-
- KIRQL old_irql;
-
- IoAcquireCancelSpinLock( &old_irql );
- if (irp != dev_obj->CurrentIrp || irp->Cancel)
- {
- IoReleaseCancelSpinLock(old_irql);
- return;
- }
- else
- {
- IoSetCancelRoutine(irp, NULL);
- IoReleaseCancelSpinLock(old_irql);
- }
-
- dev_ext = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
-
- if( dev_ext && dev_ext->start_io )
- {
- dev_ext->start_io( dev_obj, irp );
- return;
- }
-
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-
- IoStartNextPacket( dev_obj, FALSE );
- IoCompleteRequest( irp, IO_NO_INCREMENT );
+ PDEVEXT_HEADER dev_ext;
+
+ KIRQL old_irql;
+
+ IoAcquireCancelSpinLock(&old_irql);
+ if (irp != dev_obj->CurrentIrp || irp->Cancel)
+ {
+ IoReleaseCancelSpinLock(old_irql);
+ return;
+ }
+ else
+ {
+ IoSetCancelRoutine(irp, NULL);
+ IoReleaseCancelSpinLock(old_irql);
+ }
+
+ dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+
+ if (dev_ext && dev_ext->start_io)
+ {
+ dev_ext->start_io(dev_obj, irp);
+ return;
+ }
+
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+
+ IoStartNextPacket(dev_obj, FALSE);
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
}
NTSTATUS
-DriverEntry(
- IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
- )
+DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
BOOLEAN fRes;
#if DBG
- // should be done before any debug output is done.
+ // should be done before any debug output is done.
// read our debug verbosity level from the registry
//NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path
- // L"DebugLevel", // REG_DWORD ValueName
- // &gDebugLevel ); // Value receiver
+ // L"DebugLevel", // REG_DWORD ValueName
+ // &gDebugLevel ); // Value receiver
- // debug_level = DBGLVL_MAXIMUM;
+ // debug_level = DBGLVL_MAXIMUM;
#endif
- ehci_dbg_print_cond( DBGLVL_MINIMUM , DEBUG_UHCI, ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer ));
+ ehci_dbg_print_cond(DBGLVL_MINIMUM, DEBUG_UHCI,
+ ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer));
// Remember our driver object, for when we create our child PDO
usb_driver_obj = DriverObject;
//
// Create dispatch points for create, close, unload
- DriverObject->MajorFunction[ IRP_MJ_CREATE ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = generic_dispatch_irp;
DriverObject->DriverUnload = ehci_unload;
// User mode DeviceIoControl() calls will be routed here
- DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_INTERNAL_DEVICE_CONTROL ] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = generic_dispatch_irp;
// User mode ReadFile()/WriteFile() calls will be routed here
- DriverObject->MajorFunction[ IRP_MJ_WRITE ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_READ ] = generic_dispatch_irp;
-
- DriverObject->MajorFunction[ IRP_MJ_SHUTDOWN ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_SCSI ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_FLUSH_BUFFERS ] = generic_dispatch_irp;
-
- DriverObject->DriverStartIo = generic_start_io;
- // routines for handling system PNP and power management requests
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_READ] = generic_dispatch_irp;
+
+ DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_SCSI] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = generic_dispatch_irp;
+
+ DriverObject->DriverStartIo = generic_start_io;
+ // routines for handling system PNP and power management requests
//DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp;
// The Functional Device Object (FDO) will not be created for PNP devices until
// this routine is called upon device plug-in.
- RtlZeroMemory( &g_dev_mgr, sizeof( USB_DEV_MANAGER ) );
- g_dev_mgr.usb_driver_obj = DriverObject;
-
- ehci_probe( DriverObject, RegistryPath, &g_dev_mgr );
-
- if( dev_mgr_strobe( &g_dev_mgr ) == FALSE )
- {
- dev_mgr_release_hcd( &g_dev_mgr );
- return STATUS_UNSUCCESSFUL;
- }
-
- dev_mgr_start_hcd( &g_dev_mgr );
- ehci_dbg_print_cond( DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus));
- return STATUS_SUCCESS;
+ RtlZeroMemory(&g_dev_mgr, sizeof(USB_DEV_MANAGER));
+ g_dev_mgr.usb_driver_obj = DriverObject;
+
+ ehci_probe(DriverObject, RegistryPath, &g_dev_mgr);
+
+ if (dev_mgr_strobe(&g_dev_mgr) == FALSE)
+ {
+ dev_mgr_release_hcd(&g_dev_mgr);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ dev_mgr_start_hcd(&g_dev_mgr);
+ ehci_dbg_print_cond(DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus));
+ return STATUS_SUCCESS;
}
#endif
max_liSTS = ( EHCI_MAX_ELEMS_POOL / ii1 ) > EHCI_MAX_LISTS_POOL ? EHCI_MAX_LISTS_POOL : ( EHCI_MAX_ELEMS_POOL / ii1 );\
}
-VOID
-elem_list_destroy_elem_list(
-PEHCI_ELEM_LIST plist
-);
+VOID elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist);
-PLIST_ENTRY
-elem_list_get_list_head(
-PEHCI_ELEM_LIST plist
-);
+PLIST_ENTRY elem_list_get_list_head(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_get_total_count(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_get_total_count(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_get_elem_size(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_get_elem_size(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_get_link_offset(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_get_link_offset(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_add_ref(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_add_ref(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_release_ref(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_release_ref(PEHCI_ELEM_LIST plist);
-LONG
-elem_list_get_ref(
-PEHCI_ELEM_LIST plist
-);
+LONG elem_list_get_ref(PEHCI_ELEM_LIST plist);
BOOL
-elem_pool_lock(
-PEHCI_ELEM_POOL pool,
-BOOL at_dpc
-)
+elem_pool_lock(PEHCI_ELEM_POOL pool, BOOL at_dpc)
{
- return TRUE;
+ return TRUE;
}
+
BOOL
-elem_pool_unlock(
-PEHCI_ELEM_POOL pool,
-BOOL at_dpc
-)
+elem_pool_unlock(PEHCI_ELEM_POOL pool, BOOL at_dpc)
{
- return TRUE;
+ return TRUE;
}
+
LONG
-get_elem_phys_part_size(
-ULONG type
-)
+get_elem_phys_part_size(ULONG type)
{
- // type is INIT_LIST_FLAG_XXX
- LONG size;
-
- size = 0;
- switch( type )
- {
- case INIT_LIST_FLAG_ITD:
- size = 64;
- break;
- case INIT_LIST_FLAG_SITD:
- size = 28;
- break;
- case INIT_LIST_FLAG_QTD:
- size = 32;
- break;
- case INIT_LIST_FLAG_QH:
- size = 48;
- break;
- case INIT_LIST_FLAG_FSTN:
- size = 8;
- break;
- }
- return size;
+ // type is INIT_LIST_FLAG_XXX
+ LONG size;
+
+ size = 0;
+ switch (type)
+ {
+ case INIT_LIST_FLAG_ITD:
+ size = 64;
+ break;
+ case INIT_LIST_FLAG_SITD:
+ size = 28;
+ break;
+ case INIT_LIST_FLAG_QTD:
+ size = 32;
+ break;
+ case INIT_LIST_FLAG_QH:
+ size = 48;
+ break;
+ case INIT_LIST_FLAG_FSTN:
+ size = 8;
+ break;
+ }
+ return size;
}
-BOOL
-elem_list_init_elem_list(
-PEHCI_ELEM_LIST plist,
-LONG init_flags,
-PVOID context,
-LONG count
-)
+BOOL
+elem_list_init_elem_list(PEHCI_ELEM_LIST plist, LONG init_flags, PVOID context, LONG count)
{
- LONG pages, i, j, elms_per_page;
- PEHCI_QH pqh;
- PEHCI_ITD pitd;
- PEHCI_SITD psitd;
- PEHCI_QTD pqtd;
- PEHCI_FSTN pfstn;
- PINIT_ELEM_LIST_CONTEXT pinit_ctx;
-
- if( plist == NULL || context == NULL )
- return FALSE;
-
- RtlZeroMemory( plist, sizeof( EHCI_ELEM_LIST ) );
-
- pinit_ctx = context;
-
- plist->destroy_list = elem_list_destroy_elem_list;
- plist->get_list_head = elem_list_get_list_head;
- plist->get_total_count = elem_list_get_total_count;
- plist->get_elem_size = elem_list_get_elem_size;
- plist->get_link_offset = elem_list_get_link_offset;
- plist->add_ref = elem_list_add_ref;
- plist->release_ref = elem_list_release_ref;
- plist->get_ref = elem_list_get_ref;
-
- InitializeListHead( &plist->free_list );
-
- switch( init_flags & 0x0f )
- {
- case INIT_LIST_FLAG_ITD:
- plist->total_count = EHCI_MAX_ITDS_LIST;
- plist->elem_size = sizeof( EHCI_ITD );
- break;
- case INIT_LIST_FLAG_QH:
- plist->total_count = EHCI_MAX_QHS_LIST;
- plist->elem_size = sizeof( EHCI_QH );
- break;
- case INIT_LIST_FLAG_SITD:
- plist->total_count = EHCI_MAX_SITDS_LIST;
- plist->elem_size = sizeof( EHCI_SITD );
- break;
- case INIT_LIST_FLAG_FSTN:
- plist->total_count = EHCI_MAX_FSTNS_LIST;
- plist->elem_size = sizeof( EHCI_FSTN );
- break;
- case INIT_LIST_FLAG_QTD:
- plist->total_count = EHCI_MAX_QTDS_LIST;
- plist->elem_size = sizeof( EHCI_QTD );
- break;
- default:
- goto ERROR_OUT;
- }
- if( plist->elem_size & 0x1f )
- {
- plist->total_count = 0;
- goto ERROR_OUT;
- }
-
- plist->flags = init_flags;
- plist->parent_pool = pinit_ctx->pool;
- plist->padapter = pinit_ctx->padapter;
- pages = ( ( plist->elem_size * plist->total_count ) + ( PAGE_SIZE - 1 ) ) / PAGE_SIZE;
- elms_per_page = PAGE_SIZE / plist->elem_size;
-
- plist->phys_addrs = usb_alloc_mem( NonPagedPool,
- ( sizeof( PHYSICAL_ADDRESS ) + sizeof( PBYTE ) ) * pages + \
- sizeof( EHCI_ELEM_LINKS ) * plist->total_count );
-
- if( plist->phys_addrs == NULL )
- {
- plist->total_count = 0;
- goto ERROR_OUT;
- }
-
- plist->phys_bufs = ( PBYTE* )&plist->phys_addrs[ pages ];
- plist->elem_head_buf = ( PEHCI_ELEM_LINKS )&plist->phys_bufs[ pages ];
- RtlZeroMemory( plist->phys_addrs,
- ( sizeof( PHYSICAL_ADDRESS ) + sizeof( PBYTE ) ) * pages + \
- sizeof( EHCI_ELEM_LINKS ) * plist->total_count );
-
- for( i = 0; i < pages; i++ )
- {
- plist->phys_bufs[ i ] = HalAllocateCommonBuffer(
- plist->padapter,
- PAGE_SIZE,
- &plist->phys_addrs[ i ],
- FALSE);
-
- if( plist->phys_bufs[ i ] == NULL )
- {
- // failed, roll back
- for( j = i - 1; j >= 0; j -- )
- HalFreeCommonBuffer(
- plist->padapter,
- PAGE_SIZE,
- plist->phys_addrs[ j ],
- plist->phys_bufs[ j ],
- FALSE );
- goto ERROR_OUT;
- }
- RtlZeroMemory( plist->phys_bufs[ i ], PAGE_SIZE );
- for( j = 0; j < elms_per_page; j++ )
- {
- switch( init_flags & 0xf )
- {
- case INIT_LIST_FLAG_QH:
- {
- init_elem( pqh, EHCI_QH, INIT_LIST_FLAG_QH );
- break;
- }
- case INIT_LIST_FLAG_ITD:
- {
- init_elem( pitd, EHCI_ITD, INIT_LIST_FLAG_ITD );
- break;
- }
- case INIT_LIST_FLAG_QTD:
- {
- init_elem( pqtd, EHCI_QTD, INIT_LIST_FLAG_QTD );
- break;
- }
- case INIT_LIST_FLAG_SITD:
- {
- init_elem( psitd, EHCI_SITD, INIT_LIST_FLAG_SITD );
- break;
- }
- case INIT_LIST_FLAG_FSTN:
- {
- init_elem( pfstn, EHCI_FSTN, INIT_LIST_FLAG_FSTN );
- break;
- }
- default:
- TRAP();
- }
- }
- }
- return TRUE;
+ LONG pages, i, j, elms_per_page;
+ PEHCI_QH pqh;
+ PEHCI_ITD pitd;
+ PEHCI_SITD psitd;
+ PEHCI_QTD pqtd;
+ PEHCI_FSTN pfstn;
+ PINIT_ELEM_LIST_CONTEXT pinit_ctx;
+
+ if (plist == NULL || context == NULL)
+ return FALSE;
+
+ RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
+
+ pinit_ctx = context;
+
+ plist->destroy_list = elem_list_destroy_elem_list;
+ plist->get_list_head = elem_list_get_list_head;
+ plist->get_total_count = elem_list_get_total_count;
+ plist->get_elem_size = elem_list_get_elem_size;
+ plist->get_link_offset = elem_list_get_link_offset;
+ plist->add_ref = elem_list_add_ref;
+ plist->release_ref = elem_list_release_ref;
+ plist->get_ref = elem_list_get_ref;
+
+ InitializeListHead(&plist->free_list);
+
+ switch (init_flags & 0x0f)
+ {
+ case INIT_LIST_FLAG_ITD:
+ plist->total_count = EHCI_MAX_ITDS_LIST;
+ plist->elem_size = sizeof(EHCI_ITD);
+ break;
+ case INIT_LIST_FLAG_QH:
+ plist->total_count = EHCI_MAX_QHS_LIST;
+ plist->elem_size = sizeof(EHCI_QH);
+ break;
+ case INIT_LIST_FLAG_SITD:
+ plist->total_count = EHCI_MAX_SITDS_LIST;
+ plist->elem_size = sizeof(EHCI_SITD);
+ break;
+ case INIT_LIST_FLAG_FSTN:
+ plist->total_count = EHCI_MAX_FSTNS_LIST;
+ plist->elem_size = sizeof(EHCI_FSTN);
+ break;
+ case INIT_LIST_FLAG_QTD:
+ plist->total_count = EHCI_MAX_QTDS_LIST;
+ plist->elem_size = sizeof(EHCI_QTD);
+ break;
+ default:
+ goto ERROR_OUT;
+ }
+ if (plist->elem_size & 0x1f)
+ {
+ plist->total_count = 0;
+ goto ERROR_OUT;
+ }
+
+ plist->flags = init_flags;
+ plist->parent_pool = pinit_ctx->pool;
+ plist->padapter = pinit_ctx->padapter;
+ pages = ((plist->elem_size * plist->total_count) + (PAGE_SIZE - 1)) / PAGE_SIZE;
+ elms_per_page = PAGE_SIZE / plist->elem_size;
+
+ plist->phys_addrs = usb_alloc_mem(NonPagedPool,
+ (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages +
+ sizeof(EHCI_ELEM_LINKS) * plist->total_count);
+
+ if (plist->phys_addrs == NULL)
+ {
+ plist->total_count = 0;
+ goto ERROR_OUT;
+ }
+
+ plist->phys_bufs = (PBYTE *) & plist->phys_addrs[pages];
+ plist->elem_head_buf = (PEHCI_ELEM_LINKS) & plist->phys_bufs[pages];
+ RtlZeroMemory(plist->phys_addrs,
+ (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages +
+ sizeof(EHCI_ELEM_LINKS) * plist->total_count);
+
+ for(i = 0; i < pages; i++)
+ {
+ plist->phys_bufs[i] = HalAllocateCommonBuffer(plist->padapter,
+ PAGE_SIZE, &plist->phys_addrs[i], FALSE);
+
+ if (plist->phys_bufs[i] == NULL)
+ {
+ // failed, roll back
+ for(j = i - 1; j >= 0; j--)
+ HalFreeCommonBuffer(plist->padapter,
+ PAGE_SIZE, plist->phys_addrs[j], plist->phys_bufs[j], FALSE);
+ goto ERROR_OUT;
+ }
+ RtlZeroMemory(plist->phys_bufs[i], PAGE_SIZE);
+ for(j = 0; j < elms_per_page; j++)
+ {
+ switch (init_flags & 0xf)
+ {
+ case INIT_LIST_FLAG_QH:
+ {
+ init_elem(pqh, EHCI_QH, INIT_LIST_FLAG_QH);
+ break;
+ }
+ case INIT_LIST_FLAG_ITD:
+ {
+ init_elem(pitd, EHCI_ITD, INIT_LIST_FLAG_ITD);
+ break;
+ }
+ case INIT_LIST_FLAG_QTD:
+ {
+ init_elem(pqtd, EHCI_QTD, INIT_LIST_FLAG_QTD);
+ break;
+ }
+ case INIT_LIST_FLAG_SITD:
+ {
+ init_elem(psitd, EHCI_SITD, INIT_LIST_FLAG_SITD);
+ break;
+ }
+ case INIT_LIST_FLAG_FSTN:
+ {
+ init_elem(pfstn, EHCI_FSTN, INIT_LIST_FLAG_FSTN);
+ break;
+ }
+ default:
+ TRAP();
+ }
+ }
+ }
+ return TRUE;
+
ERROR_OUT:
+ if (plist->phys_addrs != NULL)
+ usb_free_mem(plist->phys_addrs);
- if( plist->phys_addrs != NULL )
- usb_free_mem( plist->phys_addrs );
-
- RtlZeroMemory( plist, sizeof( EHCI_ELEM_LIST ) );
- return FALSE;
+ RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
+ return FALSE;
}
VOID
-elem_list_destroy_elem_list(
-PEHCI_ELEM_LIST plist
-)
+elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist)
{
- LONG i, pages;
-
- if( plist == NULL )
- return;
-
- pages = ( plist->total_count * plist->elem_size + PAGE_SIZE - 1 ) / PAGE_SIZE;
- for( i = 0; i < pages; i++ )
- HalFreeCommonBuffer(
- plist->padapter,
- PAGE_SIZE,
- plist->phys_addrs[ i ],
- plist->phys_bufs[ i ],
- FALSE );
-
- usb_free_mem( plist->phys_addrs );
- RtlZeroMemory( plist, sizeof( EHCI_ELEM_LIST ) );
+ LONG i, pages;
+
+ if (plist == NULL)
+ return;
+
+ pages = (plist->total_count * plist->elem_size + PAGE_SIZE - 1) / PAGE_SIZE;
+ for(i = 0; i < pages; i++)
+ HalFreeCommonBuffer(plist->padapter, PAGE_SIZE, plist->phys_addrs[i], plist->phys_bufs[i], FALSE);
+
+ usb_free_mem(plist->phys_addrs);
+ RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
}
PLIST_ENTRY
-elem_list_get_list_head(
-PEHCI_ELEM_LIST plist
-)
+elem_list_get_list_head(PEHCI_ELEM_LIST plist)
{
- if( plist == NULL )
- return NULL;
- return &plist->free_list;
+ if (plist == NULL)
+ return NULL;
+ return &plist->free_list;
}
-LONG
-elem_list_get_total_count(
-PEHCI_ELEM_LIST plist
-)
+LONG
+elem_list_get_total_count(PEHCI_ELEM_LIST plist)
{
- if( plist == NULL )
- return 0;
- return plist->total_count;;
+ if (plist == NULL)
+ return 0;
+ return plist->total_count;;
}
-LONG
-elem_list_get_elem_size(
-PEHCI_ELEM_LIST plist
-)
+LONG
+elem_list_get_elem_size(PEHCI_ELEM_LIST plist)
{
- if( plist == NULL )
- return 0;
- return plist->elem_size;
+ if (plist == NULL)
+ return 0;
+ return plist->elem_size;
}
LONG
-elem_list_get_link_offset(
-PEHCI_ELEM_LIST plist
-)
+elem_list_get_link_offset(PEHCI_ELEM_LIST plist)
{
- if( plist == NULL )
- return 0;
+ if (plist == NULL)
+ return 0;
- return get_elem_phys_part_size( plist->flags & 0xf );
+ return get_elem_phys_part_size(plist->flags & 0xf);
}
LONG
-elem_list_add_ref(
-PEHCI_ELEM_LIST plist
-)
+elem_list_add_ref(PEHCI_ELEM_LIST plist)
{
- plist->reference++;
- return plist->reference;
+ plist->reference++;
+ return plist->reference;
}
LONG
-elem_list_release_ref(
-PEHCI_ELEM_LIST plist
-)
+elem_list_release_ref(PEHCI_ELEM_LIST plist)
{
- plist->reference--;
- return plist->reference;
+ plist->reference--;
+ return plist->reference;
}
LONG
-elem_list_get_ref(
-PEHCI_ELEM_LIST plist
-)
+elem_list_get_ref(PEHCI_ELEM_LIST plist)
{
- return plist->reference;
+ return plist->reference;
}
//
//
BOOL
-elem_pool_init_pool(
-PEHCI_ELEM_POOL pool,
-LONG flags,
-PVOID context
-)
+elem_pool_init_pool(PEHCI_ELEM_POOL pool, LONG flags, PVOID context)
{
- PADAPTER_OBJECT padapter;
- INIT_ELEM_LIST_CONTEXT init_ctx;
+ PADAPTER_OBJECT padapter;
+ INIT_ELEM_LIST_CONTEXT init_ctx;
- if( pool == NULL || context == NULL )
- return FALSE;
+ if (pool == NULL || context == NULL)
+ return FALSE;
- RtlZeroMemory( pool, sizeof( EHCI_ELEM_POOL ) );
+ RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL));
- init_ctx.pool = pool;
- init_ctx.padapter = context;
+ init_ctx.pool = pool;
+ init_ctx.padapter = context;
- pool->elem_lists[ 0 ] = usb_alloc_mem( NonPagedPool, sizeof( EHCI_ELEM_LIST ) );
+ pool->elem_lists[0] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST));
- if( pool->elem_lists[ 0 ] == NULL )
- return FALSE;
+ if (pool->elem_lists[0] == NULL)
+ return FALSE;
- if( elem_list_init_elem_list( pool->elem_lists[ 0 ], flags, &init_ctx, 0 ) == FALSE )
- {
- usb_free_mem( pool->elem_lists[ 0 ] );
- return FALSE;
- }
- pool->link_offset = pool->elem_lists[ 0 ]->get_link_offset( pool->elem_lists[ 0 ] );
- pool->free_count = pool->elem_lists[ 0 ]->get_total_count( pool->elem_lists[ 0 ] );
- pool->list_count = 1;
- pool->flags = flags;
+ if (elem_list_init_elem_list(pool->elem_lists[0], flags, &init_ctx, 0) == FALSE)
+ {
+ usb_free_mem(pool->elem_lists[0]);
+ return FALSE;
+ }
+ pool->link_offset = pool->elem_lists[0]->get_link_offset(pool->elem_lists[0]);
+ pool->free_count = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]);
+ pool->list_count = 1;
+ pool->flags = flags;
- return TRUE;
+ return TRUE;
}
LONG
-elem_pool_get_link_offset(
-PEHCI_ELEM_POOL elem_pool
-)
+elem_pool_get_link_offset(PEHCI_ELEM_POOL elem_pool)
{
- return elem_pool->link_offset;
+ return elem_pool->link_offset;
}
LONG
-elem_pool_get_total_count(
-PEHCI_ELEM_POOL elem_pool
-)
+elem_pool_get_total_count(PEHCI_ELEM_POOL elem_pool)
{
- return elem_pool->elem_lists[ 0 ]->get_total_count( elem_pool->elem_lists[ 0 ] ) * elem_pool->list_count;
+ return elem_pool->elem_lists[0]->get_total_count(elem_pool->elem_lists[0]) * elem_pool->list_count;
}
VOID
-elem_pool_destroy_pool(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_destroy_pool(PEHCI_ELEM_POOL pool)
{
- LONG i;
- if( pool == NULL )
- return;
- for( i = pool->list_count - 1; i >= 0; i-- )
- {
- pool->elem_lists[ i ]->destroy_list( pool->elem_lists[ i ] );
- usb_free_mem( pool->elem_lists[ i ] );
- pool->elem_lists[ i ] = NULL;
- }
- RtlZeroMemory( pool, sizeof( EHCI_ELEM_POOL ) );
- return;
+ LONG i;
+ if (pool == NULL)
+ return;
+ for(i = pool->list_count - 1; i >= 0; i--)
+ {
+ pool->elem_lists[i]->destroy_list(pool->elem_lists[i]);
+ usb_free_mem(pool->elem_lists[i]);
+ pool->elem_lists[i] = NULL;
+ }
+ RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL));
+ return;
}
PEHCI_ELEM_LINKS
-elem_pool_alloc_elem(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_alloc_elem(PEHCI_ELEM_POOL pool)
{
- LONG i;
- PEHCI_ELEM_LIST pel;
- PLIST_HEAD lh;
- PEHCI_ELEM_LINKS elnk;
-
- if( pool == NULL )
- return NULL;
-
- for( i = 0; i < pool->list_count; i++ )
- {
- pel = pool->elem_lists[ i ];
- if( pel->get_ref( pel ) == pel->get_total_count( pel ) )
- continue;
- break;
- }
- if( i == pool->list_count )
- {
- if( elem_pool_expand_pool( pool, pel->get_total_count( pel ) ) == FALSE )
- return NULL;
- pel = pool->elem_lists[ i ];
- }
-
- lh = pel->get_list_head( pel );
- elnk = ( PEHCI_ELEM_LINKS )RemoveHeadList( lh );
- InitializeListHead( &elnk->elem_link );
- InitializeListHead( &elnk->sched_link );
-
- pel->add_ref( pel );
- pool->free_count--;
-
- return elnk;
+ LONG i;
+ PEHCI_ELEM_LIST pel;
+ PLIST_HEAD lh;
+ PEHCI_ELEM_LINKS elnk;
+
+ if (pool == NULL)
+ return NULL;
+
+ for(i = 0; i < pool->list_count; i++)
+ {
+ pel = pool->elem_lists[i];
+ if (pel->get_ref(pel) == pel->get_total_count(pel))
+ continue;
+ break;
+ }
+ if (i == pool->list_count)
+ {
+ if (elem_pool_expand_pool(pool, pel->get_total_count(pel)) == FALSE)
+ return NULL;
+ pel = pool->elem_lists[i];
+ }
+
+ lh = pel->get_list_head(pel);
+ elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(lh);
+ InitializeListHead(&elnk->elem_link);
+ InitializeListHead(&elnk->sched_link);
+
+ pel->add_ref(pel);
+ pool->free_count--;
+
+ return elnk;
}
VOID
-elem_pool_free_elem(
-PEHCI_ELEM_LINKS elem_link
-)
+elem_pool_free_elem(PEHCI_ELEM_LINKS elem_link)
{
- PLIST_HEAD lh;
- LONG ref;
- PEHCI_ELEM_POOL pool;
- if( elem_link == NULL )
- return;
- pool = elem_link->pool_link;
- lh = elem_link->list_link->get_list_head( elem_link->list_link );
- if( lh == NULL )
- return;
- InsertHeadList( lh, ( PLIST_ENTRY )elem_link );
- ref = elem_link->list_link->release_ref( elem_link->list_link );
- pool->free_count++;
- if( ref == 0 )
- elem_pool_collect_garbage( pool );
- return;
+ PLIST_HEAD lh;
+ LONG ref;
+ PEHCI_ELEM_POOL pool;
+ if (elem_link == NULL)
+ return;
+ pool = elem_link->pool_link;
+ lh = elem_link->list_link->get_list_head(elem_link->list_link);
+ if (lh == NULL)
+ return;
+ InsertHeadList(lh, (PLIST_ENTRY) elem_link);
+ ref = elem_link->list_link->release_ref(elem_link->list_link);
+ pool->free_count++;
+ if (ref == 0)
+ elem_pool_collect_garbage(pool);
+ return;
}
BOOL
-elem_pool_is_empty(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_is_empty(PEHCI_ELEM_POOL pool)
{
- PEHCI_ELEM_LIST pel;
+ PEHCI_ELEM_LIST pel;
- if( pool == NULL )
- return TRUE;
- pel = pool->elem_lists[ 0 ];
- return ( pool->list_count == 1 && pool->free_count == pel->get_total_count( pel ) );
+ if (pool == NULL)
+ return TRUE;
+ pel = pool->elem_lists[0];
+ return (pool->list_count == 1 && pool->free_count == pel->get_total_count(pel));
}
LONG
-elem_pool_get_free_count(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_get_free_count(PEHCI_ELEM_POOL pool)
{
- if( pool == NULL )
- return 0;
- return pool->free_count;
+ if (pool == NULL)
+ return 0;
+ return pool->free_count;
}
PEHCI_ELEM_LINKS
-elem_pool_alloc_elems(
-PEHCI_ELEM_POOL pool,
-LONG count
-)
+elem_pool_alloc_elems(PEHCI_ELEM_POOL pool, LONG count)
{
- LIST_HEAD lh;
- PLIST_ENTRY pthis;
- LONG i, alloc_count, max_pool_lists;
- PEHCI_ELEM_LIST pel;
- PEHCI_ELEM_LINKS elnk;
- // calculate to see if the count is affordable
-
- if( pool == NULL || count <= 0 )
- return NULL;
-
- get_max_lists_count( pool, max_pool_lists );
- InitializeListHead( &lh );
- pel = pool->elem_lists[ 0 ];
- if( count <= pool->free_count )
- alloc_count = 0;
- else
- alloc_count = count - pool->free_count;
-
- if( alloc_count > pel->get_total_count( pel ) * ( max_pool_lists - pool->list_count ) )
- return NULL;
-
- for( i = 0; i < count; i++ )
- {
- if( ( elnk = elem_pool_alloc_elem( pool ) ) == NULL )
- {
- // undo what we have done
- while( IsListEmpty( &lh ) == FALSE )
- {
- pthis = RemoveHeadList( &lh );
- elnk = struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link );
- elem_pool_free_elem( elnk );
- }
- return NULL;
- }
- InsertTailList( &lh, &elnk->elem_link );
- }
- ListFirst( &lh, pthis );
- elnk = struct_ptr( pthis, EHCI_ELEM_LINKS, elem_link );
- RemoveEntryList( &lh );
- return elnk;
+ LIST_HEAD lh;
+ PLIST_ENTRY pthis;
+ LONG i, alloc_count, max_pool_lists;
+ PEHCI_ELEM_LIST pel;
+ PEHCI_ELEM_LINKS elnk;
+ // calculate to see if the count is affordable
+
+ if (pool == NULL || count <= 0)
+ return NULL;
+
+ get_max_lists_count(pool, max_pool_lists);
+ InitializeListHead(&lh);
+ pel = pool->elem_lists[0];
+ if (count <= pool->free_count)
+ alloc_count = 0;
+ else
+ alloc_count = count - pool->free_count;
+
+ if (alloc_count > pel->get_total_count(pel) * (max_pool_lists - pool->list_count))
+ return NULL;
+
+ for(i = 0; i < count; i++)
+ {
+ if ((elnk = elem_pool_alloc_elem(pool)) == NULL)
+ {
+ // undo what we have done
+ while (IsListEmpty(&lh) == FALSE)
+ {
+ pthis = RemoveHeadList(&lh);
+ elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link);
+ elem_pool_free_elem(elnk);
+ }
+ return NULL;
+ }
+ InsertTailList(&lh, &elnk->elem_link);
+ }
+ ListFirst(&lh, pthis);
+ elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link);
+ RemoveEntryList(&lh);
+ return elnk;
}
BOOL
-elem_pool_free_elems(
-PEHCI_ELEM_LINKS elem_chains
-)
+elem_pool_free_elems(PEHCI_ELEM_LINKS elem_chains)
{
- // note: no list head exists.
- LIST_HEAD lh;
- PEHCI_ELEM_LINKS elnk;
-
- InsertTailList( &elem_chains->elem_link, &lh );
- while( IsListEmpty( &lh ) == FALSE )
- {
- elnk = ( PEHCI_ELEM_LINKS )RemoveHeadList( &lh );
- elem_pool_free_elem( elnk );
- }
- return TRUE;
+ // note: no list head exists.
+ LIST_HEAD lh;
+ PEHCI_ELEM_LINKS elnk;
+
+ InsertTailList(&elem_chains->elem_link, &lh);
+ while (IsListEmpty(&lh) == FALSE)
+ {
+ elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(&lh);
+ elem_pool_free_elem(elnk);
+ }
+ return TRUE;
}
+
LONG
-elem_pool_get_type(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_get_type(PEHCI_ELEM_POOL pool)
{
- if( pool == NULL )
- return -1;
- return ( pool->flags & 0xf );
+ if (pool == NULL)
+ return -1;
+ return (pool->flags & 0xf);
}
BOOL
-elem_pool_expand_pool(
-PEHCI_ELEM_POOL pool,
-LONG elem_count
-)
+elem_pool_expand_pool(PEHCI_ELEM_POOL pool, LONG elem_count)
{
- LONG elem_cnt_list, list_count, i, j;
- INIT_ELEM_LIST_CONTEXT init_ctx;
-
- if( pool == NULL || elem_count <= 0 || elem_count > EHCI_MAX_ELEMS_POOL )
- return FALSE;
-
- init_ctx.pool = pool;
- init_ctx.padapter = pool->elem_lists[ 0 ]->padapter;
-
- elem_cnt_list = pool->elem_lists[ 0 ]->get_total_count( pool->elem_lists[ 0 ] );
- list_count = ( elem_count + elem_cnt_list - 1 ) / elem_cnt_list;
- get_max_lists_count( pool, i );
-
- if( list_count + pool->list_count > i )
- return FALSE;
-
- for( i = pool->list_count; i < list_count + pool->list_count; i++ )
- {
- pool->elem_lists[ i ] = usb_alloc_mem( NonPagedPool, sizeof( EHCI_ELEM_LIST ) );
- if( elem_list_init_elem_list( pool->elem_lists[ i ], pool->flags, &init_ctx, 0 ) == FALSE )
- break;
- }
-
- if( i < list_count + pool->list_count )
- {
- // undo all we have done
- for( j = pool->list_count; j < pool->list_count + i; j++ )
- {
- pool->elem_lists[ j ]->destroy_list( pool->elem_lists[ j ] );
- usb_free_mem( pool->elem_lists[ j ] );
- pool->elem_lists[ j ] = NULL;
- }
- return FALSE;
- }
-
- // update pool
- pool->free_count += elem_cnt_list * list_count;
- pool->list_count += list_count;
- return TRUE;
+ LONG elem_cnt_list, list_count, i, j;
+ INIT_ELEM_LIST_CONTEXT init_ctx;
+
+ if (pool == NULL || elem_count <= 0 || elem_count > EHCI_MAX_ELEMS_POOL)
+ return FALSE;
+
+ init_ctx.pool = pool;
+ init_ctx.padapter = pool->elem_lists[0]->padapter;
+
+ elem_cnt_list = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]);
+ list_count = (elem_count + elem_cnt_list - 1) / elem_cnt_list;
+ get_max_lists_count(pool, i);
+
+ if (list_count + pool->list_count > i)
+ return FALSE;
+
+ for(i = pool->list_count; i < list_count + pool->list_count; i++)
+ {
+ pool->elem_lists[i] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST));
+ if (elem_list_init_elem_list(pool->elem_lists[i], pool->flags, &init_ctx, 0) == FALSE)
+ break;
+ }
+
+ if (i < list_count + pool->list_count)
+ {
+ // undo all we have done
+ for(j = pool->list_count; j < pool->list_count + i; j++)
+ {
+ pool->elem_lists[j]->destroy_list(pool->elem_lists[j]);
+ usb_free_mem(pool->elem_lists[j]);
+ pool->elem_lists[j] = NULL;
+ }
+ return FALSE;
+ }
+
+ // update pool
+ pool->free_count += elem_cnt_list * list_count;
+ pool->list_count += list_count;
+ return TRUE;
}
BOOL
-elem_pool_collect_garbage(
-PEHCI_ELEM_POOL pool
-)
+elem_pool_collect_garbage(PEHCI_ELEM_POOL pool)
{
- LONG i, j, k, fl;
- LONG free_elem_lists[ EHCI_MAX_LISTS_POOL - 1 ];
- PEHCI_ELEM_LIST pel;
-
- if( pool == NULL )
- return FALSE;
-
- for( i = 1, fl = 0; i < pool->list_count; i++ )
- {
- if( pool->elem_lists[ i ]->get_ref( pool->elem_lists[ i ] ) == 0 )
- {
- free_elem_lists[ fl++ ] = i;
- }
- }
- for( j = fl - 1; j >= 0; j-- )
- {
- pel = pool->elem_lists[ free_elem_lists[ j ] ];
- pel->destroy_list( pel );
- usb_free_mem( pel );
-
- for( k = free_elem_lists[ j ] + 1; k < pool->list_count; k++ )
- {
- // shrink the elem_lists
- pool->elem_lists[ k - 1 ] = pool->elem_lists[ k ];
- }
- pool->elem_lists[ k ] = NULL;
- pel = pool->elem_lists[ 0 ];
- pool->free_count -= pel->get_total_count( pel );
- pool->list_count --;
- }
- return TRUE;
+ LONG i, j, k, fl;
+ LONG free_elem_lists[EHCI_MAX_LISTS_POOL - 1];
+ PEHCI_ELEM_LIST pel;
+
+ if (pool == NULL)
+ return FALSE;
+
+ for(i = 1, fl = 0; i < pool->list_count; i++)
+ {
+ if (pool->elem_lists[i]->get_ref(pool->elem_lists[i]) == 0)
+ {
+ free_elem_lists[fl++] = i;
+ }
+ }
+ for(j = fl - 1; j >= 0; j--)
+ {
+ pel = pool->elem_lists[free_elem_lists[j]];
+ pel->destroy_list(pel);
+ usb_free_mem(pel);
+
+ for(k = free_elem_lists[j] + 1; k < pool->list_count; k++)
+ {
+ // shrink the elem_lists
+ pool->elem_lists[k - 1] = pool->elem_lists[k];
+ }
+ pool->elem_lists[k] = NULL;
+ pel = pool->elem_lists[0];
+ pool->free_count -= pel->get_total_count(pel);
+ pool->list_count--;
+ }
+ return TRUE;
}
BOOL
-elem_pool_can_transfer(
-PEHCI_ELEM_POOL pool,
-LONG td_count
-)
+elem_pool_can_transfer(PEHCI_ELEM_POOL pool, LONG td_count)
{
- LONG i;
- if( pool == NULL || td_count <= 0 )
- return FALSE;
- get_max_lists_count( pool, i );
- if( ( i - pool->list_count )
- * pool->elem_lists[ 0 ]->get_total_count( pool->elem_lists[ 0 ] )
- + pool->free_count < td_count )
- return FALSE;
- return TRUE;
+ LONG i;
+ if (pool == NULL || td_count <= 0)
+ return FALSE;
+ get_max_lists_count(pool, i);
+ if ((i - pool->list_count)
+ * pool->elem_lists[0]->get_total_count(pool->elem_lists[0]) + pool->free_count < td_count)
+ return FALSE;
+ return TRUE;
}
//----------------------------------------------------------
-
#include "stdio.h"
#define if_dev( dev_obj ) \
-( ( ( ( PGENDRV_DEVICE_EXTENSION)dev_obj->DeviceExtension )->pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) != 0 )
+( ( ( ( PGENDRV_DEVICE_EXTENSION)dev_obj->DeviceExtension )->pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) != 0 )
#define GENDRV_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \
{\
extern POBJECT_TYPE NTSYSAPI IoDriverObjectType;
-extern VOID
-disp_urb_completion(
-PURB purb,
-PVOID context
-);
+extern VOID disp_urb_completion(PURB purb, PVOID context);
-VOID
-disp_noio_urb_completion(
-PURB purb,
-PVOID context
-);
+VOID disp_noio_urb_completion(PURB purb, PVOID context);
-NTSYSAPI
-NTSTATUS
-NTAPI
-ZwLoadDriver(
-IN PUNICODE_STRING DriverServiceName
-);
+NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);
-NTSYSAPI
-NTSTATUS
-NTAPI
-ZwClose(
-IN HANDLE Handle
-);
+NTSYSAPI NTSTATUS NTAPI ZwClose(IN HANDLE Handle);
NTSYSAPI
NTSTATUS
NTAPI
-ObOpenObjectByName(
-IN POBJECT_ATTRIBUTES ObjectAttributes,
-IN POBJECT_TYPE ObjectType OPTIONAL,
-IN KPROCESSOR_MODE AccessMode,
-IN OUT PACCESS_STATE AccessState OPTIONAL,
-IN ACCESS_MASK DesiredAccess OPTIONAL,
-IN OUT PVOID ParseContext OPTIONAL,
-OUT PHANDLE Handle
-);
+ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN POBJECT_TYPE ObjectType OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN OUT PACCESS_STATE AccessState OPTIONAL,
+ IN ACCESS_MASK DesiredAccess OPTIONAL,
+ IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle);
-BOOL
-gendrv_if_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-);
+BOOL gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
-VOID
-gendrv_set_cfg_completion(
-PURB purb,
-PVOID context
-);
+VOID gendrv_set_cfg_completion(PURB purb, PVOID context);
-BOOL
-gendrv_connect(
-PCONNECT_DATA param,
-DEV_HANDLE dev_handle
-);
+BOOL gendrv_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle);
-BOOL
-gendrv_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-BOOL
-gendrv_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-VOID
-gendrv_startio(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-);
+VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
-VOID
-gendrv_cancel_queued_irp(
-PDEVICE_OBJECT pdev_obj,
-PIRP pirp
-);
+VOID gendrv_cancel_queued_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp);
-VOID
-gendrv_release_ext_drvr_entry(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-PGENDRV_EXT_DRVR_ENTRY pentry
-);
+VOID gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry);
-VOID
-gendrv_clean_up_queued_irps(
-PDEVICE_OBJECT dev_obj
-);
+VOID gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj);
-PGENDRV_EXT_DRVR_ENTRY
-gendrv_alloc_ext_drvr_entry(
-PGENDRV_DRVR_EXTENSION pdrvr_ext
-);
+PGENDRV_EXT_DRVR_ENTRY gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext);
-PDRIVER_OBJECT
-gendrv_open_ext_driver(
-PUNICODE_STRING unicode_string
-);
+PDRIVER_OBJECT gendrv_open_ext_driver(PUNICODE_STRING unicode_string);
NTSTATUS
-gendrv_get_key_value(
-IN HANDLE KeyHandle,
-IN PWSTR ValueName,
-OUT PKEY_VALUE_FULL_INFORMATION *Information
-);
+gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information);
NTSTATUS
-gendrv_open_reg_key(
-OUT PHANDLE handle,
-IN HANDLE base_handle OPTIONAL,
-IN PUNICODE_STRING keyname,
-IN ACCESS_MASK desired_access,
-IN BOOLEAN create
-);
+gendrv_open_reg_key(OUT PHANDLE handle,
+ IN HANDLE base_handle OPTIONAL,
+ IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create);
-BOOL
-gendrv_do_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle,
-BOOL is_if
-);
+BOOL gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOL is_if);
-BOOL
-gendrv_do_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle,
-BOOL is_if
-);
+BOOL gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOL is_if);
-NTSTATUS
-gendrv_send_pnp_msg(
-ULONG msg,
-PDEVICE_OBJECT pdev_obj,
-PVOID pctx
-);
+NTSTATUS gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx);
-BOOL
-gendrv_delete_device(
-PUSB_DEV_MANAGER dev_mgr,
-PDEVICE_OBJECT dev_obj
-);
+BOOL gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj);
-PDEVICE_OBJECT
-gendrv_create_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER gen_drvr,
-DEV_HANDLE dev_handle
-);
+PDEVICE_OBJECT gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle);
-PDRIVER_OBJECT
-gendrv_load_ext_drvr(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-PUSB_DESC_HEADER pdesc
-);
+PDRIVER_OBJECT gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc);
-PDRIVER_OBJECT
-gendrv_find_drvr_by_key(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-ULONG key
-);
+PDRIVER_OBJECT gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key);
-ULONG
-gendrv_make_key(
-PUSB_DESC_HEADER pdesc
-);
+ULONG gendrv_make_key(PUSB_DESC_HEADER pdesc);
BOOL
-gendrv_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+gendrv_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
- 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 = 0xff; // Interface Class
- pdriver->driver_desc.if_sub_class = 0xff; // Interface SubClass
- pdriver->driver_desc.if_protocol = 0xff; // Interface Protocol
+ pdriver->driver_desc.config_val = 0; // Configuration Value
+ pdriver->driver_desc.if_num = 0; // Interface Number
+ pdriver->driver_desc.if_class = 0xff; // Interface Class
+ pdriver->driver_desc.if_sub_class = 0xff; // Interface SubClass
+ pdriver->driver_desc.if_protocol = 0xff; // Interface Protocol
- pdriver->driver_desc.driver_name = "USB generic dev driver"; // Driver name for Name Registry
- pdriver->driver_desc.dev_class = USB_CLASS_VENDOR_SPEC;
- pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
- pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
+ pdriver->driver_desc.driver_name = "USB generic dev driver"; // Driver name for Name Registry
+ pdriver->driver_desc.dev_class = USB_CLASS_VENDOR_SPEC;
+ pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
+ pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
- pdriver->driver_ext = usb_alloc_mem( NonPagedPool, sizeof( GENDRV_DRVR_EXTENSION ) );
- pdriver->driver_ext_size = sizeof( GENDRV_DRVR_EXTENSION );
+ pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION));
+ pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION);
- RtlZeroMemory( pdriver->driver_ext, pdriver->driver_ext_size );
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdriver->driver_ext;
+ RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size);
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
- // InitializeListHead( &pdrvr_ext->dev_list );
- InitializeListHead( &pdrvr_ext->ext_drvr_list );
- pdrvr_ext->ext_drvr_count = 0;
- ExInitializeFastMutex( &pdrvr_ext->drvr_ext_mutex );
+ // InitializeListHead( &pdrvr_ext->dev_list );
+ InitializeListHead(&pdrvr_ext->ext_drvr_list);
+ pdrvr_ext->ext_drvr_count = 0;
+ ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex);
- pdriver->disp_tbl.version = 1;
- pdriver->disp_tbl.dev_connect = gendrv_connect;
- pdriver->disp_tbl.dev_disconnect = gendrv_disconnect;
- pdriver->disp_tbl.dev_stop = gendrv_stop;
- pdriver->disp_tbl.dev_reserved = NULL;
+ pdriver->disp_tbl.version = 1;
+ pdriver->disp_tbl.dev_connect = gendrv_connect;
+ pdriver->disp_tbl.dev_disconnect = gendrv_disconnect;
+ pdriver->disp_tbl.dev_stop = gendrv_stop;
+ pdriver->disp_tbl.dev_reserved = NULL;
- return TRUE;
+ return TRUE;
}
BOOL
-gendrv_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+gendrv_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- return gendrv_if_driver_destroy( dev_mgr, pdriver );
+ return gendrv_if_driver_destroy(dev_mgr, pdriver);
}
BOOL
-gendrv_connect(
-PCONNECT_DATA param,
-DEV_HANDLE dev_handle
-)
+gendrv_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle)
{
- PURB purb;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- PUCHAR buf;
- LONG i;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_DEV_MANAGER dev_mgr;
-
- if( param == NULL || dev_handle == 0 )
- return FALSE;
-
- dev_mgr = param->dev_mgr;
-
- // 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, ( "gendrv_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;
-
- status = usb_submit_urb( dev_mgr, purb );
- if( status == STATUS_PENDING )
- {
- TRAP();
- usb_free_mem( buf );
- usb_free_mem( purb );
- return FALSE;
- }
-
- // check the config desc valid
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )buf;
- if( pconfig_desc->wTotalLength > 512 )
- {
- usb_free_mem( buf );
- usb_free_mem( purb );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_connect(): error, bad configuration desc\n" ) );
- return FALSE;
- }
-
- i = pconfig_desc->bConfigurationValue;
- usb_free_mem( buf );
- buf = NULL;
-
- //set the configuration
- urb_init( purb );
- purb->endp_handle = dev_handle | 0xffff;
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->completion = gendrv_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, ( "gendrv_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_SUCCESS )
- return TRUE;
-
- return FALSE;
- }
-
- return TRUE;
+ PURB purb;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ PUCHAR buf;
+ LONG i;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+ PUSB_DEV_MANAGER dev_mgr;
+
+ if (param == NULL || dev_handle == 0)
+ return FALSE;
+
+ dev_mgr = param->dev_mgr;
+
+ // 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, ("gendrv_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;
+
+ status = usb_submit_urb(dev_mgr, purb);
+ if (status == STATUS_PENDING)
+ {
+ TRAP();
+ usb_free_mem(buf);
+ usb_free_mem(purb);
+ return FALSE;
+ }
+
+ // check the config desc valid
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) buf;
+ if (pconfig_desc->wTotalLength > 512)
+ {
+ usb_free_mem(buf);
+ usb_free_mem(purb);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): error, bad configuration desc\n"));
+ return FALSE;
+ }
+
+ i = pconfig_desc->bConfigurationValue;
+ usb_free_mem(buf);
+ buf = NULL;
+
+ //set the configuration
+ urb_init(purb);
+ purb->endp_handle = dev_handle | 0xffff;
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->completion = gendrv_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, ("gendrv_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_SUCCESS)
+ return TRUE;
+
+ return FALSE;
+ }
+
+ return TRUE;
}
BOOL
-gendrv_event_select_driver(
-PUSB_DEV pdev, //always null. we do not use this param
-ULONG event,
-ULONG context,
-ULONG param
-)
+gendrv_event_select_driver(PUSB_DEV pdev, //always null. we do not use this param
+ ULONG event, ULONG context, ULONG param)
{
- //
- // try to search the registry to find one driver.
- // if found, create the PDO, load the driver.
- // and call its AddDevice.
- //
- LONG i;
- PUSB_DRIVER pdrvr;
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- PGENDRV_EXT_DRVR_ENTRY pentry;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_DEV_MANAGER dev_mgr;
-
- PDEVICE_OBJECT pdev_obj;
- PDRIVER_OBJECT pdrvr_obj;
- PLIST_ENTRY pthis, pnext;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( pdev == NULL )
- return FALSE;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_event_select_driver(): entering...\n" ) );
-
- pdrvr = ( PUSB_DRIVER )param;
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )pdev->desc_buf[ sizeof( USB_DEVICE_DESC ) ];
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdrvr->driver_ext;
-
- //
- // well, let's do the hard work to see if there is a class driver
- // for this device.
- // in the event routine, we have no need to check if the device is zomb or
- // not, it must be alive there.
- //
- i = gendrv_make_key( ( PUSB_DESC_HEADER )pdev->pusb_dev_desc );
- if( i == -1 )
- {
- return FALSE;
- }
-
- pdrvr_obj = gendrv_find_drvr_by_key( pdrvr_ext, ( ULONG )i );
- if( !pdrvr_obj )
- {
- if( ( pdrvr_obj = gendrv_load_ext_drvr( pdrvr_ext, ( PUSB_DESC_HEADER )pdev->pusb_dev_desc ) ) == NULL )
- return FALSE;
- }
-
- dev_mgr = dev_mgr_from_dev( pdev );
- pdev_obj = gendrv_create_device( dev_mgr, pdrvr, usb_make_handle( pdev->dev_id, 0, 0 ) );
- if( pdev_obj == NULL )
- {
- goto ERROR_OUT;
- }
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB ||
- dev_mgr_set_driver( dev_mgr, usb_make_handle( pdev->dev_id, 0, 0 ), pdrvr, pdev ) == FALSE )
- {
- unlock_dev( pdev, FALSE );
- gendrv_delete_device( dev_mgr, pdev_obj );
- goto ERROR_OUT;
- }
-
- if( pdev->usb_config )
- {
- pdev->dev_obj = pdev_obj;
- }
-
- unlock_dev( pdev, FALSE );
-
- pdev_ext = ( PGENDRV_DEVICE_EXTENSION )pdev_obj->DeviceExtension;
- pdev_ext->desc_buf = usb_alloc_mem( NonPagedPool, 512 );
- RtlCopyMemory( pdev_ext->desc_buf, pconfig_desc, 512 );
-
- // insert the device to the dev_list
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ListFirst( &pdrvr_ext->ext_drvr_list, pthis );
- pentry = NULL;
- while( pthis )
- {
- pentry = ( PGENDRV_EXT_DRVR_ENTRY )pthis;
- if( pentry->pext_drvr == pdrvr_obj )
- break;
- ListNext( &pdrvr_ext->ext_drvr_list, pthis, pnext );
- pthis = pnext;
- pentry = NULL;
- }
- ASSERT( pentry );
- InsertTailList( &pentry->dev_list, &pdev_ext->dev_obj_link );
- pdev_ext->ext_drvr_entry = pentry;
- pentry->ref_count++;
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- // notify the class driver, some device comes
- gendrv_send_pnp_msg( GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj );
- usb_unlock_dev( pdev );
- return TRUE;
+ //
+ // try to search the registry to find one driver.
+ // if found, create the PDO, load the driver.
+ // and call its AddDevice.
+ //
+ LONG i;
+ PUSB_DRIVER pdrvr;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+ PUSB_DEV_MANAGER dev_mgr;
-ERROR_OUT:
+ PDEVICE_OBJECT pdev_obj;
+ PDRIVER_OBJECT pdrvr_obj;
+ PLIST_ENTRY pthis, pnext;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (pdev == NULL)
+ return FALSE;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_event_select_driver(): entering...\n"));
+
+ pdrvr = (PUSB_DRIVER) param;
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
+
+ //
+ // well, let's do the hard work to see if there is a class driver
+ // for this device.
+ // in the event routine, we have no need to check if the device is zomb or
+ // not, it must be alive there.
+ //
+ i = gendrv_make_key((PUSB_DESC_HEADER) pdev->pusb_dev_desc);
+ if (i == -1)
+ {
+ return FALSE;
+ }
+
+ pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i);
+ if (!pdrvr_obj)
+ {
+ if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pdev->pusb_dev_desc)) == NULL)
+ return FALSE;
+ }
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ pdev_obj = gendrv_create_device(dev_mgr, pdrvr, usb_make_handle(pdev->dev_id, 0, 0));
+ if (pdev_obj == NULL)
+ {
+ goto ERROR_OUT;
+ }
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
+ dev_mgr_set_driver(dev_mgr, usb_make_handle(pdev->dev_id, 0, 0), pdrvr, pdev) == FALSE)
+ {
+ unlock_dev(pdev, FALSE);
+ gendrv_delete_device(dev_mgr, pdev_obj);
+ goto ERROR_OUT;
+ }
+
+ if (pdev->usb_config)
+ {
+ pdev->dev_obj = pdev_obj;
+ }
+
+ unlock_dev(pdev, FALSE);
+
+ pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
+ pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512);
+ RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512);
+
+ // insert the device to the dev_list
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
+ pentry = NULL;
+ while (pthis)
+ {
+ pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
+ if (pentry->pext_drvr == pdrvr_obj)
+ break;
+ ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
+ pthis = pnext;
+ pentry = NULL;
+ }
+ ASSERT(pentry);
+ InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link);
+ pdev_ext->ext_drvr_entry = pentry;
+ pentry->ref_count++;
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ // notify the class driver, some device comes
+ gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj);
+ usb_unlock_dev(pdev);
+ return TRUE;
- usb_unlock_dev( pdev );
- return FALSE;
+ ERROR_OUT:
+
+ usb_unlock_dev(pdev);
+ return FALSE;
}
VOID
-gendrv_set_cfg_completion(
-PURB purb,
-PVOID context
-)
+gendrv_set_cfg_completion(PURB purb, PVOID context)
{
- DEV_HANDLE dev_handle;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DRIVER pdriver;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_EVENT pevent;
- USE_BASIC_NON_PENDING_IRQL;
-
- if( purb == NULL || context == NULL )
- return;
-
- 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;
- }
-
- usb_free_mem( purb );
- purb = NULL;
-
- // set the dev state
- status = usb_query_and_lock_dev( dev_mgr, purb->endp_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- usb_unlock_dev( pdev );
- return;
- }
- usb_unlock_dev( pdev ); // safe to release the pdev ref since we are in urb completion
-
-
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) >= USB_DEV_STATE_BEFORE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- return;
- }
-
- if( dev_mgr_set_driver( dev_mgr, dev_handle, pdriver, pdev ) == FALSE )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- return;
- }
-
- //transit the state to configured
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_CONFIGURED;
-
- pevent = alloc_event( &dev_mgr->event_pool, 1 );
- if( pevent == NULL )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- }
-
- pevent->flags = USB_EVENT_FLAG_ACTIVE;
- pevent->event = USB_EVENT_DEFAULT;
- pevent->pdev = pdev;
- pevent->context = 0;
- pevent->param = ( ULONG )pdriver;
- pevent->pnext = 0; //vertical queue for serialized operation
- pevent->process_event = (PROCESS_EVENT)gendrv_event_select_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 );
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
-
- return;
+ DEV_HANDLE dev_handle;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DRIVER pdriver;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_EVENT pevent;
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (purb == NULL || context == NULL)
+ return;
+
+ 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;
+ }
+
+ usb_free_mem(purb);
+ purb = NULL;
+
+ // set the dev state
+ status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ usb_unlock_dev(pdev);
+ return;
+ }
+ usb_unlock_dev(pdev); // safe to release the pdev ref since we are in urb completion
+
+
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ return;
+ }
+
+ if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ return;
+ }
+
+ //transit the state to configured
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_CONFIGURED;
+
+ pevent = alloc_event(&dev_mgr->event_pool, 1);
+ if (pevent == NULL)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ }
+
+ pevent->flags = USB_EVENT_FLAG_ACTIVE;
+ pevent->event = USB_EVENT_DEFAULT;
+ pevent->pdev = pdev;
+ pevent->context = 0;
+ pevent->param = (ULONG) pdriver;
+ pevent->pnext = 0; //vertical queue for serialized operation
+ pevent->process_event = (PROCESS_EVENT) gendrv_event_select_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);
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+
+ return;
}
BOOL
-gendrv_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- if( dev_mgr == NULL )
- return FALSE;
- return gendrv_do_stop( dev_mgr, dev_handle, FALSE );
+ if (dev_mgr == NULL)
+ return FALSE;
+ return gendrv_do_stop(dev_mgr, dev_handle, FALSE);
}
BOOL
-gendrv_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- if( dev_mgr == NULL )
- return FALSE;
- return gendrv_do_disconnect( dev_mgr, dev_handle, FALSE );
+ if (dev_mgr == NULL)
+ return FALSE;
+ return gendrv_do_disconnect(dev_mgr, dev_handle, FALSE);
}
BOOL
-gendrv_build_reg_string(
-PUSB_DESC_HEADER pdesc,
-PUNICODE_STRING pus
-)
+gendrv_build_reg_string(PUSB_DESC_HEADER pdesc, PUNICODE_STRING pus)
{
- CHAR desc_str[ 128 ];
- STRING atemp;
-
- if( pdesc == NULL || pus == NULL )
- return FALSE;
-
- if( pdesc->bDescriptorType == USB_DT_DEVICE )
- {
- PUSB_DEVICE_DESC pdev_desc;
- pdev_desc = ( PUSB_DEVICE_DESC )pdesc;
- sprintf( desc_str, "%sv_%04x&p_%04x",
- "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\",
- pdev_desc->idVendor,
- pdev_desc->idProduct );
- }
- else if( pdesc->bDescriptorType == USB_DT_INTERFACE )
- {
- PUSB_INTERFACE_DESC pif_desc;
- pif_desc = ( PUSB_INTERFACE_DESC )pdesc;
- sprintf( desc_str, "%sc_%04x&s_%04x&p_%04x",
- "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\",
- pif_desc->bInterfaceClass,
- pif_desc->bInterfaceSubClass,
- pif_desc->bInterfaceProtocol );
- }
- else
- return FALSE;
-
- RtlInitString( &atemp, desc_str );
- RtlAnsiStringToUnicodeString( pus, &atemp, TRUE );
- return TRUE;
+ CHAR desc_str[128];
+ STRING atemp;
+
+ if (pdesc == NULL || pus == NULL)
+ return FALSE;
+
+ if (pdesc->bDescriptorType == USB_DT_DEVICE)
+ {
+ PUSB_DEVICE_DESC pdev_desc;
+ pdev_desc = (PUSB_DEVICE_DESC) pdesc;
+ sprintf(desc_str, "%sv_%04x&p_%04x",
+ "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\",
+ pdev_desc->idVendor, pdev_desc->idProduct);
+ }
+ else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
+ {
+ PUSB_INTERFACE_DESC pif_desc;
+ pif_desc = (PUSB_INTERFACE_DESC) pdesc;
+ sprintf(desc_str, "%sc_%04x&s_%04x&p_%04x",
+ "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\",
+ pif_desc->bInterfaceClass, pif_desc->bInterfaceSubClass, pif_desc->bInterfaceProtocol);
+ }
+ else
+ return FALSE;
+
+ RtlInitString(&atemp, desc_str);
+ RtlAnsiStringToUnicodeString(pus, &atemp, TRUE);
+ return TRUE;
}
ULONG
-gendrv_make_key(
-PUSB_DESC_HEADER pdesc
-)
+gendrv_make_key(PUSB_DESC_HEADER pdesc)
{
- PUSB_DEVICE_DESC pdev_desc;
- PUSB_INTERFACE_DESC pif_desc;
-
- if( pdesc == NULL )
- return ( ULONG )-1;
- if( pdesc->bDescriptorType == USB_DT_DEVICE )
- {
- pdev_desc = ( PUSB_DEVICE_DESC )pdesc;
- return ( ( ( ( ULONG )pdev_desc->idVendor ) << 16 ) | pdev_desc->idProduct );
- }
- else if( pdesc->bDescriptorType == USB_DT_INTERFACE )
- {
- pif_desc = ( PUSB_INTERFACE_DESC )pdesc;
- return ( ( ( ( ULONG )pif_desc->bInterfaceClass ) << 16 ) | \
- ( ( ( ULONG )pif_desc->bInterfaceSubClass ) << 8 ) | \
- ( ( ULONG )pif_desc->bInterfaceProtocol ) );
- }
- return ( ULONG )-1;
+ PUSB_DEVICE_DESC pdev_desc;
+ PUSB_INTERFACE_DESC pif_desc;
+
+ if (pdesc == NULL)
+ return (ULONG) - 1;
+ if (pdesc->bDescriptorType == USB_DT_DEVICE)
+ {
+ pdev_desc = (PUSB_DEVICE_DESC) pdesc;
+ return ((((ULONG) pdev_desc->idVendor) << 16) | pdev_desc->idProduct);
+ }
+ else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
+ {
+ pif_desc = (PUSB_INTERFACE_DESC) pdesc;
+ return ((((ULONG) pif_desc->bInterfaceClass) << 16) |
+ (((ULONG) pif_desc->bInterfaceSubClass) << 8) | ((ULONG) pif_desc->bInterfaceProtocol));
+ }
+ return (ULONG) - 1;
}
PDRIVER_OBJECT
-gendrv_find_drvr_by_key(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-ULONG key
-)
+gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key)
{
- PGENDRV_EXT_DRVR_ENTRY pentry;
- PLIST_ENTRY pthis, pnext;
- if( pdrvr_ext == NULL || key == ( ULONG )-1 )
- return NULL;
-
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ListFirst( &pdrvr_ext->ext_drvr_list, pthis );
- while( pthis )
- {
- pentry = ( PGENDRV_EXT_DRVR_ENTRY )pthis;
- if( pentry->drvr_key == key )
- {
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
- return pentry->pext_drvr;
- }
- ListNext( &pdrvr_ext->ext_drvr_list, pthis, pnext );
- pthis = pnext;
- }
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- return NULL;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+ PLIST_ENTRY pthis, pnext;
+ if (pdrvr_ext == NULL || key == (ULONG) - 1)
+ return NULL;
+
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
+ while (pthis)
+ {
+ pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
+ if (pentry->drvr_key == key)
+ {
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ return pentry->pext_drvr;
+ }
+ ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
+ pthis = pnext;
+ }
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ return NULL;
}
PDRIVER_OBJECT
-gendrv_load_ext_drvr(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-PUSB_DESC_HEADER pdesc
-)
+gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc)
{
- PDRIVER_OBJECT pdrvr_obj;
- PGENDRV_EXT_DRVR_ENTRY pentry;
- UNICODE_STRING usz, svc_name, svc_key, utemp;
- PKEY_VALUE_FULL_INFORMATION val_info;
- PWCHAR val_buf;
- HANDLE handle;
- NTSTATUS status;
-
- if( pdrvr_ext == NULL || pdesc == NULL )
- return NULL;
-
- // try to search and load driver from outside
- handle = NULL;
- RtlZeroMemory( &svc_key, sizeof( svc_key ) );
- val_info = NULL;
- RtlInitUnicodeString( &usz, L"" );
- gendrv_build_reg_string( pdesc, &usz );
- if( gendrv_open_reg_key( &handle, NULL, &usz, KEY_READ, FALSE ) != STATUS_SUCCESS )
- {
- goto ERROR_OUT;
- }
- if( gendrv_get_key_value( handle, L"service", &val_info ) != STATUS_SUCCESS )
- {
- goto ERROR_OUT;
- }
-
- if( val_info->DataLength > 32 )
- goto ERROR_OUT;
-
- val_buf = ( PWCHAR )( ( ( PBYTE )val_info ) + val_info->DataOffset );
- svc_key.Length = 0, svc_key.MaximumLength = 255;
- svc_key.Buffer = usb_alloc_mem( NonPagedPool, 256 );
-
- RtlInitUnicodeString( &utemp, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" );
- RtlAppendUnicodeStringToString( &svc_key, &utemp);
- RtlInitUnicodeString( &svc_name, val_buf );
- RtlAppendUnicodeStringToString( &svc_key, &svc_name );
-
- status = ZwLoadDriver( &svc_key );
- if( status != STATUS_SUCCESS )
- goto ERROR_OUT;
-
- svc_key.Length = 0;
- RtlZeroMemory( svc_key.Buffer, 128 );
- RtlInitUnicodeString( &svc_key, L"\\Driver\\" );
- RtlAppendUnicodeStringToString( &svc_key, &svc_name );
- pdrvr_obj = gendrv_open_ext_driver( &svc_key );
- if( pdrvr_obj == NULL )
- goto ERROR_OUT;
-
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- // insert the driver to the drvr list
- pentry = gendrv_alloc_ext_drvr_entry( pdrvr_ext );
- if( pentry == NULL )
- {
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ObDereferenceObject( pdrvr_obj );
- goto ERROR_OUT;
- }
- pentry->pext_drvr = pdrvr_obj;
- InsertTailList( &pdrvr_ext->ext_drvr_list, &pentry->drvr_link );
- pdrvr_ext->ext_drvr_count++;
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ZwClose( handle );
- return pdrvr_obj;
+ PDRIVER_OBJECT pdrvr_obj;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+ UNICODE_STRING usz, svc_name, svc_key, utemp;
+ PKEY_VALUE_FULL_INFORMATION val_info;
+ PWCHAR val_buf;
+ HANDLE handle;
+ NTSTATUS status;
+
+ if (pdrvr_ext == NULL || pdesc == NULL)
+ return NULL;
+
+ // try to search and load driver from outside
+ handle = NULL;
+ RtlZeroMemory(&svc_key, sizeof(svc_key));
+ val_info = NULL;
+ RtlInitUnicodeString(&usz, L"");
+ gendrv_build_reg_string(pdesc, &usz);
+ if (gendrv_open_reg_key(&handle, NULL, &usz, KEY_READ, FALSE) != STATUS_SUCCESS)
+ {
+ goto ERROR_OUT;
+ }
+ if (gendrv_get_key_value(handle, L"service", &val_info) != STATUS_SUCCESS)
+ {
+ goto ERROR_OUT;
+ }
+
+ if (val_info->DataLength > 32)
+ goto ERROR_OUT;
+
+ val_buf = (PWCHAR) (((PBYTE) val_info) + val_info->DataOffset);
+ svc_key.Length = 0, svc_key.MaximumLength = 255;
+ svc_key.Buffer = usb_alloc_mem(NonPagedPool, 256);
+
+ RtlInitUnicodeString(&utemp, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+ RtlAppendUnicodeStringToString(&svc_key, &utemp);
+ RtlInitUnicodeString(&svc_name, val_buf);
+ RtlAppendUnicodeStringToString(&svc_key, &svc_name);
+
+ status = ZwLoadDriver(&svc_key);
+ if (status != STATUS_SUCCESS)
+ goto ERROR_OUT;
+
+ svc_key.Length = 0;
+ RtlZeroMemory(svc_key.Buffer, 128);
+ RtlInitUnicodeString(&svc_key, L"\\Driver\\");
+ RtlAppendUnicodeStringToString(&svc_key, &svc_name);
+ pdrvr_obj = gendrv_open_ext_driver(&svc_key);
+ if (pdrvr_obj == NULL)
+ goto ERROR_OUT;
+
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ // insert the driver to the drvr list
+ pentry = gendrv_alloc_ext_drvr_entry(pdrvr_ext);
+ if (pentry == NULL)
+ {
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ObDereferenceObject(pdrvr_obj);
+ goto ERROR_OUT;
+ }
+ pentry->pext_drvr = pdrvr_obj;
+ InsertTailList(&pdrvr_ext->ext_drvr_list, &pentry->drvr_link);
+ pdrvr_ext->ext_drvr_count++;
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ZwClose(handle);
+ return pdrvr_obj;
ERROR_OUT:
- RtlFreeUnicodeString( &usz );
- if( val_info != NULL )
- {
- usb_free_mem( val_info );
- val_info = NULL;
- }
- if( svc_key.Buffer )
- usb_free_mem( svc_key.Buffer );
-
- if( handle )
- ZwClose( handle );
-
- return NULL;
+ RtlFreeUnicodeString(&usz);
+ if (val_info != NULL)
+ {
+ usb_free_mem(val_info);
+ val_info = NULL;
+ }
+ if (svc_key.Buffer)
+ usb_free_mem(svc_key.Buffer);
+
+ if (handle)
+ ZwClose(handle);
+
+ return NULL;
}
VOID
-gendrv_release_drvr(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-PDRIVER_OBJECT pdrvr_obj
-)
+gendrv_release_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PDRIVER_OBJECT pdrvr_obj)
{
- PLIST_ENTRY pthis, pnext;
- PGENDRV_EXT_DRVR_ENTRY pentry;
-
- if( pdrvr_ext == NULL || pdrvr_obj == NULL )
- return;
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ListFirst( &pdrvr_ext->ext_drvr_list, pthis );
- while( pthis )
- {
- pentry = ( PGENDRV_EXT_DRVR_ENTRY )pthis;
- if( pentry->pext_drvr == pdrvr_obj )
- {
- ASSERT( pentry->ref_count );
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
- return;
- }
- ListNext( &pdrvr_ext->ext_drvr_list, pthis, pnext );
- pthis = pnext;
- }
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
+ PLIST_ENTRY pthis, pnext;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+
+ if (pdrvr_ext == NULL || pdrvr_obj == NULL)
+ return;
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
+ while (pthis)
+ {
+ pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
+ if (pentry->pext_drvr == pdrvr_obj)
+ {
+ ASSERT(pentry->ref_count);
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ return;
+ }
+ ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
+ pthis = pnext;
+ }
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
}
NTSTATUS
-gendrv_send_pnp_msg(
-ULONG msg,
-PDEVICE_OBJECT pdev_obj,
-PVOID pctx
-)
+gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx)
{
- if( pdev_obj == NULL )
- return STATUS_INVALID_PARAMETER;
-
- switch( msg )
- {
- case GENDRV_MSG_ADDDEVICE:
- {
- PDRIVER_OBJECT pdrvr_obj;
- if( pctx == NULL )
- return STATUS_INVALID_PARAMETER;
- pdrvr_obj = (PDRIVER_OBJECT )pctx;
- if( pdrvr_obj->DriverExtension )
- {
- return pdrvr_obj->DriverExtension->AddDevice( pdrvr_obj, pdev_obj );
- }
- return STATUS_IO_DEVICE_ERROR;
- }
- case GENDRV_MSG_STOPDEVICE:
- case GENDRV_MSG_DISCDEVICE:
- {
- NTSTATUS status;
- IO_STACK_LOCATION *irpstack;
- IRP *irp;
- // IRP_MJ_PNP_POWER
- irp = IoAllocateIrp( 2, FALSE );
- if( irp == NULL )
- return STATUS_NO_MEMORY;
-
- irpstack = IoGetNextIrpStackLocation(irp);
- irpstack->MajorFunction = IRP_MJ_PNP_POWER;
- irpstack->MinorFunction =
- ( msg == GENDRV_MSG_STOPDEVICE ) ? IRP_MN_STOP_DEVICE : IRP_MN_REMOVE_DEVICE;
- status = IoCallDriver( pdev_obj, irp );
- ASSERT( status != STATUS_PENDING );
- status = irp->IoStatus.Status;
- IoFreeIrp( irp );
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- return STATUS_INVALID_PARAMETER;
+ if (pdev_obj == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (msg)
+ {
+ case GENDRV_MSG_ADDDEVICE:
+ {
+ PDRIVER_OBJECT pdrvr_obj;
+ if (pctx == NULL)
+ return STATUS_INVALID_PARAMETER;
+ pdrvr_obj = (PDRIVER_OBJECT) pctx;
+ if (pdrvr_obj->DriverExtension)
+ {
+ return pdrvr_obj->DriverExtension->AddDevice(pdrvr_obj, pdev_obj);
+ }
+ return STATUS_IO_DEVICE_ERROR;
+ }
+ case GENDRV_MSG_STOPDEVICE:
+ case GENDRV_MSG_DISCDEVICE:
+ {
+ NTSTATUS status;
+ IO_STACK_LOCATION *irpstack;
+ IRP *irp;
+ // IRP_MJ_PNP_POWER
+ irp = IoAllocateIrp(2, FALSE);
+ if (irp == NULL)
+ return STATUS_NO_MEMORY;
+
+ irpstack = IoGetNextIrpStackLocation(irp);
+ irpstack->MajorFunction = IRP_MJ_PNP_POWER;
+ irpstack->MinorFunction =
+ (msg == GENDRV_MSG_STOPDEVICE) ? IRP_MN_STOP_DEVICE : IRP_MN_REMOVE_DEVICE;
+ status = IoCallDriver(pdev_obj, irp);
+ ASSERT(status != STATUS_PENDING);
+ status = irp->IoStatus.Status;
+ IoFreeIrp(irp);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+ }
+ return STATUS_INVALID_PARAMETER;
}
BOOL
-gendrv_if_connect(
-PCONNECT_DATA params,
-DEV_HANDLE if_handle
-)
+gendrv_if_connect(PCONNECT_DATA params, DEV_HANDLE if_handle)
{
- //
- // try to search the registry to find one driver.
- // if found, create the PDO, load the driver.
- // and call its AddDevice.
- //
- LONG if_idx, i;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_DRIVER pdrvr;
- PUSB_INTERFACE_DESC pif_desc;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_DEV_MANAGER dev_mgr;
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- PGENDRV_EXT_DRVR_ENTRY pentry;
-
- PDEVICE_OBJECT pdev_obj;
- PDRIVER_OBJECT pdrvr_obj;
- PLIST_ENTRY pthis, pnext;
- USE_BASIC_NON_PENDING_IRQL;
-
- pdev = NULL;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_if_connect(): entering...\n" ) );
-
- if( params == NULL )
- return FALSE;
-
- dev_mgr = params->dev_mgr;
- pdrvr = params->pdriver;
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdrvr->driver_ext;
-
- status = usb_query_and_lock_dev( dev_mgr, if_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- goto ERROR_OUT;
- }
- // obtain the pointer to the config desc, the dev won't go away in this routine
- pconfig_desc = pdev->usb_config->pusb_config_desc; //
- usb_unlock_dev( pdev );
- pdev = NULL;
-
- if_idx = if_idx_from_handle( if_handle );
- pif_desc = ( PUSB_INTERFACE_DESC )( &pconfig_desc[ 1 ] );
-
- for( i = 0; i < if_idx; i++ )
- {
- //search for our if
- if( usb_skip_if_and_altif( ( PUCHAR* )&pif_desc ) == FALSE )
- break;
- }
- if( pif_desc == NULL )
- return FALSE;
-
- //
- // well, let's do the hard work to see if there is a class driver
- // for this device.
- //
- i = gendrv_make_key( ( PUSB_DESC_HEADER )pif_desc );
- if( i == -1 )
- {
- return FALSE;
- }
-
- pdrvr_obj = gendrv_find_drvr_by_key( pdrvr_ext, ( ULONG )i );
- if( !pdrvr_obj )
- {
- if( ( pdrvr_obj = gendrv_load_ext_drvr( pdrvr_ext, ( PUSB_DESC_HEADER )pif_desc ) ) == NULL )
- return FALSE;
- }
-
-
- pdev_obj = gendrv_create_device( dev_mgr, pdrvr, if_handle );
- if( pdev_obj == NULL )
- {
- goto ERROR_OUT;
- }
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB ||
- dev_mgr_set_if_driver( dev_mgr, if_handle, pdrvr, pdev ) == FALSE )
- {
- unlock_dev( pdev, FALSE );
- gendrv_delete_device( dev_mgr, pdev_obj );
- goto ERROR_OUT;
- }
-
- if( pdev->usb_config )
- {
- pdev->usb_config->interf[ if_idx ].if_ext = pdev_obj;
- pdev->usb_config->interf[ if_idx ].if_ext_size = 0;
- }
-
- unlock_dev( pdev, FALSE );
-
- pdev_ext = ( PGENDRV_DEVICE_EXTENSION )pdev_obj->DeviceExtension;
- pdev_ext->desc_buf = usb_alloc_mem( NonPagedPool, 512 );
- RtlCopyMemory( pdev_ext->desc_buf, pconfig_desc, 512 );
- pdev_ext->if_ctx.pif_desc = ( PUSB_INTERFACE_DESC )&pdev_ext->desc_buf[ ( PBYTE )pif_desc - ( PBYTE )pconfig_desc ];
-
- // insert the device to the dev_list
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- ListFirst( &pdrvr_ext->ext_drvr_list, pthis );
- pentry = NULL;
- while( pthis )
- {
- pentry = ( PGENDRV_EXT_DRVR_ENTRY )pthis;
- if( pentry->pext_drvr == pdrvr_obj )
- break;
- ListNext( &pdrvr_ext->ext_drvr_list, pthis, pnext );
- pthis = pnext;
- pentry = NULL;
- }
- ASSERT( pentry );
- InsertTailList( &pentry->dev_list, &pdev_ext->dev_obj_link );
- pdev_ext->ext_drvr_entry = pentry;
- pentry->ref_count++;
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- // notify the class driver, some device comes
- gendrv_send_pnp_msg( GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj );
- usb_unlock_dev( pdev );
- return TRUE;
+ //
+ // try to search the registry to find one driver.
+ // if found, create the PDO, load the driver.
+ // and call its AddDevice.
+ //
+ LONG if_idx, i;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_DRIVER pdrvr;
+ PUSB_INTERFACE_DESC pif_desc;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+ PUSB_DEV_MANAGER dev_mgr;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+
+ PDEVICE_OBJECT pdev_obj;
+ PDRIVER_OBJECT pdrvr_obj;
+ PLIST_ENTRY pthis, pnext;
+ USE_BASIC_NON_PENDING_IRQL;
+
+ pdev = NULL;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): entering...\n"));
+
+ if (params == NULL)
+ return FALSE;
+
+ dev_mgr = params->dev_mgr;
+ pdrvr = params->pdriver;
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
+
+ status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ goto ERROR_OUT;
+ }
+ // obtain the pointer to the config desc, the dev won't go away in this routine
+ pconfig_desc = pdev->usb_config->pusb_config_desc; //
+ usb_unlock_dev(pdev);
+ pdev = NULL;
+
+ if_idx = if_idx_from_handle(if_handle);
+ pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
+
+ for(i = 0; i < if_idx; i++)
+ {
+ //search for our if
+ if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
+ break;
+ }
+ if (pif_desc == NULL)
+ return FALSE;
+
+ //
+ // well, let's do the hard work to see if there is a class driver
+ // for this device.
+ //
+ i = gendrv_make_key((PUSB_DESC_HEADER) pif_desc);
+ if (i == -1)
+ {
+ return FALSE;
+ }
+
+ pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i);
+ if (!pdrvr_obj)
+ {
+ if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pif_desc)) == NULL)
+ return FALSE;
+ }
-ERROR_OUT:
- usb_unlock_dev( pdev );
- return FALSE;
+ pdev_obj = gendrv_create_device(dev_mgr, pdrvr, if_handle);
+ if (pdev_obj == NULL)
+ {
+ goto ERROR_OUT;
+ }
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
+ dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
+ {
+ unlock_dev(pdev, FALSE);
+ gendrv_delete_device(dev_mgr, pdev_obj);
+ goto ERROR_OUT;
+ }
+
+ if (pdev->usb_config)
+ {
+ pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
+ pdev->usb_config->interf[if_idx].if_ext_size = 0;
+ }
+
+ unlock_dev(pdev, FALSE);
+
+ pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
+ pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512);
+ RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512);
+ pdev_ext->if_ctx.pif_desc =
+ (PUSB_INTERFACE_DESC) & pdev_ext->desc_buf[(PBYTE) pif_desc - (PBYTE) pconfig_desc];
+
+ // insert the device to the dev_list
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
+ pentry = NULL;
+ while (pthis)
+ {
+ pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
+ if (pentry->pext_drvr == pdrvr_obj)
+ break;
+ ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
+ pthis = pnext;
+ pentry = NULL;
+ }
+ ASSERT(pentry);
+ InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link);
+ pdev_ext->ext_drvr_entry = pentry;
+ pentry->ref_count++;
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ // notify the class driver, some device comes
+ gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj);
+ usb_unlock_dev(pdev);
+ return TRUE;
+
+ ERROR_OUT:
+
+ usb_unlock_dev(pdev);
+ return FALSE;
}
BOOL
-gendrv_do_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle,
-BOOL is_if
-)
+gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOL is_if)
{
- PUSB_DEV pdev;
- PDEVICE_OBJECT pdev_obj;
- ULONG if_idx;
-
- if( dev_mgr == NULL )
- return FALSE;
-
- // clean up the irps
- if_idx = if_idx_from_handle( dev_handle );
- if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) != STATUS_SUCCESS )
- {
- return FALSE;
- }
- if( is_if && pdev->usb_config )
- pdev_obj = ( PDEVICE_OBJECT )pdev->usb_config->interf[ if_idx ].if_ext;
- else
- pdev_obj = pdev->dev_obj;
-
- gendrv_clean_up_queued_irps( pdev_obj );
- usb_unlock_dev( pdev );
-
- // send message to class drivers.
- gendrv_send_pnp_msg( GENDRV_MSG_STOPDEVICE, pdev_obj, NULL );
-
- return TRUE;
+ PUSB_DEV pdev;
+ PDEVICE_OBJECT pdev_obj;
+ ULONG if_idx;
+
+ if (dev_mgr == NULL)
+ return FALSE;
+
+ // clean up the irps
+ if_idx = if_idx_from_handle(dev_handle);
+ if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+ if (is_if && pdev->usb_config)
+ pdev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
+ else
+ pdev_obj = pdev->dev_obj;
+
+ gendrv_clean_up_queued_irps(pdev_obj);
+ usb_unlock_dev(pdev);
+
+ // send message to class drivers.
+ gendrv_send_pnp_msg(GENDRV_MSG_STOPDEVICE, pdev_obj, NULL);
+
+ return TRUE;
}
BOOL
-gendrv_if_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+gendrv_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- if( dev_mgr == NULL )
- return FALSE;
+ if (dev_mgr == NULL)
+ return FALSE;
- return gendrv_do_stop( dev_mgr, dev_handle, TRUE );
+ return gendrv_do_stop(dev_mgr, dev_handle, TRUE);
}
BOOL
-gendrv_do_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle,
-BOOL is_if
-)
+gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOL is_if)
{
- PUSB_DEV pdev;
- PDEVICE_OBJECT dev_obj = NULL;
- NTSTATUS status;
- PUSB_DRIVER pdrvr;
- PGENDRV_DRVR_EXTENSION pdrvr_ext = NULL;
- PGENDRV_DEVICE_EXTENSION pdev_ext = NULL;
- ULONG if_idx;
-
- status = usb_query_and_lock_dev( dev_mgr, if_handle, &pdev );
- if( pdev == NULL )
- {
- return FALSE;
- }
- if( status == STATUS_SUCCESS )
- {
- // must be a bug
- TRAP();
- }
- if_idx = if_idx_from_handle( if_handle );
- if( pdev->usb_config )
- {
- if( is_if )
- {
- pdrvr = pdev->usb_config->interf[ if_idx ].pif_drv;
- dev_obj = ( PDEVICE_OBJECT )pdev->usb_config->interf[ if_idx ].if_ext;
- }
- else
- {
- pdrvr = pdev->dev_driver;
- dev_obj = pdev->dev_obj;
- }
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdrvr->driver_ext;
- pdev_ext = ( PGENDRV_DEVICE_EXTENSION ) dev_obj->DeviceExtension;
- }
- else
- TRAP();
- pdev = NULL;
-
- // remove the device from the list
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- RemoveEntryList( &pdev_ext->dev_obj_link );
- pdev_ext->ext_drvr_entry->ref_count--;
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- // send message to class driver
- gendrv_send_pnp_msg( GENDRV_MSG_DISCDEVICE, dev_obj, NULL );
- // delete the device object
- gendrv_delete_device( dev_mgr, dev_obj );
- return TRUE;
+ PUSB_DEV pdev;
+ PDEVICE_OBJECT dev_obj = NULL;
+ NTSTATUS status;
+ PUSB_DRIVER pdrvr;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext = NULL;
+ PGENDRV_DEVICE_EXTENSION pdev_ext = NULL;
+ ULONG if_idx;
+
+ status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
+ if (pdev == NULL)
+ {
+ return FALSE;
+ }
+ if (status == STATUS_SUCCESS)
+ {
+ // must be a bug
+ TRAP();
+ }
+ if_idx = if_idx_from_handle(if_handle);
+ if (pdev->usb_config)
+ {
+ if (is_if)
+ {
+ pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
+ dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
+ }
+ else
+ {
+ pdrvr = pdev->dev_driver;
+ dev_obj = pdev->dev_obj;
+ }
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
+ pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
+ }
+ else
+ TRAP();
+ pdev = NULL;
+
+ // remove the device from the list
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ RemoveEntryList(&pdev_ext->dev_obj_link);
+ pdev_ext->ext_drvr_entry->ref_count--;
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ // send message to class driver
+ gendrv_send_pnp_msg(GENDRV_MSG_DISCDEVICE, dev_obj, NULL);
+ // delete the device object
+ gendrv_delete_device(dev_mgr, dev_obj);
+ return TRUE;
}
BOOL
-gendrv_if_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle
-)
+gendrv_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
- return gendrv_do_disconnect( dev_mgr, if_handle, TRUE );
+ return gendrv_do_disconnect(dev_mgr, if_handle, TRUE);
}
BOOL
-gendrv_if_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+gendrv_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
- pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
- pdriver->driver_desc.product_id = 0x0000; // 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 = 0x0; // Interface Class
- pdriver->driver_desc.if_sub_class = 0x0; // Interface SubClass
- pdriver->driver_desc.if_protocol = 0x0; // Interface Protocol
-
- pdriver->driver_desc.driver_name = "USB generic interface driver"; // Driver name for Name Registry
- pdriver->driver_desc.dev_class = 0;
- 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->disp_tbl.version = 1;
- pdriver->disp_tbl.dev_connect = gendrv_if_connect;
- pdriver->disp_tbl.dev_disconnect = gendrv_if_disconnect;
- pdriver->disp_tbl.dev_stop = gendrv_if_stop;
- pdriver->disp_tbl.dev_reserved = NULL;
-
- pdriver->driver_ext = usb_alloc_mem( NonPagedPool, sizeof( GENDRV_DRVR_EXTENSION ) );
- pdriver->driver_ext_size = sizeof( GENDRV_DRVR_EXTENSION );
-
- RtlZeroMemory( pdriver->driver_ext, pdriver->driver_ext_size );
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdriver->driver_ext;
-
- // InitializeListHead( &pdrvr_ext->dev_list );
- InitializeListHead( &pdrvr_ext->ext_drvr_list );
- pdrvr_ext->ext_drvr_count = 0;
- ExInitializeFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- return TRUE;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
+ pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
+ pdriver->driver_desc.product_id = 0x0000; // 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 = 0x0; // Interface Class
+ pdriver->driver_desc.if_sub_class = 0x0; // Interface SubClass
+ pdriver->driver_desc.if_protocol = 0x0; // Interface Protocol
+
+ pdriver->driver_desc.driver_name = "USB generic interface driver"; // Driver name for Name Registry
+ pdriver->driver_desc.dev_class = 0;
+ 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->disp_tbl.version = 1;
+ pdriver->disp_tbl.dev_connect = gendrv_if_connect;
+ pdriver->disp_tbl.dev_disconnect = gendrv_if_disconnect;
+ pdriver->disp_tbl.dev_stop = gendrv_if_stop;
+ pdriver->disp_tbl.dev_reserved = NULL;
+
+ pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION));
+ pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION);
+
+ RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size);
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
+
+ // InitializeListHead( &pdrvr_ext->dev_list );
+ InitializeListHead(&pdrvr_ext->ext_drvr_list);
+ pdrvr_ext->ext_drvr_count = 0;
+ ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ return TRUE;
}
BOOL
-gendrv_if_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- PLIST_ENTRY pthis;
- PGENDRV_EXT_DRVR_ENTRY pentry;
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- if( pdriver->driver_ext )
- {
- // should we lock it?
- // ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdriver->driver_ext;
- if( pdrvr_ext->ext_drvr_count )
- {
- while( IsListEmpty( &pdrvr_ext->ext_drvr_list ) )
- {
- pthis = RemoveHeadList( &pdrvr_ext->ext_drvr_list );
- pentry = ( PGENDRV_EXT_DRVR_ENTRY )pthis;
- if( pentry->pext_drvr )
- {
- if( pentry->ref_count )
- {
- // FIXME: really fail?
- continue;
- }
- ObDereferenceObject( pentry->pext_drvr );
- gendrv_release_ext_drvr_entry( pdrvr_ext, pentry );
- }
- }
- pdrvr_ext->ext_drvr_count = 0;
- }
-
- usb_free_mem( pdriver->driver_ext );
- pdriver->driver_ext = NULL;
- pdriver->driver_ext_size = 0;
- }
- return TRUE;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ PLIST_ENTRY pthis;
+ PGENDRV_EXT_DRVR_ENTRY pentry;
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ if (pdriver->driver_ext)
+ {
+ // should we lock it?
+ // ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
+ if (pdrvr_ext->ext_drvr_count)
+ {
+ while (IsListEmpty(&pdrvr_ext->ext_drvr_list))
+ {
+ pthis = RemoveHeadList(&pdrvr_ext->ext_drvr_list);
+ pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
+ if (pentry->pext_drvr)
+ {
+ if (pentry->ref_count)
+ {
+ // FIXME: really fail?
+ continue;
+ }
+ ObDereferenceObject(pentry->pext_drvr);
+ gendrv_release_ext_drvr_entry(pdrvr_ext, pentry);
+ }
+ }
+ pdrvr_ext->ext_drvr_count = 0;
+ }
+
+ usb_free_mem(pdriver->driver_ext);
+ pdriver->driver_ext = NULL;
+ pdriver->driver_ext_size = 0;
+ }
+ return TRUE;
}
PDRIVER_OBJECT
-gendrv_open_ext_driver(
-PUNICODE_STRING unicode_string
-)
+gendrv_open_ext_driver(PUNICODE_STRING unicode_string)
{
- NTSTATUS status;
- OBJECT_ATTRIBUTES oa;
- HANDLE drvr_handle;
- UNICODE_STRING oname;
- PDRIVER_OBJECT pdrvr = NULL;
-
- RtlZeroMemory( &oa, sizeof( oa ) );
- oa.Length = sizeof( oa );
- oa.ObjectName = &oname;
- oa.Attributes = OBJ_CASE_INSENSITIVE;
- RtlInitUnicodeString( &oname, L"" );
- RtlAppendUnicodeStringToString( &oname, unicode_string );
-
- status = ObOpenObjectByName( &oa,
- IoDriverObjectType, // object type
- KernelMode, // access mode
- NULL, // access state
- FILE_READ_DATA, // STANDARD_RIGHTS_READ, access right
- NULL,
- &drvr_handle );
-
- if( status != STATUS_SUCCESS )
- {
- return NULL;
- }
- ObReferenceObjectByHandle( drvr_handle,
- FILE_READ_DATA,
- IoDriverObjectType,
- KernelMode,
- (PVOID)&pdrvr,
- NULL // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
- );
- ZwClose( drvr_handle );
- return pdrvr;
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES oa;
+ HANDLE drvr_handle;
+ UNICODE_STRING oname;
+ PDRIVER_OBJECT pdrvr = NULL;
+
+ RtlZeroMemory(&oa, sizeof(oa));
+ oa.Length = sizeof(oa);
+ oa.ObjectName = &oname;
+ oa.Attributes = OBJ_CASE_INSENSITIVE;
+ RtlInitUnicodeString(&oname, L"");
+ RtlAppendUnicodeStringToString(&oname, unicode_string);
+
+ status = ObOpenObjectByName(&oa, IoDriverObjectType, // object type
+ KernelMode, // access mode
+ NULL, // access state
+ FILE_READ_DATA, // STANDARD_RIGHTS_READ, access right
+ NULL,
+ &drvr_handle);
+
+ if (status != STATUS_SUCCESS)
+ {
+ return NULL;
+ }
+ ObReferenceObjectByHandle(drvr_handle,
+ FILE_READ_DATA,
+ IoDriverObjectType,
+ KernelMode,
+ (PVOID)&pdrvr,
+ NULL); // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
+
+ ZwClose(drvr_handle);
+ return pdrvr;
}
BOOL
-gendrv_close_ext_driver( PDRIVER_OBJECT pdrvr )
+gendrv_close_ext_driver(PDRIVER_OBJECT pdrvr)
{
- if( pdrvr == NULL )
- return FALSE;
- ObDereferenceObject( pdrvr );
- return TRUE;
+ if (pdrvr == NULL)
+ return FALSE;
+ ObDereferenceObject(pdrvr);
+ return TRUE;
}
NTSTATUS
-gendrv_dispatch(
-PDEVICE_OBJECT dev_obj,
-PIRP irp
-)
+gendrv_dispatch(PDEVICE_OBJECT dev_obj, PIRP irp)
{
- IO_STACK_LOCATION *irpstack;
- PUSB_DEV_MANAGER dev_mgr;
- PDEVEXT_HEADER ext_hdr;
- NTSTATUS status;
-
- if( dev_obj == NULL || irp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- ext_hdr = dev_obj->DeviceExtension;
- dev_mgr = ext_hdr->dev_mgr;
-
- irpstack = IoGetNextIrpStackLocation(irp);
- switch( irpstack->MajorFunction )
- {
- case IRP_MJ_PNP_POWER:
- {
- irp->IoStatus.Information = 0;
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_SUCCESS, irp );
- }
- case IRP_MJ_INTERNAL_DEVICE_CONTROL:
- {
- status = STATUS_NOT_SUPPORTED;
- if( irpstack->MinorFunction == IOCTL_SUBMIT_URB_RD ||
- irpstack->MinorFunction == IOCTL_SUBMIT_URB_WR ||
- irpstack->MinorFunction == IOCTL_SUBMIT_URB_NOIO )
- {
- PURB purb;
- DEV_HANDLE endp_handle;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
-
- pdev_ext = dev_obj->DeviceExtension;
- if( irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof( URB ) )
- {
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- purb = ( PURB )irp->AssociatedIrp.SystemBuffer;
- endp_handle = purb->endp_handle;
- if( purb->data_buffer == NULL || purb->data_length == 0 )
- {
- if( irpstack->MinorFunction != IOCTL_SUBMIT_URB_NOIO )
- {
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
- }
- if( !default_endp_handle( endp_handle ) )
- {
- //no permit to other interface if interface dev
- if( if_dev( dev_obj ) &&
- if_idx_from_handle( endp_handle ) != pdev_ext->if_ctx.if_idx )
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_PENDING, irp );
- }
- else if( irpstack->MinorFunction == IOCTL_GET_DEV_DESC )
- {
- // this is a synchronous call, route to dev_mgr_dispatch
- return dev_mgr_dispatch( dev_mgr, irp );
- }
- else if( irpstack->MinorFunction == IOCTL_GET_DEV_HANDLE )
- {
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- pdev_ext = dev_obj->DeviceExtension;
- if( irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( LONG ) )
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
-
- *( ( PLONG )irp->AssociatedIrp.SystemBuffer ) = pdev_ext->dev_handle;
- irp->IoStatus.Information = sizeof( LONG );
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_SUCCESS, irp );
- }
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_NOT_SUPPORTED, irp );
- }
- case IRP_MJ_DEVICE_CONTROL:
- {
- status = STATUS_NOT_SUPPORTED;
- if( irpstack->MinorFunction == IOCTL_SUBMIT_URB_RD ||
- irpstack->MinorFunction == IOCTL_SUBMIT_URB_WR ||
- irpstack->MinorFunction == IOCTL_SUBMIT_URB_NOIO )
- {
- PURB purb;
- DEV_HANDLE endp_handle;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
-
- pdev_ext = dev_obj->DeviceExtension;
- if( irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof( URB ) )
- {
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- purb = ( PURB )irp->AssociatedIrp.SystemBuffer;
- endp_handle = purb->endp_handle;
- if( !default_endp_handle( endp_handle ) )
- {
- //no permit to other interface if interface dev
- if( if_dev( dev_obj ) &&
- if_idx_from_handle( endp_handle ) != pdev_ext->if_ctx.if_idx )
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_PENDING, irp );
- }
- else if( irpstack->MinorFunction == IOCTL_GET_DEV_DESC )
- {
- // this is a synchronous call, route to dev_mgr_dispatch
- return dev_mgr_dispatch( dev_mgr, irp );
- }
- else if( irpstack->MinorFunction == IOCTL_GET_DEV_HANDLE )
- {
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- pdev_ext = dev_obj->DeviceExtension;
- if( irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( LONG ) )
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_INVALID_PARAMETER, irp );
-
- *( ( PLONG )irp->AssociatedIrp.SystemBuffer ) = pdev_ext->dev_handle;
- irp->IoStatus.Information = sizeof( LONG );
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_SUCCESS, irp );
- }
- GENDRV_EXIT_DISPATCH( dev_obj, STATUS_NOT_SUPPORTED, irp );
- }
- }
- irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
- irp->IoStatus.Information = 0;
- IoCompleteRequest( irp, IO_NO_INCREMENT );
-
- return STATUS_NOT_SUPPORTED;
+ IO_STACK_LOCATION *irpstack;
+ PUSB_DEV_MANAGER dev_mgr;
+ PDEVEXT_HEADER ext_hdr;
+ NTSTATUS status;
+
+ if (dev_obj == NULL || irp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ ext_hdr = dev_obj->DeviceExtension;
+ dev_mgr = ext_hdr->dev_mgr;
+
+ irpstack = IoGetNextIrpStackLocation(irp);
+ switch (irpstack->MajorFunction)
+ {
+ case IRP_MJ_PNP_POWER:
+ {
+ irp->IoStatus.Information = 0;
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
+ }
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+ {
+ status = STATUS_NOT_SUPPORTED;
+ if (irpstack->MinorFunction == IOCTL_SUBMIT_URB_RD ||
+ irpstack->MinorFunction == IOCTL_SUBMIT_URB_WR ||
+ irpstack->MinorFunction == IOCTL_SUBMIT_URB_NOIO)
+ {
+ PURB purb;
+ DEV_HANDLE endp_handle;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+
+ pdev_ext = dev_obj->DeviceExtension;
+ if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
+ {
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ purb = (PURB) irp->AssociatedIrp.SystemBuffer;
+ endp_handle = purb->endp_handle;
+ if (purb->data_buffer == NULL || purb->data_length == 0)
+ {
+ if (irpstack->MinorFunction != IOCTL_SUBMIT_URB_NOIO)
+ {
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+ }
+ if (!default_endp_handle(endp_handle))
+ {
+ //no permit to other interface if interface dev
+ if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
+ }
+ else if (irpstack->MinorFunction == IOCTL_GET_DEV_DESC)
+ {
+ // this is a synchronous call, route to dev_mgr_dispatch
+ return dev_mgr_dispatch(dev_mgr, irp);
+ }
+ else if (irpstack->MinorFunction == IOCTL_GET_DEV_HANDLE)
+ {
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ pdev_ext = dev_obj->DeviceExtension;
+ if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+
+ *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
+ irp->IoStatus.Information = sizeof(LONG);
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
+ }
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
+ }
+ case IRP_MJ_DEVICE_CONTROL:
+ {
+ status = STATUS_NOT_SUPPORTED;
+ if (irpstack->MinorFunction == IOCTL_SUBMIT_URB_RD ||
+ irpstack->MinorFunction == IOCTL_SUBMIT_URB_WR ||
+ irpstack->MinorFunction == IOCTL_SUBMIT_URB_NOIO)
+ {
+ PURB purb;
+ DEV_HANDLE endp_handle;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+
+ pdev_ext = dev_obj->DeviceExtension;
+ if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
+ {
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ purb = (PURB) irp->AssociatedIrp.SystemBuffer;
+ endp_handle = purb->endp_handle;
+ if (!default_endp_handle(endp_handle))
+ {
+ //no permit to other interface if interface dev
+ if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
+ }
+ else if (irpstack->MinorFunction == IOCTL_GET_DEV_DESC)
+ {
+ // this is a synchronous call, route to dev_mgr_dispatch
+ return dev_mgr_dispatch(dev_mgr, irp);
+ }
+ else if (irpstack->MinorFunction == IOCTL_GET_DEV_HANDLE)
+ {
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ pdev_ext = dev_obj->DeviceExtension;
+ if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
+
+ *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
+ irp->IoStatus.Information = sizeof(LONG);
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
+ }
+ GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
+ }
+ }
+ irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ irp->IoStatus.Information = 0;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return STATUS_NOT_SUPPORTED;
}
+
BOOL
-gendrv_init_dev_ext_hdr(
-PDEVICE_OBJECT dev_obj,
-PUSB_DEV_MANAGER dev_mgr
-)
+gendrv_init_dev_ext_hdr(PDEVICE_OBJECT dev_obj, PUSB_DEV_MANAGER dev_mgr)
{
- PDEVEXT_HEADER dev_hdr = NULL;
- if( dev_obj == NULL || dev_mgr == NULL )
- return FALSE;
-
- dev_hdr = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
- dev_hdr->type = NTDEV_TYPE_CLIENT_DEV;
- dev_hdr->dispatch = gendrv_dispatch;
- dev_hdr->start_io = (PDRIVER_STARTIO)gendrv_startio;
- return TRUE;
+ PDEVEXT_HEADER dev_hdr = NULL;
+ if (dev_obj == NULL || dev_mgr == NULL)
+ return FALSE;
+
+ dev_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+ dev_hdr->type = NTDEV_TYPE_CLIENT_DEV;
+ dev_hdr->dispatch = gendrv_dispatch;
+ dev_hdr->start_io = (PDRIVER_STARTIO) gendrv_startio;
+ return TRUE;
}
PDEVICE_OBJECT
-gendrv_create_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER gen_drvr,
-DEV_HANDLE dev_handle
-)
+gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle)
{
- BOOL is_if;
- PDEVICE_OBJECT pdev;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- ULONG dev_id;
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- CHAR dev_name[ 64 ];
- STRING string;
- UNICODE_STRING name_string, symb_link;
- NTSTATUS status;
-
- if( dev_mgr == NULL || gen_drvr == NULL || dev_handle == 0 )
- return NULL;
-
- is_if = ( gen_drvr->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) ? 1 : 0;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_create_device(): entering...\n" ) );
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )gen_drvr->driver_ext;
- dev_id = ( UCHAR )dev_id_from_handle( dev_handle );
-
- if( is_if == FALSE )
- sprintf( dev_name, "\\Device\\gendev_%d", ( int )dev_id );
- else
- sprintf( dev_name, "\\Device\\genifdev_%d", ( int )dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &name_string, &string, TRUE );
- pdev = NULL;
-
- status = IoCreateDevice(
- dev_mgr->usb_driver_obj,
- sizeof( GENDRV_DEVICE_EXTENSION ),
- &name_string,
- FILE_USB_DEV_TYPE,
- 0,
- TRUE,
- &pdev);
-
- if( status == STATUS_SUCCESS )
- {
- //
- // We do direct io
- //
- pdev->Flags |= DO_DIRECT_IO;
-
- pdev->Flags &= ~DO_DEVICE_INITIALIZING;
- pdev->StackSize = 2; //one for fdo, one for file device obj
-
- pdev_ext = ( PGENDRV_DEVICE_EXTENSION )pdev->DeviceExtension;
-
- //may be accessed by other thread
-
- gendrv_init_dev_ext_hdr( pdev, dev_mgr );
-
- pdev_ext->dev_id = ( UCHAR )dev_id;
- pdev_ext->pdo = pdev;
- pdev_ext->dev_handle = dev_handle;
- pdev_ext->dev_mgr = dev_mgr;
- pdev_ext->pdriver = gen_drvr;
-
- if( is_if == FALSE )
- sprintf( dev_name, "\\DosDevices\\gendev%d", ( int )dev_id );
- else
- sprintf( dev_name, "\\DosDevices\\genifdev%d", ( int )dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoCreateSymbolicLink( &symb_link, &name_string );
- RtlFreeUnicodeString( &symb_link );
- KeInitializeEvent( &pdev_ext->sync_event, SynchronizationEvent, FALSE );
- KeInitializeSpinLock( &pdev_ext->dev_lock );
-
- }
- RtlFreeUnicodeString( &name_string );
- return pdev;
+ BOOL is_if;
+ PDEVICE_OBJECT pdev;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ ULONG dev_id;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ CHAR dev_name[64];
+ STRING string;
+ UNICODE_STRING name_string, symb_link;
+ NTSTATUS status;
+
+ if (dev_mgr == NULL || gen_drvr == NULL || dev_handle == 0)
+ return NULL;
+
+ is_if = (gen_drvr->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) ? 1 : 0;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_create_device(): entering...\n"));
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) gen_drvr->driver_ext;
+ dev_id = (UCHAR) dev_id_from_handle(dev_handle);
+
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\Device\\gendev_%d", (int)dev_id);
+ else
+ sprintf(dev_name, "\\Device\\genifdev_%d", (int)dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
+ pdev = NULL;
+
+ status = IoCreateDevice(dev_mgr->usb_driver_obj,
+ sizeof(GENDRV_DEVICE_EXTENSION), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);
+
+ if (status == STATUS_SUCCESS)
+ {
+ //
+ // We do direct io
+ //
+ pdev->Flags |= DO_DIRECT_IO;
+
+ pdev->Flags &= ~DO_DEVICE_INITIALIZING;
+ pdev->StackSize = 2; //one for fdo, one for file device obj
+
+ pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev->DeviceExtension;
+
+ //may be accessed by other thread
+
+ gendrv_init_dev_ext_hdr(pdev, dev_mgr);
+
+ pdev_ext->dev_id = (UCHAR) dev_id;
+ pdev_ext->pdo = pdev;
+ pdev_ext->dev_handle = dev_handle;
+ pdev_ext->dev_mgr = dev_mgr;
+ pdev_ext->pdriver = gen_drvr;
+
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\DosDevices\\gendev%d", (int)dev_id);
+ else
+ sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoCreateSymbolicLink(&symb_link, &name_string);
+ RtlFreeUnicodeString(&symb_link);
+ KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
+ KeInitializeSpinLock(&pdev_ext->dev_lock);
+
+ }
+ RtlFreeUnicodeString(&name_string);
+ return pdev;
}
VOID
-gendrv_deferred_delete_device(
-PVOID context
-)
+gendrv_deferred_delete_device(PVOID context)
{
- PDEVICE_OBJECT dev_obj;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
- LARGE_INTEGER interval;
-
- if( context == NULL )
- return;
-
- dev_obj = ( PDEVICE_OBJECT )context;
- pdev_ext = dev_obj->DeviceExtension;
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdev_ext->pdriver->driver_ext;
-
- interval.QuadPart = -20000; //two ms
-
- for( ; ; )
- {
- if( dev_obj->ReferenceCount )
- KeDelayExecutionThread( KernelMode, TRUE, &interval );
- else
- {
- KeDelayExecutionThread( KernelMode, TRUE, &interval );
- if( dev_obj->ReferenceCount == 0 )
- break;
- }
- }
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj ) );
-
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- RemoveEntryList( &pdev_ext->dev_obj_link );
- pdev_ext->ext_drvr_entry->ref_count--;
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- IoDeleteDevice( dev_obj );
- return;
+ PDEVICE_OBJECT dev_obj;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+ LARGE_INTEGER interval;
+
+ if (context == NULL)
+ return;
+
+ dev_obj = (PDEVICE_OBJECT) context;
+ pdev_ext = dev_obj->DeviceExtension;
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
+
+ interval.QuadPart = -20000; //two ms
+
+ for(;;)
+ {
+ if (dev_obj->ReferenceCount)
+ KeDelayExecutionThread(KernelMode, TRUE, &interval);
+ else
+ {
+ KeDelayExecutionThread(KernelMode, TRUE, &interval);
+ if (dev_obj->ReferenceCount == 0)
+ break;
+ }
+ }
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
+
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ RemoveEntryList(&pdev_ext->dev_obj_link);
+ pdev_ext->ext_drvr_entry->ref_count--;
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ IoDeleteDevice(dev_obj);
+ return;
}
BOOL
-gendrv_delete_device(
-PUSB_DEV_MANAGER dev_mgr,
-PDEVICE_OBJECT dev_obj
-)
+gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj)
{
- BOOL is_if;
- PUSB_DRIVER pdrvr;
- PGENDRV_DEVICE_EXTENSION pdev_ext;
- UCHAR dev_name[ 64 ];
- STRING string;
- UNICODE_STRING symb_link;
- PGENDRV_DRVR_EXTENSION pdrvr_ext;
-
- if( dev_mgr == NULL || dev_obj == 0 )
- return FALSE;
-
- pdev_ext = ( PGENDRV_DEVICE_EXTENSION )dev_obj->DeviceExtension;
- pdrvr = pdev_ext->pdriver;
- pdrvr_ext = ( PGENDRV_DRVR_EXTENSION )pdrvr->driver_ext;
- is_if = if_dev( dev_obj );
- if( is_if == FALSE )
- sprintf( dev_name, "\\DosDevices\\gendev%d", ( int )pdev_ext->dev_id );
- else
- sprintf( dev_name, "\\DosDevices\\genifdev%d", ( int )pdev_ext->dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoDeleteSymbolicLink( &symb_link );
- RtlFreeUnicodeString( &symb_link );
-
- if( pdev_ext->desc_buf )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "gendrv_delete_device(): delete desc_buf\n" ) );
- usb_free_mem( pdev_ext->desc_buf );
- pdev_ext->desc_buf = NULL;
-
- }
-
- if( dev_obj->ReferenceCount == 0 )
- {
- ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
- RemoveEntryList( &pdev_ext->dev_obj_link );
- pdev_ext->ext_drvr_entry->ref_count--; //the ext_drvr_entry is actually in pdrvr_ext, so lock it.
- ExReleaseFastMutex( &pdrvr_ext->drvr_ext_mutex );
-
- IoDeleteDevice( dev_obj );
- return TRUE;
- }
-
- // borrow from umss's work routine
- return umss_schedule_workitem( dev_obj, gendrv_deferred_delete_device, NULL, 0 );
+ BOOL is_if;
+ PUSB_DRIVER pdrvr;
+ PGENDRV_DEVICE_EXTENSION pdev_ext;
+ UCHAR dev_name[64];
+ STRING string;
+ UNICODE_STRING symb_link;
+ PGENDRV_DRVR_EXTENSION pdrvr_ext;
+
+ if (dev_mgr == NULL || dev_obj == 0)
+ return FALSE;
+
+ pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
+ pdrvr = pdev_ext->pdriver;
+ pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
+ is_if = if_dev(dev_obj);
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\DosDevices\\gendev%d", (int)pdev_ext->dev_id);
+ else
+ sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)pdev_ext->dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoDeleteSymbolicLink(&symb_link);
+ RtlFreeUnicodeString(&symb_link);
+
+ if (pdev_ext->desc_buf)
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_delete_device(): delete desc_buf\n"));
+ usb_free_mem(pdev_ext->desc_buf);
+ pdev_ext->desc_buf = NULL;
+
+ }
+
+ if (dev_obj->ReferenceCount == 0)
+ {
+ ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
+ RemoveEntryList(&pdev_ext->dev_obj_link);
+ pdev_ext->ext_drvr_entry->ref_count--; //the ext_drvr_entry is actually in pdrvr_ext, so lock it.
+ ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
+
+ IoDeleteDevice(dev_obj);
+ return TRUE;
+ }
+
+ // borrow from umss's work routine
+ return umss_schedule_workitem(dev_obj, gendrv_deferred_delete_device, NULL, 0);
}
// must have the drvr_ext_mutex acquired.
PGENDRV_EXT_DRVR_ENTRY
-gendrv_alloc_ext_drvr_entry(
-PGENDRV_DRVR_EXTENSION pdrvr_ext
-)
+gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext)
{
- LONG i;
- if( pdrvr_ext == NULL )
- return NULL;
- if( pdrvr_ext->ext_drvr_count == GENDRV_MAX_EXT_DRVR )
- return NULL;
- for( i = 0; i < GENDRV_MAX_EXT_DRVR; i++ )
- {
- if( pdrvr_ext->ext_drvr_array[ i ].drvr_link.Flink == NULL &&
- pdrvr_ext->ext_drvr_array[ i ].drvr_link.Blink == NULL )
- {
- return &pdrvr_ext->ext_drvr_array[ i ];
- }
- }
- return NULL;
+ LONG i;
+ if (pdrvr_ext == NULL)
+ return NULL;
+ if (pdrvr_ext->ext_drvr_count == GENDRV_MAX_EXT_DRVR)
+ return NULL;
+ for(i = 0; i < GENDRV_MAX_EXT_DRVR; i++)
+ {
+ if (pdrvr_ext->ext_drvr_array[i].drvr_link.Flink == NULL &&
+ pdrvr_ext->ext_drvr_array[i].drvr_link.Blink == NULL)
+ {
+ return &pdrvr_ext->ext_drvr_array[i];
+ }
+ }
+ return NULL;
}
// must have the drvr_ext_mutex acquired.
VOID
-gendrv_release_ext_drvr_entry(
-PGENDRV_DRVR_EXTENSION pdrvr_ext,
-PGENDRV_EXT_DRVR_ENTRY pentry
-)
+gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry)
{
- if( pdrvr_ext == NULL || pentry == NULL )
- return;
- RtlZeroMemory( pentry, sizeof( GENDRV_EXT_DRVR_ENTRY ) );
- InitializeListHead( &pentry->dev_list );
- return;
+ if (pdrvr_ext == NULL || pentry == NULL)
+ return;
+ RtlZeroMemory(pentry, sizeof(GENDRV_EXT_DRVR_ENTRY));
+ InitializeListHead(&pentry->dev_list);
+ return;
}
NTSTATUS
-gendrv_open_reg_key(
-OUT PHANDLE handle,
-IN HANDLE base_handle OPTIONAL,
-IN PUNICODE_STRING keyname,
-IN ACCESS_MASK desired_access,
-IN BOOLEAN create
-)
-
+gendrv_open_reg_key(OUT PHANDLE handle,
+ IN HANDLE base_handle OPTIONAL,
+ IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create)
/*++
Routine Description:
The function value is the final status of the operation.
--*/
-
{
OBJECT_ATTRIBUTES object_attr;
ULONG disposition;
// Initialize the object for the key.
//
- InitializeObjectAttributes( &object_attr,
- keyname,
- OBJ_CASE_INSENSITIVE,
- base_handle,
- (PSECURITY_DESCRIPTOR) NULL );
+ InitializeObjectAttributes(&object_attr,
+ keyname, OBJ_CASE_INSENSITIVE, base_handle, (PSECURITY_DESCRIPTOR) NULL);
//
// Create the key or open it, as appropriate based on the caller's
//
if (create)
- {
- return ZwCreateKey( handle,
- desired_access,
- &object_attr,
- 0,
- (PUNICODE_STRING) NULL,
- REG_OPTION_VOLATILE,
- &disposition );
+ {
+ return ZwCreateKey(handle,
+ desired_access,
+ &object_attr, 0, (PUNICODE_STRING) NULL, REG_OPTION_VOLATILE, &disposition);
}
- else
- {
- return ZwOpenKey( handle,
- desired_access,
- &object_attr );
+ else
+ {
+ return ZwOpenKey(handle, desired_access, &object_attr);
}
- return STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER;
}
NTSTATUS
-gendrv_get_key_value(
-IN HANDLE KeyHandle,
-IN PWSTR ValueName,
-OUT PKEY_VALUE_FULL_INFORMATION *Information
-)
-
+gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information)
/*++
Routine Description:
The function value is the final status of the query operation.
--*/
-
{
UNICODE_STRING unicodeString;
NTSTATUS status;
PAGED_CODE();
- RtlInitUnicodeString( &unicodeString, ValueName );
+ RtlInitUnicodeString(&unicodeString, ValueName);
//
// Figure out how big the data value is so that a buffer of the
// appropriate size can be allocated.
//
- status = ZwQueryValueKey( KeyHandle,
- &unicodeString,
- KeyValueFullInformation,
- (PVOID) NULL,
- 0,
- &keyValueLength );
- if (status != STATUS_BUFFER_OVERFLOW &&
- status != STATUS_BUFFER_TOO_SMALL) {
+ status = ZwQueryValueKey(KeyHandle,
+ &unicodeString, KeyValueFullInformation, (PVOID) NULL, 0, &keyValueLength);
+ if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL)
+ {
return status;
}
// Allocate a buffer large enough to contain the entire key data value.
//
- infoBuffer = usb_alloc_mem( NonPagedPool, keyValueLength );
- if (!infoBuffer) {
+ infoBuffer = usb_alloc_mem(NonPagedPool, keyValueLength);
+ if (!infoBuffer)
+ {
return STATUS_INSUFFICIENT_RESOURCES;
}
// Query the data for the key value.
//
- status = ZwQueryValueKey( KeyHandle,
- &unicodeString,
- KeyValueFullInformation,
- infoBuffer,
- keyValueLength,
- &keyValueLength );
- if (!NT_SUCCESS( status )) {
- usb_free_mem( infoBuffer );
+ status = ZwQueryValueKey(KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation, infoBuffer, keyValueLength, &keyValueLength);
+ if (!NT_SUCCESS(status))
+ {
+ usb_free_mem(infoBuffer);
return status;
}
}
VOID
-gendrv_startio(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- PIO_STACK_LOCATION irp_stack;
- ULONG ctrl_code;
- PUSB_DEV_MANAGER dev_mgr;
- USE_NON_PENDING_IRQL;
-
- if( dev_obj == NULL || irp == NULL )
- return;
-
- // standard process from walter oney
- IoAcquireCancelSpinLock(&old_irql);
- if (irp != dev_obj->CurrentIrp || irp->Cancel)
- {
- // already move on to other irp
- IoReleaseCancelSpinLock( old_irql );
- return;
- }
- else
- {
- IoSetCancelRoutine( irp, NULL );
- }
- IoReleaseCancelSpinLock( old_irql );
-
- irp->IoStatus.Information = 0;
-
- irp_stack = IoGetCurrentIrpStackLocation( irp );
- ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
- dev_mgr = ( ( PDEVEXT_HEADER )dev_obj->DeviceExtension )->dev_mgr;
-
- if( irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL &&
- irp_stack->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL )
- {
- GENDRV_COMPLETE_START_IO( dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp );
- }
-
- switch( ctrl_code )
- {
- case IOCTL_SUBMIT_URB_RD:
- case IOCTL_SUBMIT_URB_NOIO:
- case IOCTL_SUBMIT_URB_WR:
- {
- PURB purb;
- ULONG endp_idx, if_idx, user_buffer_length = 0;
- PUCHAR user_buffer = NULL;
- PUSB_DEV pdev;
- DEV_HANDLE endp_handle;
- PUSB_ENDPOINT pendp;
-
- NTSTATUS status;
-
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( URB ) )
- {
- GENDRV_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- purb = ( PURB )irp->AssociatedIrp.SystemBuffer;
- if( ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR )
- {
- if( irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
- {
- user_buffer = MmGetSystemAddressForMdl( irp->MdlAddress );
- user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
- if( user_buffer_length == 0 )
- GENDRV_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
- else
- {
- if( purb->data_buffer == NULL || purb->data_length == 0 )
- GENDRV_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
- user_buffer = purb->data_buffer;
- user_buffer_length = purb->data_length;
- }
- }
-
- purb->reference = 0;
- endp_handle = purb->endp_handle;
-
- if( usb_query_and_lock_dev( dev_mgr, endp_handle & ~0xffff, &pdev ) != STATUS_SUCCESS )
- {
- GENDRV_COMPLETE_START_IO( dev_obj, 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 > 16 )
- {
- 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 )
- {
- 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 register irp before the urb is scheduled to
- // avoid race condition.
- //
- ASSERT( dev_mgr_register_irp( dev_mgr, irp, purb ) );
- //
- // the irp can not be canceled at this point, since it is
- // now the current irp and not in any urb queue. dev_mgr_cancel_irp
- // can not find it and simply return.
- //
- // FIXME: there is a time window that the irp is registered and
- // the urb is not queued. In the meantime, the cancel
- // request may come and cause the irp removed from the irp
- // queue while fail to cancel due to urb not in any urb queue .
- // Thus from that point on, the irp can not be canceled till it
- // is completed or hanging there forever.
- //
- status = usb_submit_urb( dev_mgr, purb );
- if( status != STATUS_PENDING )
- {
- // unmark the pending bit
- 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;
- GENDRV_COMPLETE_START_IO( dev_obj, status, irp );
- }
- return;
-
-ERROR_OUT1:
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
- irp->IoStatus.Information = 0;
- GENDRV_COMPLETE_START_IO( dev_obj, status, irp );
- }
- }
- GENDRV_COMPLETE_START_IO( dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp );
+ PIO_STACK_LOCATION irp_stack;
+ ULONG ctrl_code;
+ PUSB_DEV_MANAGER dev_mgr;
+ USE_NON_PENDING_IRQL;
+
+ if (dev_obj == NULL || irp == NULL)
+ return;
+
+ // standard process from walter oney
+ IoAcquireCancelSpinLock(&old_irql);
+ if (irp != dev_obj->CurrentIrp || irp->Cancel)
+ {
+ // already move on to other irp
+ IoReleaseCancelSpinLock(old_irql);
+ return;
+ }
+ else
+ {
+ IoSetCancelRoutine(irp, NULL);
+ }
+ IoReleaseCancelSpinLock(old_irql);
+
+ irp->IoStatus.Information = 0;
+
+ irp_stack = IoGetCurrentIrpStackLocation(irp);
+ ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
+ dev_mgr = ((PDEVEXT_HEADER) dev_obj->DeviceExtension)->dev_mgr;
+
+ if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL &&
+ irp_stack->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL)
+ {
+ GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
+ }
+
+ switch (ctrl_code)
+ {
+ case IOCTL_SUBMIT_URB_RD:
+ case IOCTL_SUBMIT_URB_NOIO:
+ case IOCTL_SUBMIT_URB_WR:
+ {
+ PURB purb;
+ ULONG endp_idx, if_idx, user_buffer_length = 0;
+ PUCHAR user_buffer = NULL;
+ PUSB_DEV pdev;
+ DEV_HANDLE endp_handle;
+ PUSB_ENDPOINT pendp;
+
+ NTSTATUS status;
+
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
+ {
+ GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ purb = (PURB) irp->AssociatedIrp.SystemBuffer;
+ if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
+ {
+ if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
+ {
+ user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
+ user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
+ if (user_buffer_length == 0)
+ GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+ else
+ {
+ if (purb->data_buffer == NULL || purb->data_length == 0)
+ GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ user_buffer = purb->data_buffer;
+ user_buffer_length = purb->data_length;
+ }
+ }
+
+ purb->reference = 0;
+ endp_handle = purb->endp_handle;
+
+ if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
+ {
+ GENDRV_COMPLETE_START_IO(dev_obj, 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 > 16)
+ {
+ 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)
+ {
+ 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 register irp before the urb is scheduled to
+ // avoid race condition.
+ //
+ ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
+ //
+ // the irp can not be canceled at this point, since it is
+ // now the current irp and not in any urb queue. dev_mgr_cancel_irp
+ // can not find it and simply return.
+ //
+ // FIXME: there is a time window that the irp is registered and
+ // the urb is not queued. In the meantime, the cancel
+ // request may come and cause the irp removed from the irp
+ // queue while fail to cancel due to urb not in any urb queue .
+ // Thus from that point on, the irp can not be canceled till it
+ // is completed or hanging there forever.
+ //
+ status = usb_submit_urb(dev_mgr, purb);
+ if (status != STATUS_PENDING)
+ {
+ // unmark the pending bit
+ 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;
+ GENDRV_COMPLETE_START_IO(dev_obj, status, irp);
+ }
+ return;
+
+ ERROR_OUT1:
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+ irp->IoStatus.Information = 0;
+ GENDRV_COMPLETE_START_IO(dev_obj, status, irp);
+ }
+ }
+ GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
}
VOID
-gendrv_clean_up_queued_irps(
-PDEVICE_OBJECT dev_obj
-)
+gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj)
{
- // called when device may not function or about to be removed, need cleanup
+ // called when device may not function or about to be removed, need cleanup
KIRQL cancelIrql;
PIRP irp, cur_irp;
PKDEVICE_QUEUE_ENTRY packet;
- LIST_ENTRY cancel_irps, *pthis;
-
- //
- // cancel all the irps in the queue
- //
- if( dev_obj == NULL )
- return;
-
- InitializeListHead( &cancel_irps );
-
- // remove the irps from device queue
- IoAcquireCancelSpinLock( &cancelIrql );
- cur_irp = dev_obj->CurrentIrp;
- while(( packet = KeRemoveDeviceQueue( &dev_obj->DeviceQueue ) ))
- {
- irp = struct_ptr( packet, IRP, Tail.Overlay.DeviceQueueEntry );
- InsertTailList( &cancel_irps, &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry );
+ LIST_ENTRY cancel_irps, *pthis;
+
+ //
+ // cancel all the irps in the queue
+ //
+ if (dev_obj == NULL)
+ return;
+
+ InitializeListHead(&cancel_irps);
+
+ // remove the irps from device queue
+ IoAcquireCancelSpinLock(&cancelIrql);
+ cur_irp = dev_obj->CurrentIrp;
+ while ((packet = KeRemoveDeviceQueue(&dev_obj->DeviceQueue)))
+ {
+ irp = struct_ptr(packet, IRP, Tail.Overlay.DeviceQueueEntry);
+ InsertTailList(&cancel_irps, &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry);
}
- IoReleaseCancelSpinLock( cancelIrql );
-
- // cancel the irps in process
- // we did not cancel the current irp, it will be done by hcd when
- // disconnect is detected.
- // remove_irp_from_list( &dev_mgr->irp_list, cur_irp, dev_mgr );
-
- while( IsListEmpty( &cancel_irps ) == FALSE )
- {
- pthis = RemoveHeadList( &cancel_irps );
- irp = struct_ptr( pthis, IRP, Tail.Overlay.DeviceQueueEntry.DeviceListEntry );
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_CANCELLED;
- IoCompleteRequest( irp, IO_NO_INCREMENT );
- }
- return;
+ IoReleaseCancelSpinLock(cancelIrql);
+
+ // cancel the irps in process
+ // we did not cancel the current irp, it will be done by hcd when
+ // disconnect is detected.
+ // remove_irp_from_list( &dev_mgr->irp_list, cur_irp, dev_mgr );
+
+ while (IsListEmpty(&cancel_irps) == FALSE)
+ {
+ pthis = RemoveHeadList(&cancel_irps);
+ irp = struct_ptr(pthis, IRP, Tail.Overlay.DeviceQueueEntry.DeviceListEntry);
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ }
+ return;
}
VOID
-gendrv_cancel_queued_irp(
-PDEVICE_OBJECT dev_obj,
-PIRP pirp
-)
+gendrv_cancel_queued_irp(PDEVICE_OBJECT dev_obj, PIRP pirp)
{
- // cancel routine for irps queued in the device queue
- PUSB_DEV_MANAGER dev_mgr;
- PDEVEXT_HEADER pdev_ext_hdr;
-
- pdev_ext_hdr = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
- dev_mgr = pdev_ext_hdr->dev_mgr;
-
- if( dev_obj->CurrentIrp == pirp )
- {
- // just before start_io set the cancel routine to null
- IoReleaseCancelSpinLock( pirp->CancelIrql );
- // we did not IoStartNextPacket, leave it for dev_mgr_cancel_irp, that
- // is user have to call CancelIo again.
- return;
- }
-
- KeRemoveEntryDeviceQueue( &dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry );
- IoReleaseCancelSpinLock( pirp->CancelIrql );
-
- pirp->IoStatus.Information = 0;
- pirp->IoStatus.Status = STATUS_CANCELLED;
- IoCompleteRequest( pirp, IO_NO_INCREMENT );
- // the device queue is moved on, no need to call IoStartNextPacket
- return;
-}
+ // cancel routine for irps queued in the device queue
+ PUSB_DEV_MANAGER dev_mgr;
+ PDEVEXT_HEADER pdev_ext_hdr;
+
+ pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+ dev_mgr = pdev_ext_hdr->dev_mgr;
+
+ if (dev_obj->CurrentIrp == pirp)
+ {
+ // just before start_io set the cancel routine to null
+ IoReleaseCancelSpinLock(pirp->CancelIrql);
+ // we did not IoStartNextPacket, leave it for dev_mgr_cancel_irp, that
+ // is user have to call CancelIo again.
+ return;
+ }
+ KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
+ IoReleaseCancelSpinLock(pirp->CancelIrql);
+
+ pirp->IoStatus.Information = 0;
+ pirp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(pirp, IO_NO_INCREMENT);
+ // the device queue is moved on, no need to call IoStartNextPacket
+ return;
+}
BOOL
-dev_mgr_set_if_driver(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle,
-PUSB_DRIVER pdriver,
-PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle, and must have dev_lock acquired.
-)
+dev_mgr_set_if_driver(PUSB_DEV_MANAGER dev_mgr,
+ DEV_HANDLE if_handle,
+ PUSB_DRIVER pdriver,
+ PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle, and must have dev_lock acquired.
+ )
{
- ULONG i;
- USE_IRQL;
-
- if( dev_mgr == NULL || if_handle == 0 || pdriver == NULL )
- return FALSE;
-
- i = if_idx_from_handle( if_handle );
- if( pdev != NULL )
- {
- if( dev_state( pdev ) < USB_DEV_STATE_BEFORE_ZOMB )
- {
- pdev->usb_config->interf[ i ].pif_drv = pdriver;
- return TRUE;
- }
- return FALSE;
- }
-
- if( usb_query_and_lock_dev( dev_mgr, if_handle, &pdev ) != STATUS_SUCCESS )
- return FALSE;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) != USB_DEV_STATE_ZOMB )
- {
- pdev->usb_config->interf[ i ].pif_drv = pdriver;
- }
- unlock_dev( pdev, TRUE );
- usb_unlock_dev( pdev );
- return TRUE;
+ ULONG i;
+ USE_IRQL;
+
+ if (dev_mgr == NULL || if_handle == 0 || pdriver == NULL)
+ return FALSE;
+
+ i = if_idx_from_handle(if_handle);
+ if (pdev != NULL)
+ {
+ if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
+ {
+ pdev->usb_config->interf[i].pif_drv = pdriver;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (usb_query_and_lock_dev(dev_mgr, if_handle, &pdev) != STATUS_SUCCESS)
+ return FALSE;
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
+ {
+ pdev->usb_config->interf[i].pif_drv = pdriver;
+ }
+ unlock_dev(pdev, TRUE);
+ usb_unlock_dev(pdev);
+ return TRUE;
}
BOOL
-dev_mgr_set_driver(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle,
-PUSB_DRIVER pdriver,
-PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle
-)
+dev_mgr_set_driver(PUSB_DEV_MANAGER dev_mgr,
+ DEV_HANDLE dev_handle,
+ PUSB_DRIVER pdriver,
+ PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle
+ )
{
- USE_IRQL;
-
- if( dev_mgr == NULL || dev_handle == 0 || pdriver == NULL )
- return FALSE;
-
- if( pdev != NULL )
- {
- if( dev_state( pdev ) < USB_DEV_STATE_BEFORE_ZOMB )
- {
- pdev->dev_driver = pdriver;
- return TRUE;
- }
- return FALSE;
- }
-
- if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) != STATUS_SUCCESS )
- return FALSE;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) < USB_DEV_STATE_BEFORE_ZOMB )
- {
- pdev->dev_driver = pdriver;
- }
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
-
- return TRUE;
+ USE_IRQL;
+
+ if (dev_mgr == NULL || dev_handle == 0 || pdriver == NULL)
+ return FALSE;
+
+ if (pdev != NULL)
+ {
+ if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
+ {
+ pdev->dev_driver = pdriver;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
+ return FALSE;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
+ {
+ pdev->dev_driver = pdriver;
+ }
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+
+ return TRUE;
}
-USB_DRIVER g_driver_list[ DEVMGR_MAX_DRIVERS ];
-USB_DEV_MANAGER g_dev_mgr;
+USB_DRIVER g_driver_list[DEVMGR_MAX_DRIVERS];
+USB_DEV_MANAGER g_dev_mgr;
extern ULONG cpu_clock_freq;
-BOOL
-hub_check_reset_port_status(
-PUSB_DEV pdev,
-LONG port_idx
-);
+BOOL hub_check_reset_port_status(PUSB_DEV pdev, LONG port_idx);
-BOOL
-hub_start_next_reset_port(
-PUSB_DEV_MANAGER dev_mgr,
-BOOL from_dpc
-);
+BOOL hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr, BOOL from_dpc);
-VOID
-hub_reexamine_port_status_queue(
-PUSB_DEV hub_dev,
-ULONG port_idx,
-BOOL from_dpc
-);
+VOID hub_reexamine_port_status_queue(PUSB_DEV hub_dev, ULONG port_idx, BOOL from_dpc);
-void
-hub_int_completion(
-PURB purb,
-PVOID pcontext
-);
+void hub_int_completion(PURB purb, PVOID pcontext);
-VOID
-hub_get_port_status_completion(
-PURB purb,
-PVOID context
-);
+VOID hub_get_port_status_completion(PURB purb, PVOID context);
-VOID
-hub_clear_port_feature_completion(
-PURB purb,
-PVOID context
-);
+VOID hub_clear_port_feature_completion(PURB purb, PVOID context);
-VOID
-hub_event_examine_status_que(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context, //hub_ext
-ULONG param //port_idx
-);
+VOID hub_event_examine_status_que(PUSB_DEV pdev, ULONG event, ULONG context, //hub_ext
+ ULONG param //port_idx
+ );
-VOID
-hub_timer_wait_dev_stable(
-PUSB_DEV pdev,
-PVOID context //port-index
-);
+VOID hub_timer_wait_dev_stable(PUSB_DEV pdev,
+ PVOID context //port-index
+ );
-VOID
-hub_event_dev_stable(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context, //hub_ext
-ULONG param //port_idx
-);
+VOID hub_event_dev_stable(PUSB_DEV pdev,
+ ULONG event,
+ ULONG context, //hub_ext
+ ULONG param //port_idx
+ );
-VOID
-hub_post_esq_event(
-PUSB_DEV pdev,
-BYTE port_idx,
-PROCESS_EVENT pe
-);
+VOID hub_post_esq_event(PUSB_DEV pdev, BYTE port_idx, PROCESS_EVENT pe);
-void
-hub_set_cfg_completion(
-PURB purb,
-PVOID pcontext
-);
+void hub_set_cfg_completion(PURB purb, PVOID pcontext);
-void
-hub_get_hub_desc_completion(
-PURB purb,
-PVOID pcontext
-);
+void hub_get_hub_desc_completion(PURB purb, PVOID pcontext);
-NTSTATUS
-hub_start_int_request(
-PUSB_DEV pdev
-);
+NTSTATUS hub_start_int_request(PUSB_DEV pdev);
-BOOL
-hub_remove_reset_event(
-PUSB_DEV pdev,
-ULONG port_idx,
-BOOL from_dpc
-);
+BOOL hub_remove_reset_event(PUSB_DEV pdev, ULONG port_idx, BOOL from_dpc);
-BOOL
-hub_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-);
+BOOL hub_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
-BOOL
-hub_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-);
+BOOL hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
-BOOL
-hub_connect(
-PCONNECT_DATA init_param,
-DEV_HANDLE dev_handle
-);
+BOOL hub_connect(PCONNECT_DATA init_param, DEV_HANDLE dev_handle);
-BOOL
-hub_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL hub_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-BOOL
-hub_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL hub_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-NTSTATUS
-hub_disable_port_request(
-PUSB_DEV pdev,
-UCHAR port_idx
-);
+NTSTATUS hub_disable_port_request(PUSB_DEV pdev, UCHAR port_idx);
-VOID
-hub_start_reset_port_completion(
-PURB purb,
-PVOID context
-);
+VOID hub_start_reset_port_completion(PURB purb, PVOID context);
-BOOL
-dev_mgr_start_config_dev(
-PUSB_DEV pdev
-);
+BOOL dev_mgr_start_config_dev(PUSB_DEV pdev);
-BOOL
-dev_mgr_event_init(
-PUSB_DEV dev, //always null. we do not use this param
-ULONG event,
-ULONG context,
-ULONG param
-);
+BOOL dev_mgr_event_init(PUSB_DEV dev, //always null. we do not use this param
+ ULONG event,
+ ULONG context,
+ ULONG param);
-VOID
-dev_mgr_get_desc_completion(
-PURB purb,
-PVOID context
-);
+VOID dev_mgr_get_desc_completion(PURB purb, PVOID context);
-VOID
-dev_mgr_event_select_driver(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context,
-ULONG param
-);
+VOID dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param);
-LONG
-dev_mgr_score_driver_for_dev(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver,
-PUSB_DEVICE_DESC pdev_desc
-);
+LONG dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc);
-NTSTATUS
-dev_mgr_destroy_usb_config(
-PUSB_CONFIGURATION pcfg
-);
+NTSTATUS dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg);
-BOOL
-dev_mgr_start_select_driver(
-PUSB_DEV pdev
-);
+BOOL dev_mgr_start_select_driver(PUSB_DEV pdev);
-VOID
-dev_mgr_cancel_irp(
-PDEVICE_OBJECT pdev_obj,
-PIRP pirp
-);
+VOID dev_mgr_cancel_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp);
BOOL
-init_event_pool(
-PUSB_EVENT_POOL pool
-)
+init_event_pool(PUSB_EVENT_POOL pool)
{
- int i;
+ int i;
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- if( ( pool->event_array = usb_alloc_mem(
- NonPagedPool,
- sizeof( USB_EVENT ) * MAX_EVENTS ) )
- == NULL)
- return FALSE;
+ if ((pool->event_array = usb_alloc_mem(NonPagedPool, sizeof(USB_EVENT) * MAX_EVENTS)) == NULL)
+ return FALSE;
- InitializeListHead( &pool->free_que );
- KeInitializeSpinLock( &pool->pool_lock );
- pool->total_count = MAX_EVENTS;
- pool->free_count = 0;
+ InitializeListHead(&pool->free_que);
+ KeInitializeSpinLock(&pool->pool_lock);
+ pool->total_count = MAX_EVENTS;
+ pool->free_count = 0;
- for( i = 0; i < MAX_EVENTS; i++ )
- {
- free_event( pool, &pool->event_array[ i ] );
- }
+ for(i = 0; i < MAX_EVENTS; i++)
+ {
+ free_event(pool, &pool->event_array[i]);
+ }
- return TRUE;
+ return TRUE;
}
BOOL
-free_event(
-PUSB_EVENT_POOL pool,
-PUSB_EVENT pevent
-)
+free_event(PUSB_EVENT_POOL pool, PUSB_EVENT pevent)
{
- if( pool == NULL || pevent == NULL )
- {
- return FALSE;
- }
+ if (pool == NULL || pevent == NULL)
+ {
+ return FALSE;
+ }
- RtlZeroMemory( pevent, sizeof( USB_EVENT ) );
- InsertTailList( &pool->free_que, (PLIST_ENTRY) pevent );
- pool->free_count++;
- usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "free_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, pevent ) );
+ RtlZeroMemory(pevent, sizeof(USB_EVENT));
+ InsertTailList(&pool->free_que, (PLIST_ENTRY) pevent);
+ pool->free_count++;
+ usb_dbg_print(DBGLVL_MAXIMUM + 1,
+ ("free_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, pevent));
- return TRUE;
+ return TRUE;
}
+//null if failed
PUSB_EVENT
-alloc_event(
-PUSB_EVENT_POOL pool,
-LONG count
-) //null if failed
+alloc_event(PUSB_EVENT_POOL pool, LONG count)
{
- PUSB_EVENT new;
- if( pool == NULL || count != 1)
- return NULL;
+ PUSB_EVENT NewEvent;
+ if (pool == NULL || count != 1)
+ return NULL;
- if( pool->free_count == 0 )
- return NULL;
+ if (pool->free_count == 0)
+ return NULL;
- new = ( PUSB_EVENT )RemoveHeadList( &pool->free_que );
- pool->free_count --;
+ NewEvent = (PUSB_EVENT) RemoveHeadList(&pool->free_que);
+ pool->free_count--;
- usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "alloc_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, new ) );
- return new;
+ usb_dbg_print(DBGLVL_MAXIMUM + 1,
+ ("alloc_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, NewEvent));
+ return NewEvent;
}
BOOL
-destroy_event_pool(
-PUSB_EVENT_POOL pool
-)
+destroy_event_pool(PUSB_EVENT_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- InitializeListHead( &pool->free_que );
- pool->free_count = pool->total_count = 0;
- usb_free_mem( pool->event_array );
- pool->event_array = NULL;
+ InitializeListHead(&pool->free_que);
+ pool->free_count = pool->total_count = 0;
+ usb_free_mem(pool->event_array);
+ pool->event_array = NULL;
- return TRUE;
+ return TRUE;
}
VOID
-event_list_default_process_event(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context,
-ULONG param
-)
-{}
+event_list_default_process_event(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param)
+{
+}
//----------------------------------------------------------
//timer_svc pool routines
BOOL
-init_timer_svc_pool(
-PTIMER_SVC_POOL pool
-)
+init_timer_svc_pool(PTIMER_SVC_POOL pool)
{
- int i;
- if( pool == NULL )
- return FALSE;
-
- pool->timer_svc_array = usb_alloc_mem( NonPagedPool, sizeof( TIMER_SVC ) * MAX_TIMER_SVCS );
- InitializeListHead( &pool->free_que );
- pool->free_count = 0;
- pool->total_count = MAX_TIMER_SVCS;
- KeInitializeSpinLock( &pool->pool_lock );
-
- for( i = 0; i < MAX_TIMER_SVCS; i++ )
- {
- free_timer_svc( pool, &pool->timer_svc_array[ i ] );
- }
-
- return TRUE;
+ int i;
+
+ if (pool == NULL)
+ return FALSE;
+
+ pool->timer_svc_array = usb_alloc_mem(NonPagedPool, sizeof(TIMER_SVC) * MAX_TIMER_SVCS);
+ InitializeListHead(&pool->free_que);
+ pool->free_count = 0;
+ pool->total_count = MAX_TIMER_SVCS;
+ KeInitializeSpinLock(&pool->pool_lock);
+
+ for(i = 0; i < MAX_TIMER_SVCS; i++)
+ {
+ free_timer_svc(pool, &pool->timer_svc_array[i]);
+ }
+
+ return TRUE;
}
BOOL
-free_timer_svc(
-PTIMER_SVC_POOL pool,
-PTIMER_SVC ptimer
-)
+free_timer_svc(PTIMER_SVC_POOL pool, PTIMER_SVC ptimer)
{
- if( pool == NULL || ptimer == NULL )
- return FALSE;
+ if (pool == NULL || ptimer == NULL)
+ return FALSE;
- RtlZeroMemory( ptimer, sizeof( TIMER_SVC ) );
- InsertTailList( &pool->free_que, ( PLIST_ENTRY )&ptimer->timer_svc_link );
- pool->free_count ++;
+ RtlZeroMemory(ptimer, sizeof(TIMER_SVC));
+ InsertTailList(&pool->free_que, (PLIST_ENTRY) & ptimer->timer_svc_link);
+ pool->free_count++;
- return TRUE;
+ return TRUE;
}
+//null if failed
PTIMER_SVC
-alloc_timer_svc(
-PTIMER_SVC_POOL pool,
-LONG count
-) //null if failed
+alloc_timer_svc(PTIMER_SVC_POOL pool, LONG count)
{
- PTIMER_SVC new;
- if( pool == NULL || count != 1 )
- return NULL;
+ PTIMER_SVC NewTimer;
- if( pool->free_count <= 0 )
- return NULL;
+ if (pool == NULL || count != 1)
+ return NULL;
- new = ( PTIMER_SVC )RemoveHeadList( &pool->free_que );
- pool->free_count --;
- return new;
+ if (pool->free_count <= 0)
+ return NULL;
+
+ NewTimer = (PTIMER_SVC) RemoveHeadList(&pool->free_que);
+ pool->free_count--;
+ return NewTimer;
}
BOOL
-destroy_timer_svc_pool(
-PTIMER_SVC_POOL pool
-)
+destroy_timer_svc_pool(PTIMER_SVC_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- usb_free_mem( pool->timer_svc_array );
- pool->timer_svc_array = NULL;
- InitializeListHead( &pool->free_que );
- pool->free_count = 0;
- pool->total_count = 0;
+ usb_free_mem(pool->timer_svc_array);
+ pool->timer_svc_array = NULL;
+ InitializeListHead(&pool->free_que);
+ pool->free_count = 0;
+ pool->total_count = 0;
- return TRUE;
+ return TRUE;
}
BOOL
-dev_mgr_post_event(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_EVENT event
-)
+dev_mgr_post_event(PUSB_DEV_MANAGER dev_mgr, PUSB_EVENT event)
{
- KIRQL old_irql;
+ KIRQL old_irql;
- if( dev_mgr == NULL || event == NULL )
- return FALSE;
+ if (dev_mgr == NULL || event == NULL)
+ return FALSE;
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
- InsertTailList( &dev_mgr->event_list, &event->event_link );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+ InsertTailList(&dev_mgr->event_list, &event->event_link);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
- KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE );
- return TRUE;
+ KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
+ return TRUE;
}
VOID
-event_list_default_process_queue(
-PLIST_HEAD event_list,
-PUSB_EVENT_POOL event_pool,
-PUSB_EVENT usb_event,
-PUSB_EVENT out_event
-)
+event_list_default_process_queue(PLIST_HEAD event_list,
+ PUSB_EVENT_POOL event_pool, PUSB_EVENT usb_event, PUSB_EVENT out_event)
{
- //remove the first event from the event list, and copy it to
- //out_event
+ //remove the first event from the event list, and copy it to
+ //out_event
- if( event_list == NULL || event_pool == NULL || usb_event == NULL || out_event == NULL )
- return;
+ if (event_list == NULL || event_pool == NULL || usb_event == NULL || out_event == NULL)
+ return;
- RemoveEntryList( &usb_event->event_link );
- RtlCopyMemory( out_event, usb_event, sizeof( USB_EVENT ) );
- free_event( event_pool, usb_event );
- return;
+ RemoveEntryList(&usb_event->event_link);
+ RtlCopyMemory(out_event, usb_event, sizeof(USB_EVENT));
+ free_event(event_pool, usb_event);
+ return;
}
BOOL
-psq_enqueue(
-PPORT_STATUS_QUEUE psq,
-ULONG status
-)
+psq_enqueue(PPORT_STATUS_QUEUE psq, ULONG status)
{
- if( psq == NULL )
- return FALSE;
+ if (psq == NULL)
+ return FALSE;
- if( psq_is_full( psq ) )
- return FALSE;
+ if (psq_is_full(psq))
+ return FALSE;
- psq->port_status[ psq->status_count ].wPortChange = HIWORD( status );
- psq->port_status[ psq->status_count ].wPortStatus = LOWORD( status );
+ psq->port_status[psq->status_count].wPortChange = HIWORD(status);
+ psq->port_status[psq->status_count].wPortStatus = LOWORD(status);
- psq->status_count++;
+ psq->status_count++;
- usb_dbg_print( DBGLVL_MAXIMUM, ("psq_enqueue(): last status=0x%x, status count=0x%x, port_flag=0x%x\n", \
- status, \
- psq->status_count, \
- psq->port_flags ) );
- return TRUE;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("psq_enqueue(): last status=0x%x, status count=0x%x, port_flag=0x%x\n",
+ status, psq->status_count, psq->port_flags));
+ return TRUE;
}
VOID
-psq_init(
-PPORT_STATUS_QUEUE psq
-)
+psq_init(PPORT_STATUS_QUEUE psq)
{
- RtlZeroMemory( psq, sizeof( PORT_STATUS_QUEUE ) );
- psq->port_flags = STATE_IDLE | USB_PORT_FLAG_DISABLE;
+ RtlZeroMemory(psq, sizeof(PORT_STATUS_QUEUE));
+ psq->port_flags = STATE_IDLE | USB_PORT_FLAG_DISABLE;
}
+//return 0xffffffff if no element
ULONG
-psq_outqueue(
-PPORT_STATUS_QUEUE psq
-) //return 0xffffffff if no element
+psq_outqueue(PPORT_STATUS_QUEUE psq)
{
- ULONG status;
+ ULONG status;
- if( psq == NULL )
- return 0;
+ if (psq == NULL)
+ return 0;
- if( psq_is_empty( psq ) )
- return 0;
+ if (psq_is_empty(psq))
+ return 0;
- status = ( ( PULONG )&psq->port_status )[ 0 ];
- psq->port_status[ 0 ] = psq->port_status[ 1 ];
- psq->port_status[ 1 ] = psq->port_status[ 2 ];
- psq->port_status[ 2 ] = psq->port_status[ 3 ];
- psq->status_count--;
+ status = ((PULONG) & psq->port_status)[0];
+ psq->port_status[0] = psq->port_status[1];
+ psq->port_status[1] = psq->port_status[2];
+ psq->port_status[2] = psq->port_status[3];
+ psq->status_count--;
- return status;
+ return status;
}
BOOL
-psq_push(
-PPORT_STATUS_QUEUE psq,
-ULONG status
-)
+psq_push(PPORT_STATUS_QUEUE psq, ULONG status)
{
- if( psq == NULL )
- return FALSE;
+ if (psq == NULL)
+ return FALSE;
- status = ( ( PULONG )&psq->port_status )[ 0 ];
- psq->port_status[ 3 ] = psq->port_status[ 2 ];
- psq->port_status[ 2 ] = psq->port_status[ 1 ];
- psq->port_status[ 1 ] = psq->port_status[ 0 ];
+ status = ((PULONG) & psq->port_status)[0];
+ psq->port_status[3] = psq->port_status[2];
+ psq->port_status[2] = psq->port_status[1];
+ psq->port_status[1] = psq->port_status[0];
- ( ( PULONG )&psq->port_status )[ 0 ]= status;
+ ((PULONG) & psq->port_status)[0] = status;
- psq->status_count++;
- psq->status_count = ( ( 4 > psq->status_count ) ? psq->status_count : 4 );
+ psq->status_count++;
+ psq->status_count = ((4 > psq->status_count) ? psq->status_count : 4);
- return TRUE;
+ return TRUE;
}
VOID
-dev_mgr_driver_entry_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdrvr
-)
+dev_mgr_driver_entry_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr)
{
- // Device Info
+ // Device Info
- RtlZeroMemory( pdrvr, sizeof( USB_DRIVER ) * DEVMGR_MAX_DRIVERS );
+ RtlZeroMemory(pdrvr, sizeof(USB_DRIVER) * DEVMGR_MAX_DRIVERS);
- pdrvr[ RH_DRIVER_IDX ].driver_init = rh_driver_init; // in fact, this routine will init the rh device rather that the driver struct.
- pdrvr[ RH_DRIVER_IDX ].driver_destroy = rh_driver_destroy; // we do not need rh to destroy currently, since that may means fatal hardware failure
+ pdrvr[RH_DRIVER_IDX].driver_init = rh_driver_init; // in fact, this routine will init the rh device rather that the driver struct.
+ pdrvr[RH_DRIVER_IDX].driver_destroy = rh_driver_destroy; // we do not need rh to destroy currently, since that may means fatal hardware failure
- pdrvr[ HUB_DRIVER_IDX ].driver_init = hub_driver_init; //no need, since dev_mgr is also a hub driver
- pdrvr[ HUB_DRIVER_IDX ].driver_destroy = hub_driver_destroy;
+ pdrvr[HUB_DRIVER_IDX].driver_init = hub_driver_init; //no need, since dev_mgr is also a hub driver
+ pdrvr[HUB_DRIVER_IDX].driver_destroy = hub_driver_destroy;
- pdrvr[ UMSS_DRIVER_IDX ].driver_init = umss_if_driver_init;
- pdrvr[ UMSS_DRIVER_IDX ].driver_destroy = umss_if_driver_destroy;
+ pdrvr[UMSS_DRIVER_IDX].driver_init = umss_if_driver_init;
+ pdrvr[UMSS_DRIVER_IDX].driver_destroy = umss_if_driver_destroy;
- pdrvr[ COMP_DRIVER_IDX ].driver_init = compdev_driver_init;
- pdrvr[ COMP_DRIVER_IDX ].driver_destroy = compdev_driver_destroy;
+ pdrvr[COMP_DRIVER_IDX].driver_init = compdev_driver_init;
+ pdrvr[COMP_DRIVER_IDX].driver_destroy = compdev_driver_destroy;
- pdrvr[ GEN_DRIVER_IDX ].driver_init = gendrv_driver_init;
- pdrvr[ GEN_DRIVER_IDX ].driver_destroy = gendrv_driver_destroy;
+ pdrvr[GEN_DRIVER_IDX].driver_init = gendrv_driver_init;
+ pdrvr[GEN_DRIVER_IDX].driver_destroy = gendrv_driver_destroy;
- pdrvr[ GEN_IF_DRIVER_IDX ].driver_init = gendrv_if_driver_init;
- pdrvr[ GEN_IF_DRIVER_IDX ].driver_destroy = gendrv_if_driver_destroy;
+ pdrvr[GEN_IF_DRIVER_IDX].driver_init = gendrv_if_driver_init;
+ pdrvr[GEN_IF_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy;
}
BOOL
-dev_mgr_strobe(
-PUSB_DEV_MANAGER dev_mgr
-)
+dev_mgr_strobe(PUSB_DEV_MANAGER dev_mgr)
{
- PUSB_EVENT pevent;
- HANDLE thread_handle;
-
- if( dev_mgr == NULL )
- return FALSE;
- if( dev_mgr->hcd_count == 0 )
- return FALSE;
-
- dev_mgr->term_flag = FALSE;
-
- if( dev_mgr->hcd_count == 0 )
- return FALSE;
-
- KeInitializeSpinLock( &dev_mgr->event_list_lock );
- InitializeListHead( &dev_mgr->event_list );
- init_event_pool( &dev_mgr->event_pool );
-
- pevent = alloc_event( &dev_mgr->event_pool, 1 );
- if( pevent == NULL )
- {
- destroy_event_pool( &dev_mgr->event_pool );
- return FALSE;
- }
-
- pevent->flags = USB_EVENT_FLAG_ACTIVE;
- pevent->event = USB_EVENT_INIT_DEV_MGR;
-
- pevent->process_queue = event_list_default_process_queue;
- pevent->process_event = dev_mgr_event_init;
-
- pevent->context = ( ULONG )dev_mgr;
-
- KeInitializeEvent( &dev_mgr->wake_up_event,
- SynchronizationEvent,
- FALSE );
-
- InsertTailList( &dev_mgr->event_list, &pevent->event_link );
-
- if( PsCreateSystemThread(
- &thread_handle,
- 0,
- NULL,
- NULL,
- NULL,
- dev_mgr_thread,
- dev_mgr )
- != STATUS_SUCCESS )
- {
- destroy_event_pool( &dev_mgr->event_pool );
- return FALSE;
- }
-
- ObReferenceObjectByHandle(
- thread_handle,
- THREAD_ALL_ACCESS,
- NULL,
- KernelMode,
- (PVOID*) &dev_mgr->pthread,
- NULL);
-
- ZwClose( thread_handle );
-
- return TRUE;
+ PUSB_EVENT pevent;
+ HANDLE thread_handle;
+
+ if (dev_mgr == NULL)
+ return FALSE;
+ if (dev_mgr->hcd_count == 0)
+ return FALSE;
+
+ dev_mgr->term_flag = FALSE;
+
+ if (dev_mgr->hcd_count == 0)
+ return FALSE;
+
+ KeInitializeSpinLock(&dev_mgr->event_list_lock);
+ InitializeListHead(&dev_mgr->event_list);
+ init_event_pool(&dev_mgr->event_pool);
+
+ pevent = alloc_event(&dev_mgr->event_pool, 1);
+ if (pevent == NULL)
+ {
+ destroy_event_pool(&dev_mgr->event_pool);
+ return FALSE;
+ }
+
+ pevent->flags = USB_EVENT_FLAG_ACTIVE;
+ pevent->event = USB_EVENT_INIT_DEV_MGR;
+
+ pevent->process_queue = event_list_default_process_queue;
+ pevent->process_event = dev_mgr_event_init;
+
+ pevent->context = (ULONG) dev_mgr;
+
+ KeInitializeEvent(&dev_mgr->wake_up_event, SynchronizationEvent, FALSE);
+
+ InsertTailList(&dev_mgr->event_list, &pevent->event_link);
+
+ if (PsCreateSystemThread(&thread_handle, 0, NULL, NULL, NULL, dev_mgr_thread, dev_mgr) != STATUS_SUCCESS)
+ {
+ destroy_event_pool(&dev_mgr->event_pool);
+ return FALSE;
+ }
+
+ ObReferenceObjectByHandle(thread_handle,
+ THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) & dev_mgr->pthread, NULL);
+
+ ZwClose(thread_handle);
+
+ return TRUE;
}
BOOL
-dev_mgr_event_init(
-PUSB_DEV pdev, //always null. we do not use this param
-ULONG event,
-ULONG context,
-ULONG param
-)
+dev_mgr_event_init(PUSB_DEV pdev, //always null. we do not use this param
+ ULONG event, ULONG context, ULONG param)
{
- LARGE_INTEGER due_time;
- PUSB_DEV_MANAGER dev_mgr;
- LONG i;
+ LARGE_INTEGER due_time;
+ PUSB_DEV_MANAGER dev_mgr;
+ LONG i;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_event_init(): dev_mgr=0x%x, event=0x%x\n", context, event ) );
- dev_mgr = ( PUSB_DEV_MANAGER ) context;
- if( dev_mgr == NULL )
- return FALSE;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_init(): dev_mgr=0x%x, event=0x%x\n", context, event));
+ dev_mgr = (PUSB_DEV_MANAGER) context;
+ if (dev_mgr == NULL)
+ return FALSE;
- if( event != USB_EVENT_INIT_DEV_MGR )
- return FALSE;
+ if (event != USB_EVENT_INIT_DEV_MGR)
+ return FALSE;
//dev_mgr->root_hub = NULL;
- KeInitializeTimer( &dev_mgr->dev_mgr_timer );
+ KeInitializeTimer(&dev_mgr->dev_mgr_timer);
- KeInitializeDpc( &dev_mgr->dev_mgr_timer_dpc,
- dev_mgr_timer_dpc_callback,
- ( PVOID )dev_mgr );
+ KeInitializeDpc(&dev_mgr->dev_mgr_timer_dpc, dev_mgr_timer_dpc_callback, (PVOID) dev_mgr);
- KeInitializeSpinLock( &dev_mgr->timer_svc_list_lock );
- InitializeListHead( &dev_mgr->timer_svc_list );
- init_timer_svc_pool( &dev_mgr->timer_svc_pool );
- dev_mgr->timer_click = 0;
+ KeInitializeSpinLock(&dev_mgr->timer_svc_list_lock);
+ InitializeListHead(&dev_mgr->timer_svc_list);
+ init_timer_svc_pool(&dev_mgr->timer_svc_pool);
+ dev_mgr->timer_click = 0;
- init_irp_list( &dev_mgr->irp_list );
+ init_irp_list(&dev_mgr->irp_list);
- KeInitializeSpinLock( &dev_mgr->dev_list_lock );
- InitializeListHead( &dev_mgr->dev_list );
+ KeInitializeSpinLock(&dev_mgr->dev_list_lock);
+ InitializeListHead(&dev_mgr->dev_list);
- dev_mgr->hub_count = 0;
- InitializeListHead( &dev_mgr->hub_list );
+ dev_mgr->hub_count = 0;
+ InitializeListHead(&dev_mgr->hub_list);
- dev_mgr->conn_count = 0;
- dev_mgr->driver_list = g_driver_list;
+ dev_mgr->conn_count = 0;
+ dev_mgr->driver_list = g_driver_list;
- dev_mgr_driver_entry_init( dev_mgr, dev_mgr->driver_list );
+ dev_mgr_driver_entry_init(dev_mgr, dev_mgr->driver_list);
- for( i = 0; i < DEVMGR_MAX_DRIVERS; i++ )
- {
- if( dev_mgr->driver_list[ i ].driver_init == NULL )
- continue;
+ for(i = 0; i < DEVMGR_MAX_DRIVERS; i++)
+ {
+ if (dev_mgr->driver_list[i].driver_init == NULL)
+ continue;
- if( dev_mgr->driver_list[ i ].driver_init( dev_mgr, &dev_mgr->driver_list[ i ] ) == FALSE )
- break;
- }
- if( i == DEVMGR_MAX_DRIVERS )
- {
- due_time.QuadPart = -( DEV_MGR_TIMER_INTERVAL_NS - 10 );
+ if (dev_mgr->driver_list[i].driver_init(dev_mgr, &dev_mgr->driver_list[i]) == FALSE)
+ break;
+ }
+ if (i == DEVMGR_MAX_DRIVERS)
+ {
+ due_time.QuadPart = -(DEV_MGR_TIMER_INTERVAL_NS - 10);
- KeSetTimerEx( &dev_mgr->dev_mgr_timer,
- due_time,
- DEV_MGR_TIMER_INTERVAL_MS,
- &dev_mgr->dev_mgr_timer_dpc );
+ KeSetTimerEx(&dev_mgr->dev_mgr_timer,
+ due_time, DEV_MGR_TIMER_INTERVAL_MS, &dev_mgr->dev_mgr_timer_dpc);
- return TRUE;
- }
+ return TRUE;
+ }
- i--;
+ i--;
- for( ; i >= 0; i-- )
- {
- if( dev_mgr->driver_list[ i ].driver_destroy )
- dev_mgr->driver_list[ i ].driver_destroy( dev_mgr, &dev_mgr->driver_list[ i ] );
- }
+ for(; i >= 0; i--)
+ {
+ if (dev_mgr->driver_list[i].driver_destroy)
+ dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
+ }
- KeCancelTimer( &dev_mgr->dev_mgr_timer );
- KeRemoveQueueDpc( &dev_mgr->dev_mgr_timer_dpc );
- return FALSE;
+ KeCancelTimer(&dev_mgr->dev_mgr_timer);
+ KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
+ return FALSE;
}
-VOID dev_mgr_destroy(
-PUSB_DEV_MANAGER dev_mgr
-)
+VOID
+dev_mgr_destroy(PUSB_DEV_MANAGER dev_mgr)
{
- LONG i;
- // oops...
- KeCancelTimer ( &dev_mgr->dev_mgr_timer );
- KeRemoveQueueDpc( &dev_mgr->dev_mgr_timer_dpc );
+ LONG i;
+ // oops...
+ KeCancelTimer(&dev_mgr->dev_mgr_timer);
+ KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
- for( i = DEVMGR_MAX_DRIVERS - 1; i >= 0; i-- )
- dev_mgr->driver_list[ i ].driver_destroy( dev_mgr, &dev_mgr->driver_list[ i ]);
+ for(i = DEVMGR_MAX_DRIVERS - 1; i >= 0; i--)
+ dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
- destroy_irp_list( &dev_mgr->irp_list );
- destroy_timer_svc_pool( &dev_mgr->timer_svc_pool );
- destroy_event_pool( &dev_mgr->event_pool );
+ destroy_irp_list(&dev_mgr->irp_list);
+ destroy_timer_svc_pool(&dev_mgr->timer_svc_pool);
+ destroy_event_pool(&dev_mgr->event_pool);
}
VOID
-dev_mgr_thread(
-PVOID context
-)
+dev_mgr_thread(PVOID context)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_EVENT pevent;
- PLIST_ENTRY pthis, pnext;
- USB_EVENT usb_event;
- LARGE_INTEGER time_out;
- NTSTATUS status;
- BOOL dev_mgr_inited;
- KIRQL old_irql;
- LONG i;
-
- dev_mgr = ( PUSB_DEV_MANAGER )context;
- dev_mgr_inited = FALSE;
- usb_cal_cpu_freq();
- time_out.u.LowPart = ( 10 * 1000 * 1000 ) * 100 - 1; //1 minutes
- time_out.u.HighPart = 0;
- time_out.QuadPart = -time_out.QuadPart;
-
- //usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "dev_mgr_thread(): current uhci status=0x%x\n", uhci_status( dev_mgr->pdev_ext->uhci ) ) );
-
- while( dev_mgr->term_flag == FALSE )
- {
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
- if( IsListEmpty( &dev_mgr->event_list ) == TRUE )
- {
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- status = KeWaitForSingleObject(
- &dev_mgr->wake_up_event,
- Executive,
- KernelMode,
- TRUE,
- &time_out
- );
- continue;
- }
-
- // usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_thread(): current element in event list is 0x%x\n", \
- // dbg_count_list( &dev_mgr->event_list ) ) );
-
- dev_mgr_inited = TRUE; //since we have post one event, if this statement is executed, dev_mgr_event_init must be called sometime later or earlier
-
- ListFirst( &dev_mgr->event_list, pthis );
- pevent = struct_ptr( pthis, USB_EVENT, event_link );
-
- while( pevent && ( ( pevent->flags & USB_EVENT_FLAG_ACTIVE ) == 0 ) )
- {
- //skip inactive ones
- ListNext( &dev_mgr->event_list, &pevent->event_link, pnext );
- pevent = struct_ptr( pnext, USB_EVENT, event_link );
- }
-
- if( pevent != NULL )
- {
- if( pevent->process_queue == NULL )
- pevent->process_queue = event_list_default_process_queue;
-
- pevent->process_queue( &dev_mgr->event_list,
- &dev_mgr->event_pool,
- pevent,
- &usb_event );
- }
- else
- {
- //no active event
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- status = KeWaitForSingleObject(
- &dev_mgr->wake_up_event,
- Executive,
- KernelMode,
- TRUE,
- &time_out // 10 minutes
- );
-
- usb_dbg_print( DBGLVL_MAXIMUM, ("dev_mgr_thread(): wake up, reason=0x%x\n", status ) );
- continue;
- }
-
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
-
- if( usb_event.process_event )
- {
- usb_event.process_event( usb_event.pdev,
- usb_event.event,
- usb_event.context,
- usb_event.param);
- }
- else
- {
- event_list_default_process_event( usb_event.pdev,
- usb_event.event,
- usb_event.context,
- usb_event.param);
- }
- }
-
- if( dev_mgr_inited )
- {
- for( i = 0; i < dev_mgr->hcd_count; i++ )
- dev_mgr_disconnect_dev( dev_mgr->hcd_array[ i ]->hcd_get_root_hub( dev_mgr->hcd_array[ i ] ) );
- dev_mgr_destroy( dev_mgr );
- }
- PsTerminateSystemThread( 0 );
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_EVENT pevent;
+ PLIST_ENTRY pthis, pnext;
+ USB_EVENT usb_event;
+ LARGE_INTEGER time_out;
+ NTSTATUS status;
+ BOOL dev_mgr_inited;
+ KIRQL old_irql;
+ LONG i;
+
+ dev_mgr = (PUSB_DEV_MANAGER) context;
+ dev_mgr_inited = FALSE;
+ usb_cal_cpu_freq();
+ time_out.u.LowPart = (10 * 1000 * 1000) * 100 - 1; //1 minutes
+ time_out.u.HighPart = 0;
+ time_out.QuadPart = -time_out.QuadPart;
+
+ //usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "dev_mgr_thread(): current uhci status=0x%x\n", uhci_status( dev_mgr->pdev_ext->uhci ) ) );
+
+ while (dev_mgr->term_flag == FALSE)
+ {
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+ if (IsListEmpty(&dev_mgr->event_list) == TRUE)
+ {
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out);
+ continue;
+ }
+
+ // usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_thread(): current element in event list is 0x%x\n", \
+ // dbg_count_list( &dev_mgr->event_list ) ) );
+
+ dev_mgr_inited = TRUE; //since we have post one event, if this statement is executed, dev_mgr_event_init must be called sometime later or earlier
+
+ ListFirst(&dev_mgr->event_list, pthis);
+ pevent = struct_ptr(pthis, USB_EVENT, event_link);
+
+ while (pevent && ((pevent->flags & USB_EVENT_FLAG_ACTIVE) == 0))
+ {
+ //skip inactive ones
+ ListNext(&dev_mgr->event_list, &pevent->event_link, pnext);
+ pevent = struct_ptr(pnext, USB_EVENT, event_link);
+ }
+
+ if (pevent != NULL)
+ {
+ if (pevent->process_queue == NULL)
+ pevent->process_queue = event_list_default_process_queue;
+
+ pevent->process_queue(&dev_mgr->event_list, &dev_mgr->event_pool, pevent, &usb_event);
+ }
+ else
+ {
+ //no active event
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out // 10 minutes
+ );
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_thread(): wake up, reason=0x%x\n", status));
+ continue;
+ }
+
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+
+ if (usb_event.process_event)
+ {
+ usb_event.process_event(usb_event.pdev, usb_event.event, usb_event.context, usb_event.param);
+ }
+ else
+ {
+ event_list_default_process_event(usb_event.pdev,
+ usb_event.event, usb_event.context, usb_event.param);
+ }
+ }
+
+ if (dev_mgr_inited)
+ {
+ for(i = 0; i < dev_mgr->hcd_count; i++)
+ dev_mgr_disconnect_dev(dev_mgr->hcd_array[i]->hcd_get_root_hub(dev_mgr->hcd_array[i]));
+ dev_mgr_destroy(dev_mgr);
+ }
+ PsTerminateSystemThread(0);
}
VOID
-dev_mgr_timer_dpc_callback(
-PKDPC Dpc,
-PVOID context,
-PVOID SystemArgument1,
-PVOID SystemArgument2
-)
+dev_mgr_timer_dpc_callback(PKDPC Dpc, PVOID context, PVOID SystemArgument1, PVOID SystemArgument2)
{
- PUSB_DEV_MANAGER dev_mgr;
- LIST_HEAD templist;
- PLIST_ENTRY pthis, pnext;
- static ULONG ticks = 0;
-
- ticks++;
- dev_mgr = ( PUSB_DEV_MANAGER ) context;
- if( dev_mgr == NULL )
- return;
-
- dev_mgr->timer_click ++;
- InitializeListHead( &templist );
-
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->timer_svc_list_lock );
- if( IsListEmpty( &dev_mgr->timer_svc_list ) == TRUE )
- {
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->timer_svc_list_lock );
- return;
- }
-
- ListFirst( &dev_mgr->timer_svc_list, pthis );
- while( pthis )
- {
- ( ( PTIMER_SVC )pthis )->counter++;
- ListNext( &dev_mgr->timer_svc_list, pthis, pnext );
- if( ( ( PTIMER_SVC )pthis )->counter >= ( ( PTIMER_SVC )pthis )->threshold )
- {
- RemoveEntryList( pthis );
- InsertTailList( &templist, pthis );
- }
- pthis = pnext;
- }
-
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->timer_svc_list_lock );
-
-
- while( IsListEmpty( &templist ) == FALSE )
- {
- pthis = RemoveHeadList( &templist );
- ( ( PTIMER_SVC )pthis )->func( ( ( PTIMER_SVC )pthis )->pdev, ( PVOID )( ( PTIMER_SVC )pthis )->context );
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->timer_svc_list_lock );
- free_timer_svc( &dev_mgr->timer_svc_pool, ( PTIMER_SVC )pthis );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->timer_svc_list_lock );
- }
+ PUSB_DEV_MANAGER dev_mgr;
+ LIST_HEAD templist;
+ PLIST_ENTRY pthis, pnext;
+ static ULONG ticks = 0;
+
+ ticks++;
+ dev_mgr = (PUSB_DEV_MANAGER) context;
+ if (dev_mgr == NULL)
+ return;
+
+ dev_mgr->timer_click++;
+ InitializeListHead(&templist);
+
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
+ if (IsListEmpty(&dev_mgr->timer_svc_list) == TRUE)
+ {
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
+ return;
+ }
+
+ ListFirst(&dev_mgr->timer_svc_list, pthis);
+ while (pthis)
+ {
+ ((PTIMER_SVC) pthis)->counter++;
+ ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
+ if (((PTIMER_SVC) pthis)->counter >= ((PTIMER_SVC) pthis)->threshold)
+ {
+ RemoveEntryList(pthis);
+ InsertTailList(&templist, pthis);
+ }
+ pthis = pnext;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
+
+
+ while (IsListEmpty(&templist) == FALSE)
+ {
+ pthis = RemoveHeadList(&templist);
+ ((PTIMER_SVC) pthis)->func(((PTIMER_SVC) pthis)->pdev, (PVOID) ((PTIMER_SVC) pthis)->context);
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
+ free_timer_svc(&dev_mgr->timer_svc_pool, (PTIMER_SVC) pthis);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
+ }
}
BOOL
-dev_mgr_request_timer_svc(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DEV pdev,
-ULONG context,
-ULONG due_time,
-TIMER_SVC_HANDLER handler
-)
+dev_mgr_request_timer_svc(PUSB_DEV_MANAGER dev_mgr,
+ PUSB_DEV pdev, ULONG context, ULONG due_time, TIMER_SVC_HANDLER handler)
{
- PTIMER_SVC timer_svc;
- KIRQL old_irql;
-
- if( dev_mgr == NULL || pdev == NULL || due_time == 0 || handler == NULL )
- return FALSE;
-
- KeAcquireSpinLock( &dev_mgr->timer_svc_list_lock, &old_irql );
- timer_svc = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- if( timer_svc == NULL )
- {
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return FALSE;
- }
- timer_svc->pdev = pdev;
- timer_svc->threshold = due_time;
- timer_svc->func = handler;
- timer_svc->counter = 0;
-
- InsertTailList( &dev_mgr->timer_svc_list, &timer_svc->timer_svc_link );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return TRUE;
+ PTIMER_SVC timer_svc;
+ KIRQL old_irql;
+
+ if (dev_mgr == NULL || pdev == NULL || due_time == 0 || handler == NULL)
+ return FALSE;
+
+ KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
+ timer_svc = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ if (timer_svc == NULL)
+ {
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return FALSE;
+ }
+ timer_svc->pdev = pdev;
+ timer_svc->threshold = due_time;
+ timer_svc->func = handler;
+ timer_svc->counter = 0;
+
+ InsertTailList(&dev_mgr->timer_svc_list, &timer_svc->timer_svc_link);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return TRUE;
}
BYTE
-dev_mgr_alloc_addr(
-PUSB_DEV_MANAGER dev_mgr,
-PHCD hcd
-)
+dev_mgr_alloc_addr(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
- // alloc a usb addr for the device within 1-128
- ULONG i;
- if( dev_mgr == NULL || hcd == NULL )
- return 0xff;
+ // alloc a usb addr for the device within 1-128
+ ULONG i;
+ if (dev_mgr == NULL || hcd == NULL)
+ return 0xff;
- return hcd->hcd_alloc_addr( hcd );
+ return hcd->hcd_alloc_addr(hcd);
}
BOOL
-dev_mgr_free_addr(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DEV pdev,
-BYTE addr
-)
+dev_mgr_free_addr(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, BYTE addr)
{
- PHCD hcd;
- if( addr & 0x80 )
- return FALSE;
-
- if( dev_mgr == NULL || pdev == NULL )
- return FALSE;
-
- hcd = pdev->hcd;
- if( hcd == NULL )
- return FALSE;
- hcd->hcd_free_addr( hcd, addr );
- return TRUE;
+ PHCD hcd;
+ if (addr & 0x80)
+ return FALSE;
+
+ if (dev_mgr == NULL || pdev == NULL)
+ return FALSE;
+
+ hcd = pdev->hcd;
+ if (hcd == NULL)
+ return FALSE;
+ hcd->hcd_free_addr(hcd, addr);
+ return TRUE;
}
PUSB_DEV
-dev_mgr_alloc_device(
-PUSB_DEV_MANAGER dev_mgr,
-PHCD hcd
-)
+dev_mgr_alloc_device(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
- BYTE addr;
- PUSB_DEV pdev;
+ BYTE addr;
+ PUSB_DEV pdev;
- if( ( addr = dev_mgr_alloc_addr( dev_mgr, hcd ) ) == 0xff )
- return NULL;
+ if ((addr = dev_mgr_alloc_addr(dev_mgr, hcd)) == 0xff)
+ return NULL;
- pdev = usb_alloc_mem( NonPagedPool, sizeof( USB_DEV ) );
- if( pdev == NULL )
- return NULL;
+ pdev = usb_alloc_mem(NonPagedPool, sizeof(USB_DEV));
+ if (pdev == NULL)
+ return NULL;
- RtlZeroMemory( pdev, sizeof( USB_DEV ) );
+ RtlZeroMemory(pdev, sizeof(USB_DEV));
- KeInitializeSpinLock( &pdev->dev_lock );
- dev_mgr->conn_count++;
+ KeInitializeSpinLock(&pdev->dev_lock);
+ dev_mgr->conn_count++;
- pdev->flags = USB_DEV_STATE_RESET; //class | cur_state | low speed
- pdev->ref_count = 0;
- pdev->dev_addr = addr;
+ pdev->flags = USB_DEV_STATE_RESET; //class | cur_state | low speed
+ pdev->ref_count = 0;
+ pdev->dev_addr = addr;
- pdev->hcd = hcd;
+ pdev->hcd = hcd;
- pdev->dev_id = dev_mgr->conn_count; //will be used to compose dev_handle
+ pdev->dev_id = dev_mgr->conn_count; //will be used to compose dev_handle
- InitializeListHead( &pdev->default_endp.urb_list );
- pdev->default_endp.pusb_if = ( PUSB_INTERFACE )pdev;
- pdev->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP; //toggle | busy-count | stall | default-endp
+ InitializeListHead(&pdev->default_endp.urb_list);
+ pdev->default_endp.pusb_if = (PUSB_INTERFACE) pdev;
+ pdev->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP; //toggle | busy-count | stall | default-endp
- return pdev;
+ return pdev;
}
VOID
-dev_mgr_free_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DEV pdev
-)
+dev_mgr_free_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev)
{
- if( pdev == NULL || dev_mgr == NULL )
- return;
-
- dev_mgr_free_addr( dev_mgr, pdev, pdev->dev_addr );
- if( pdev->usb_config && pdev != pdev->hcd->hcd_get_root_hub( pdev->hcd ) )
- {
- //root hub has its config and desc buf allocated together,
- //so no usb_config allocated seperately
- dev_mgr_destroy_usb_config( pdev->usb_config );
- pdev->usb_config = NULL;
- }
- if( pdev->desc_buf )
- {
- usb_free_mem( pdev->desc_buf );
- pdev->desc_buf = NULL;
- }
- usb_free_mem( pdev );
- pdev = NULL;
- return;
-}
+ if (pdev == NULL || dev_mgr == NULL)
+ return;
-BOOL
-rh_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
-{
- LONG i;
- PHCD hcd;
-
- if( dev_mgr == NULL )
- return FALSE;
-
- for( i = 0; i < dev_mgr->hcd_count; i++ )
- {
- hcd = dev_mgr->hcd_array[ i ];
- // if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
- // continue;
- rh_destroy( hcd->hcd_get_root_hub( hcd ) );
- }
- return TRUE;
+ dev_mgr_free_addr(dev_mgr, pdev, pdev->dev_addr);
+ if (pdev->usb_config && pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd))
+ {
+ //root hub has its config and desc buf allocated together,
+ //so no usb_config allocated seperately
+ dev_mgr_destroy_usb_config(pdev->usb_config);
+ pdev->usb_config = NULL;
+ }
+ if (pdev->desc_buf)
+ {
+ usb_free_mem(pdev->desc_buf);
+ pdev->desc_buf = NULL;
+ }
+ usb_free_mem(pdev);
+ pdev = NULL;
+ return;
}
BOOL
-rh_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+rh_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
+ LONG i;
+ PHCD hcd;
- PUSB_DEV rh;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_ENDPOINT_DESC pendp_desc;
- PUSB_CONFIGURATION pconfig;
- PUSB_INTERFACE pif;
- PUSB_ENDPOINT pendp;
- PHUB2_EXTENSION phub_ext;
- PTIMER_SVC ptimer;
- PURB purb;
- NTSTATUS status;
- PHCD hcd;
- LONG i;
-
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- //init driver structure, no PNP table functions
- 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 = 0xffff; // 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 = USB_CLASS_HUB; // 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 root hub"; // Driver name for Name Registry
- pdriver->driver_desc.dev_class = USB_CLASS_HUB;
- pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
- pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
-
- //pdriver->driver_init = rh_driver_init; // initialized in dev_mgr_init_driver
- //pdriver->driver_destroy = rh_driver_destroy;
- pdriver->disp_tbl.version = 1; // other fields of the dispatch table is not used since rh needs no pnp
-
- pdriver->driver_ext = 0;
- pdriver->driver_ext_size = 0;
-
- for( i = 0; i < dev_mgr->hcd_count; i++ )
- {
- hcd = dev_mgr->hcd_array[ i ];
- //if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
- // continue;
-
- if( ( rh = dev_mgr_alloc_device( dev_mgr, hcd ) )== NULL )
- return FALSE;
-
- rh->parent_dev = NULL;
- rh->port_idx = 0;
- rh->hcd = hcd;
- rh->flags = USB_DEV_CLASS_ROOT_HUB | USB_DEV_STATE_CONFIGURED;
-
- if( usb2( hcd ) )
- rh->flags |= USB_DEV_FLAG_HIGH_SPEED;
-
- rh->dev_driver = pdriver;
-
- rh->desc_buf_size = sizeof( USB_DEVICE_DESC )
- + sizeof( USB_CONFIGURATION_DESC )
- + sizeof( USB_INTERFACE_DESC )
- + sizeof( USB_ENDPOINT_DESC )
- + sizeof( USB_CONFIGURATION )
- + sizeof( HUB2_EXTENSION );
-
- rh->desc_buf = usb_alloc_mem( NonPagedPool, rh->desc_buf_size );
-
- if( rh->desc_buf == NULL )
- {
- return FALSE;
- }
- else
- RtlZeroMemory( rh->desc_buf, rh->desc_buf_size );
-
- rh->pusb_dev_desc = ( PUSB_DEVICE_DESC )rh->desc_buf;
-
- rh->pusb_dev_desc->bLength = sizeof( USB_DEVICE_DESC );
- rh->pusb_dev_desc->bDescriptorType = USB_DT_DEVICE;
- rh->pusb_dev_desc->bcdUSB = 0x110;
- if( usb2( hcd ) )
- rh->pusb_dev_desc->bcdUSB = 0x200;
- rh->pusb_dev_desc->bDeviceClass = USB_CLASS_HUB;
- rh->pusb_dev_desc->bDeviceSubClass = 0;
- rh->pusb_dev_desc->bDeviceProtocol = 0;
- rh->pusb_dev_desc->bMaxPacketSize0 = 8;
- if( usb2( hcd ) )
- {
- rh->pusb_dev_desc->bDeviceProtocol = 1;
- rh->pusb_dev_desc->bMaxPacketSize0 = 64;
- }
- rh->pusb_dev_desc->idVendor = 0;
- rh->pusb_dev_desc->idProduct = 0;
- rh->pusb_dev_desc->bcdDevice = 0x100;
- rh->pusb_dev_desc->iManufacturer = 0;
- rh->pusb_dev_desc->iProduct = 0;
- rh->pusb_dev_desc->iSerialNumber = 0;
- rh->pusb_dev_desc->bNumConfigurations = 1;
-
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )&rh->desc_buf[ sizeof( USB_DEVICE_DESC ) ];
- pif_desc = ( PUSB_INTERFACE_DESC ) &pconfig_desc[ 1 ];
- pendp_desc = ( PUSB_ENDPOINT_DESC ) &pif_desc[ 1 ];
-
- pconfig_desc->bLength = sizeof( USB_CONFIGURATION_DESC );
- pconfig_desc->bDescriptorType = USB_DT_CONFIG;
-
- pconfig_desc->wTotalLength = sizeof( USB_CONFIGURATION_DESC )
- + sizeof( USB_INTERFACE_DESC )
- + sizeof( USB_ENDPOINT_DESC );
-
- pconfig_desc->bNumInterfaces = 1;
- pconfig_desc->bConfigurationValue = 1;
- pconfig_desc->iConfiguration = 0;
- pconfig_desc->bmAttributes = 0Xe0; //self-powered and support remoke wakeup
- pconfig_desc->MaxPower = 0;
-
- pif_desc->bLength = sizeof( USB_INTERFACE_DESC );
- pif_desc->bDescriptorType = USB_DT_INTERFACE;
- pif_desc->bInterfaceNumber = 0;
- pif_desc->bAlternateSetting = 0;
- pif_desc->bNumEndpoints = 1;
- pif_desc->bInterfaceClass = USB_CLASS_HUB;
- pif_desc->bInterfaceSubClass = 0;
- pif_desc->bInterfaceProtocol = 0;
- pif_desc->iInterface = 0;
-
- pendp_desc->bLength = sizeof( USB_ENDPOINT_DESC );
- pendp_desc->bDescriptorType = USB_DT_ENDPOINT;
- pendp_desc->bEndpointAddress = 0x81;
- pendp_desc->bmAttributes = 0x03;
- pendp_desc->wMaxPacketSize = 8;
- pendp_desc->bInterval = USB_HUB_INTERVAL;
- if( usb2( hcd ) )
- pendp_desc->bInterval = 0x0c;
-
- pconfig = rh->usb_config = ( PUSB_CONFIGURATION )&pendp_desc[ 1 ];
- rh->active_config_idx = 0;
- pconfig->pusb_config_desc = pconfig_desc;
- pconfig->if_count = 1;
- pconfig->pusb_dev = rh;
- pif = &pconfig->interf[ 0 ];
-
- pif->endp_count = 1;
- pendp = &pif->endp[ 0 ];
- pif->pusb_config = pconfig;;
- pif->pusb_if_desc = pif_desc;
-
- pif->if_ext_size = 0;
- pif->if_ext = NULL;
-
- phub_ext = ( PHUB2_EXTENSION )&pconfig[ 1 ];
- phub_ext->port_count = 2;
-
- if( usb2( hcd ) )
- {
- // port count is configurable in usb2
- hcd->hcd_dispatch( hcd, HCD_DISP_READ_PORT_COUNT, &phub_ext->port_count );
- }
-
- {
- int j;
- for( j = 0; j < phub_ext->port_count; j++ )
- {
- psq_init( &phub_ext->port_status_queue[ j ] );
- phub_ext->child_dev[ j ] = NULL;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "rh_driver_init(): port[ %d ].flag=0x%x\n", \
- j, phub_ext->port_status_queue[ j ].port_flags ) );
- }
- }
-
- phub_ext->pif = pif;
- phub_ext->hub_desc.bLength = sizeof( USB_HUB_DESCRIPTOR );
- phub_ext->hub_desc.bDescriptorType = USB_DT_HUB;
- phub_ext->hub_desc.bNbrPorts = ( UCHAR )phub_ext->port_count;
- phub_ext->hub_desc.wHubCharacteristics = 0;
- phub_ext->hub_desc.bPwrOn2PwrGood = 0;
- phub_ext->hub_desc.bHubContrCurrent = 50;
-
- rh->dev_ext = ( PBYTE )phub_ext;
- rh->dev_ext_size = sizeof( HUB2_EXTENSION );
-
- rh->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP;
- InitializeListHead( &rh->default_endp.urb_list );
- rh->default_endp.pusb_if = ( PUSB_INTERFACE )rh;
- rh->default_endp.pusb_endp_desc = NULL; //???
- rh->time_out_count = 0;
- rh->error_count = 0;
-
- InitializeListHead( &pendp->urb_list );
- pendp->flags = 0;
- pendp->pusb_endp_desc = pendp_desc;
- pendp->pusb_if = pif;
-
- //add to device list
- InsertTailList( &dev_mgr->dev_list, &rh->dev_link );
- hcd->hcd_set_root_hub( hcd, rh );
- status = hub_start_int_request( rh );
- pdriver->driver_ext = 0;
- }
- return TRUE;
+ if (dev_mgr == NULL)
+ return FALSE;
+
+ for(i = 0; i < dev_mgr->hcd_count; i++)
+ {
+ hcd = dev_mgr->hcd_array[i];
+ // if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
+ // continue;
+ rh_destroy(hcd->hcd_get_root_hub(hcd));
+ }
+ return TRUE;
}
BOOL
-rh_destroy(
-PUSB_DEV pdev
-)
-//to be the reverse of what init does, we assume that the timer is now killed
-//int is disconnected and the hub thread will not process event anymore
+rh_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUSB_DEV rh;
- PLIST_ENTRY pthis, pnext;
- PUSB_DEV_MANAGER dev_mgr;
- if( pdev == NULL )
- return FALSE;
+ PUSB_DEV rh;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+ PUSB_INTERFACE_DESC pif_desc;
+ PUSB_ENDPOINT_DESC pendp_desc;
+ PUSB_CONFIGURATION pconfig;
+ PUSB_INTERFACE pif;
+ PUSB_ENDPOINT pendp;
+ PHUB2_EXTENSION phub_ext;
+ PTIMER_SVC ptimer;
+ PURB purb;
+ NTSTATUS status;
+ PHCD hcd;
+ LONG i;
+
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ //init driver structure, no PNP table functions
+ 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 = 0xffff; // 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 = USB_CLASS_HUB; // 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 root hub"; // Driver name for Name Registry
+ pdriver->driver_desc.dev_class = USB_CLASS_HUB;
+ pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
+ pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
+
+ //pdriver->driver_init = rh_driver_init; // initialized in dev_mgr_init_driver
+ //pdriver->driver_destroy = rh_driver_destroy;
+ pdriver->disp_tbl.version = 1; // other fields of the dispatch table is not used since rh needs no pnp
+
+ pdriver->driver_ext = 0;
+ pdriver->driver_ext_size = 0;
+
+ for(i = 0; i < dev_mgr->hcd_count; i++)
+ {
+ hcd = dev_mgr->hcd_array[i];
+ //if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
+ // continue;
- dev_mgr = dev_mgr_from_dev( pdev );
+ if ((rh = dev_mgr_alloc_device(dev_mgr, hcd)) == NULL)
+ return FALSE;
- //???
- rh = pdev->hcd->hcd_get_root_hub( pdev->hcd );
- if( rh == pdev )
- {
- //free all the buf
- dev_mgr_free_device(dev_mgr, rh );
- //dev_mgr->root_hub = NULL;
- }
+ rh->parent_dev = NULL;
+ rh->port_idx = 0;
+ rh->hcd = hcd;
+ rh->flags = USB_DEV_CLASS_ROOT_HUB | USB_DEV_STATE_CONFIGURED;
- return TRUE;
-}
+ if (usb2(hcd))
+ rh->flags |= USB_DEV_FLAG_HIGH_SPEED;
-VOID
-rh_timer_svc_int_completion(
-PUSB_DEV pdev,
-PVOID context
-)
-{
- PUSB_EVENT pevent;
- PURB purb;
- ULONG status, i;
- PHCD hcd;
- USE_IRQL;
-
- if( pdev == NULL || context == NULL )
- return;
-
- purb = ( PURB )context;
-
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- pdev->ref_count -= 2; // one for timer_svc and one for urb, for those rh requests
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "rh_timer_svc_int_completion(): the dev is zomb, 0x%x\n", pdev ) );
- return;
- }
-
- hcd = pdev->hcd;
- if( purb->data_length < 1 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- unlock_dev( pdev, TRUE );
- goto LBL_OUT;
- }
-
- pdev->hcd->hcd_dispatch( pdev->hcd, HCD_DISP_READ_RH_DEV_CHANGE, purb->data_buffer );
- purb->status = STATUS_SUCCESS;
- unlock_dev( pdev, TRUE );
+ rh->dev_driver = pdriver;
-LBL_OUT:
- hcd->hcd_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, TRUE );
- pdev->ref_count -= 2; // one for timer_svc and one for urb, for those rh requests
- // that completed immediately, the ref_count of the dev for
- // that urb won't increment and for normal hub request
- // completion, hcd_generic_urb_completion will be called
- // by the xhci_dpc_callback, and the ref_count for the urb
- // is maintained there. So only rh's timer-svc cares refcount
- // when hcd_generic_urb_completion is called.
- usb_dbg_print( DBGLVL_MAXIMUM, ( "rh_timer_svc_int_completion(): rh's ref_count=0x%x\n", pdev->ref_count ) );
- unlock_dev( pdev, TRUE );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "rh_timer_svc_int_completion(): exitiing...\n" ) );
- return;
-}
+ rh->desc_buf_size = sizeof(USB_DEVICE_DESC)
+ + sizeof(USB_CONFIGURATION_DESC)
+ + sizeof(USB_INTERFACE_DESC)
+ + sizeof(USB_ENDPOINT_DESC) + sizeof(USB_CONFIGURATION) + sizeof(HUB2_EXTENSION);
-VOID
-rh_timer_svc_reset_port_completion(
-PUSB_DEV pdev,
-PVOID context
-)
-{
- PURB purb;
- ULONG i;
- USHORT port_num;
- PHUB2_EXTENSION hub_ext;
- PLIST_ENTRY pthis, pnext;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_CTRL_SETUP_PACKET psetup;
-
- USE_IRQL;
-
- if( pdev == NULL || context == NULL )
- return;
-
- dev_mgr = dev_mgr_from_dev( pdev ); //readonly and hold ref_count
-
- //block the rh polling
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->timer_svc_list_lock );
- if( IsListEmpty( &dev_mgr->timer_svc_list ) == FALSE )
- {
- ListFirst( &dev_mgr->timer_svc_list, pthis );
- while( pthis )
- {
- if( ( ( PTIMER_SVC )pthis )->pdev == pdev && \
- ( ( PTIMER_SVC )pthis )->threshold == RH_INTERVAL )
- {
- ( ( PTIMER_SVC )pthis )->threshold = RH_INTERVAL + 0x800000;
- break;
- }
-
- ListNext( &dev_mgr->timer_svc_list, pthis, pnext );
- pthis = pnext;
- }
- }
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->timer_svc_list_lock );
-
- purb = ( PURB )context;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- //purb->status = STATUS_ERROR;
- //pdev->hcd->hcd_generic_urb_completion( purb, purb->context );
-
- pdev->ref_count -= 2;
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- return;
- }
-
- i = pdev->hcd->hcd_rh_reset_port( pdev->hcd, ( UCHAR )psetup->wIndex );
-
- hub_ext = hub_ext_from_dev( pdev );
-
- {
- USHORT temp;
- PUCHAR pbuf;
- if( psetup->wIndex < 16 )
- {
- temp = 1 << psetup->wIndex;
- pbuf = ( PUCHAR )&temp;
- if( temp > 128 )
- pbuf++;
- hub_ext->int_data_buf[ psetup->wIndex / 8 ] |= *pbuf;
- if( i == TRUE )
- hub_ext->rh_port_status[ psetup->wIndex ].wPortChange |= USB_PORT_STAT_C_RESET;
- else // notify that is not a high speed device, will lost definitely
- hub_ext->rh_port_status[ psetup->wIndex ].wPortChange |= USB_PORT_STAT_C_CONNECTION;
- }
- }
-
- //???how to construct port status map
- // decrease the timer_svc ref-count
- pdev->ref_count --;
- unlock_dev( pdev, TRUE );
-
- purb->status = STATUS_SUCCESS;
- //we delegate the completion to the rh_timer_svc_int_completion.
- //this function is equivalent to hub_start_reset_port_completion
-
- usb_free_mem( purb );
-
- //expire the rh polling timer
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->timer_svc_list_lock );
- if( IsListEmpty( &dev_mgr->timer_svc_list ) == FALSE )
- {
- ListFirst( &dev_mgr->timer_svc_list, pthis );
- while( pthis )
- {
- if( ( ( PTIMER_SVC )pthis )->pdev == pdev && \
- ( ( PTIMER_SVC )pthis )->threshold == RH_INTERVAL + 0x800000 )
- {
- ( ( PTIMER_SVC )pthis )->counter = RH_INTERVAL;
- ( ( PTIMER_SVC )pthis )->threshold = RH_INTERVAL;
- break;
- }
-
- ListNext( &dev_mgr->timer_svc_list, pthis, pnext );
- pthis = pnext;
- }
- }
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->timer_svc_list_lock );
-
- lock_dev( pdev, TRUE );
- pdev->ref_count--;
- unlock_dev( pdev, TRUE );
- return;
-}
+ rh->desc_buf = usb_alloc_mem(NonPagedPool, rh->desc_buf_size);
-VOID
-dev_mgr_disconnect_dev(
-PUSB_DEV pdev
-)
-//called when a disconnect is detected on the port
-{
- PLIST_ENTRY pthis, pnext;
- PHUB2_EXTENSION phub_ext;
- PUSB_CONFIGURATION pconfig;
- PUSB_INTERFACE pif;
- PUSB_DEV_MANAGER dev_mgr;
- PHCD hcd;
- BOOL is_hub, found;
- ULONG dev_id;
-
- int i;
- USE_IRQL;
-
- if( pdev == NULL )
- return;
-
- found = FALSE;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_disconnect_dev(): entering, pdev=0x%x\n", pdev ) );
- lock_dev( pdev, FALSE );
- pdev->flags &= ~ USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_BEFORE_ZOMB;
- dev_mgr = dev_mgr_from_dev( pdev );
- unlock_dev( pdev, FALSE );
-
- // notify dev_driver that the dev stops function before any operations
- if( pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_stop )
- pdev->dev_driver->disp_tbl.dev_stop( dev_mgr, dev_handle_from_dev( pdev ) );
-
- //safe to use the dev pointer in this function.
- lock_dev( pdev, FALSE );
- pdev->flags &= ~ USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_ZOMB;
- hcd = pdev->hcd;
- dev_id = pdev->dev_id;
- unlock_dev( pdev, FALSE );
-
- if( dev_mgr == NULL )
- return;
-
- hcd->hcd_remove_device( hcd, pdev );
-
- //disconnect its children
- if( ( pdev->flags & USB_DEV_CLASS_MASK ) == USB_DEV_CLASS_HUB || \
- ( pdev->flags & USB_DEV_CLASS_MASK ) == USB_DEV_CLASS_ROOT_HUB )
- {
- phub_ext = hub_ext_from_dev( pdev );
- if( phub_ext )
- {
- for( i = 1; i <= phub_ext->port_count; i++ )
- {
- if( phub_ext->child_dev[ i ] )
- {
- dev_mgr_disconnect_dev( phub_ext->child_dev[ i ] );
- phub_ext->child_dev[ i ] = NULL;
- }
- }
- }
- }
-
- pconfig = pdev->usb_config;
-
- //remove event belong to the dev
- is_hub = ( ( pdev->flags & USB_DEV_CLASS_MASK ) == USB_DEV_CLASS_HUB );
-
- if( phub_ext && is_hub )
- {
- for( i = 1; i <= phub_ext->port_count; i++ )
- {
- found = hub_remove_reset_event( pdev, i, FALSE );
- if( found )
- break;
- }
- }
-
- //free event of the dev from the event list
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
- ListFirst( &dev_mgr->event_list, pthis );
- while( pthis )
- {
- ListNext( &dev_mgr->event_list, pthis, pnext );
- if( ( ( PUSB_EVENT )pthis )->pdev == pdev )
- {
- PLIST_ENTRY p1;
- RemoveEntryList( pthis );
- if( ( ( ( PUSB_EVENT )pthis )->flags & USB_EVENT_FLAG_QUE_TYPE )
- != USB_EVENT_FLAG_NOQUE )
- {
- //has a queue, re-insert the queue
- if( p1 = ( PLIST_ENTRY )( ( PUSB_EVENT )pthis )->pnext )
- {
- InsertHeadList( &dev_mgr->event_list, p1 );
- free_event( &dev_mgr->event_pool, struct_ptr( pthis, USB_EVENT, event_link ) );
- pthis = p1;
- //note: this queue will be examined again in the next loop
- //to find the matched dev in the queue
- continue;
- }
- }
- free_event( &dev_mgr->event_pool, struct_ptr( pthis, USB_EVENT, event_link ) );
- }
- else if( ( ( ( ( PUSB_EVENT )pthis )->flags & USB_EVENT_FLAG_QUE_TYPE )
- != USB_EVENT_FLAG_NOQUE ) && ( ( PUSB_EVENT )pthis )->pnext )
- {
- //has a queue, examine the queue
- PUSB_EVENT p1, p2;
- p1 = ( PUSB_EVENT )pthis;
- p2 = p1->pnext;
- while( p2 )
- {
- if( p2->pdev == pdev )
- {
- p1->pnext = p2->pnext;
- p2->pnext = NULL;
- free_event( &dev_mgr->event_pool, p2 );
- p2 = p1->pnext;
- }
- else
- {
- p1 = p2;
- p2 = p2->pnext;
- }
- }
- }
- pthis = pnext;
- }
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
-
- // found indicates the reset event on one of the dev's port in process
- if( found )
- hub_start_next_reset_port( dev_mgr_from_dev( pdev ), FALSE );
-
- // remove timer-svc belonging to the dev
- KeAcquireSpinLock( &dev_mgr->timer_svc_list_lock, &old_irql );
- ListFirst( &dev_mgr->timer_svc_list, pthis );
- i = 0;
- while( pthis )
- {
- ListNext( &dev_mgr->timer_svc_list, pthis, pnext );
- if( ( ( PUSB_EVENT )pthis )->pdev == pdev )
- {
- RemoveEntryList( pthis );
- free_timer_svc( &dev_mgr->timer_svc_pool, struct_ptr( pthis, TIMER_SVC, timer_svc_link ) );
- i++;
- }
- pthis = pnext;
- }
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
-
- // release the refcount
- if( i )
- {
- lock_dev( pdev, FALSE );
- pdev->ref_count -= i;
- unlock_dev( pdev, FALSE );
- }
-
- // wait for all the reference count be released
- for( ; ; )
- {
- LARGE_INTEGER interval;
-
- lock_dev( pdev, FALSE );
- if( pdev->ref_count == 0 )
- {
- unlock_dev( pdev, FALSE );
- break;
- }
- unlock_dev( pdev, FALSE );
- // Wait two ms.
- interval.QuadPart = -20000;
- KeDelayExecutionThread( KernelMode, FALSE, &interval );
- }
-
- if( pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_disconnect )
- pdev->dev_driver->disp_tbl.dev_disconnect( dev_mgr, dev_handle_from_dev( pdev ) );
-
- // we put it here to let handle valid before disconnect
- KeAcquireSpinLock( &dev_mgr->dev_list_lock, &old_irql );
- ListFirst( &dev_mgr->dev_list, pthis );
- while( pthis )
- {
- if( ( ( PUSB_DEV )pthis ) == pdev )
- {
- RemoveEntryList( pthis );
- break;
- }
- ListNext( &dev_mgr->dev_list, pthis, pnext );
- pthis = pnext;
- }
- KeReleaseSpinLock( &dev_mgr->dev_list_lock, old_irql );
-
-
- if( pdev != pdev->hcd->hcd_get_root_hub( pdev->hcd ) )
- {
- dev_mgr_free_device( dev_mgr, pdev );
- }
- else
- {
- //rh_destroy( pdev );
- //TRAP();
- //destroy it in dev_mgr_destroy
- }
-
- return;
-}
+ if (rh->desc_buf == NULL)
+ {
+ return FALSE;
+ }
+ else
+ RtlZeroMemory(rh->desc_buf, rh->desc_buf_size);
+
+ rh->pusb_dev_desc = (PUSB_DEVICE_DESC) rh->desc_buf;
+
+ rh->pusb_dev_desc->bLength = sizeof(USB_DEVICE_DESC);
+ rh->pusb_dev_desc->bDescriptorType = USB_DT_DEVICE;
+ rh->pusb_dev_desc->bcdUSB = 0x110;
+ if (usb2(hcd))
+ rh->pusb_dev_desc->bcdUSB = 0x200;
+ rh->pusb_dev_desc->bDeviceClass = USB_CLASS_HUB;
+ rh->pusb_dev_desc->bDeviceSubClass = 0;
+ rh->pusb_dev_desc->bDeviceProtocol = 0;
+ rh->pusb_dev_desc->bMaxPacketSize0 = 8;
+ if (usb2(hcd))
+ {
+ rh->pusb_dev_desc->bDeviceProtocol = 1;
+ rh->pusb_dev_desc->bMaxPacketSize0 = 64;
+ }
+ rh->pusb_dev_desc->idVendor = 0;
+ rh->pusb_dev_desc->idProduct = 0;
+ rh->pusb_dev_desc->bcdDevice = 0x100;
+ rh->pusb_dev_desc->iManufacturer = 0;
+ rh->pusb_dev_desc->iProduct = 0;
+ rh->pusb_dev_desc->iSerialNumber = 0;
+ rh->pusb_dev_desc->bNumConfigurations = 1;
+
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) & rh->desc_buf[sizeof(USB_DEVICE_DESC)];
+ pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1];
+ pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
+
+ pconfig_desc->bLength = sizeof(USB_CONFIGURATION_DESC);
+ pconfig_desc->bDescriptorType = USB_DT_CONFIG;
+
+ pconfig_desc->wTotalLength = sizeof(USB_CONFIGURATION_DESC)
+ + sizeof(USB_INTERFACE_DESC) + sizeof(USB_ENDPOINT_DESC);
+
+ pconfig_desc->bNumInterfaces = 1;
+ pconfig_desc->bConfigurationValue = 1;
+ pconfig_desc->iConfiguration = 0;
+ pconfig_desc->bmAttributes = 0Xe0; //self-powered and support remoke wakeup
+ pconfig_desc->MaxPower = 0;
+
+ pif_desc->bLength = sizeof(USB_INTERFACE_DESC);
+ pif_desc->bDescriptorType = USB_DT_INTERFACE;
+ pif_desc->bInterfaceNumber = 0;
+ pif_desc->bAlternateSetting = 0;
+ pif_desc->bNumEndpoints = 1;
+ pif_desc->bInterfaceClass = USB_CLASS_HUB;
+ pif_desc->bInterfaceSubClass = 0;
+ pif_desc->bInterfaceProtocol = 0;
+ pif_desc->iInterface = 0;
+
+ pendp_desc->bLength = sizeof(USB_ENDPOINT_DESC);
+ pendp_desc->bDescriptorType = USB_DT_ENDPOINT;
+ pendp_desc->bEndpointAddress = 0x81;
+ pendp_desc->bmAttributes = 0x03;
+ pendp_desc->wMaxPacketSize = 8;
+ pendp_desc->bInterval = USB_HUB_INTERVAL;
+ if (usb2(hcd))
+ pendp_desc->bInterval = 0x0c;
+
+ pconfig = rh->usb_config = (PUSB_CONFIGURATION) & pendp_desc[1];
+ rh->active_config_idx = 0;
+ pconfig->pusb_config_desc = pconfig_desc;
+ pconfig->if_count = 1;
+ pconfig->pusb_dev = rh;
+ pif = &pconfig->interf[0];
+
+ pif->endp_count = 1;
+ pendp = &pif->endp[0];
+ pif->pusb_config = pconfig;;
+ pif->pusb_if_desc = pif_desc;
+
+ pif->if_ext_size = 0;
+ pif->if_ext = NULL;
+
+ phub_ext = (PHUB2_EXTENSION) & pconfig[1];
+ phub_ext->port_count = 2;
+
+ if (usb2(hcd))
+ {
+ // port count is configurable in usb2
+ hcd->hcd_dispatch(hcd, HCD_DISP_READ_PORT_COUNT, &phub_ext->port_count);
+ }
-BOOL
-hub_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
-{
- //init driver structure, no PNP table functions
- 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 = 0xffff; // 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 = USB_CLASS_HUB; // 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 hub"; // Driver name for Name Registry
- pdriver->driver_desc.dev_class = USB_CLASS_HUB;
- pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
- pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
-
- //pdriver->driver_init = hub_driver_init; // initialized in dev_mgr_init_driver
- //pdriver->driver_destroy = hub_driver_destroy;
-
- pdriver->driver_ext = 0;
- pdriver->driver_ext_size = 0;
-
- pdriver->disp_tbl.version = 1;
- pdriver->disp_tbl.dev_connect = hub_connect;
- pdriver->disp_tbl.dev_disconnect = hub_disconnect;
- pdriver->disp_tbl.dev_stop = hub_stop;
- pdriver->disp_tbl.dev_reserved = NULL;
-
- return TRUE;
+ {
+ int j;
+ for(j = 0; j < phub_ext->port_count; j++)
+ {
+ psq_init(&phub_ext->port_status_queue[j]);
+ phub_ext->child_dev[j] = NULL;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("rh_driver_init(): port[ %d ].flag=0x%x\n",
+ j, phub_ext->port_status_queue[j].port_flags));
+ }
+ }
+
+ phub_ext->pif = pif;
+ phub_ext->hub_desc.bLength = sizeof(USB_HUB_DESCRIPTOR);
+ phub_ext->hub_desc.bDescriptorType = USB_DT_HUB;
+ phub_ext->hub_desc.bNbrPorts = (UCHAR) phub_ext->port_count;
+ phub_ext->hub_desc.wHubCharacteristics = 0;
+ phub_ext->hub_desc.bPwrOn2PwrGood = 0;
+ phub_ext->hub_desc.bHubContrCurrent = 50;
+
+ rh->dev_ext = (PBYTE) phub_ext;
+ rh->dev_ext_size = sizeof(HUB2_EXTENSION);
+
+ rh->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP;
+ InitializeListHead(&rh->default_endp.urb_list);
+ rh->default_endp.pusb_if = (PUSB_INTERFACE) rh;
+ rh->default_endp.pusb_endp_desc = NULL; //???
+ rh->time_out_count = 0;
+ rh->error_count = 0;
+
+ InitializeListHead(&pendp->urb_list);
+ pendp->flags = 0;
+ pendp->pusb_endp_desc = pendp_desc;
+ pendp->pusb_if = pif;
+
+ //add to device list
+ InsertTailList(&dev_mgr->dev_list, &rh->dev_link);
+ hcd->hcd_set_root_hub(hcd, rh);
+ status = hub_start_int_request(rh);
+ pdriver->driver_ext = 0;
+ }
+ return TRUE;
}
+//to be the reverse of what init does, we assume that the timer is now killed
+//int is disconnected and the hub thread will not process event anymore
BOOL
-hub_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+rh_destroy(PUSB_DEV pdev)
{
- pdriver->driver_ext = NULL;
- return TRUE;
-}
-void
+ PUSB_DEV rh;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_DEV_MANAGER dev_mgr;
-hub_reset_pipe_completion(
-PURB purb, //only for reference, can not be released
-PVOID context
-)
-{
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- NTSTATUS status;
-
- USE_IRQL;
-
- if( purb == NULL )
- {
- return;
- }
-
- pdev = purb->pdev;
- pendp = purb->pendp;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- return;
- }
-
- if( usb_error( purb->status ) )
- {
- //simply retry it
- unlock_dev( pdev, TRUE );
- //usb_free_mem( purb );
- return;
- }
- unlock_dev( pdev, TRUE );
-
- pdev = purb->pdev;
- hub_start_int_request( pdev );
- return;
+ if (pdev == NULL)
+ return FALSE;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ //???
+ rh = pdev->hcd->hcd_get_root_hub(pdev->hcd);
+ if (rh == pdev)
+ {
+ //free all the buf
+ dev_mgr_free_device(dev_mgr, rh);
+ //dev_mgr->root_hub = NULL;
+ }
+
+ return TRUE;
}
-NTSTATUS
-hub_start_int_request(
-PUSB_DEV pdev
-)
+VOID
+rh_timer_svc_int_completion(PUSB_DEV pdev, PVOID context)
{
- PURB purb;
- PUSB_INTERFACE pif;
- PHUB2_EXTENSION hub_ext;
- NTSTATUS status;
- PHCD hcd;
- USE_IRQL;
-
- if( pdev == NULL )
- return STATUS_INVALID_PARAMETER;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- RtlZeroMemory( purb, sizeof( URB ) );
-
- if( purb == NULL )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_NO_MEMORY;
- }
+ PUSB_EVENT pevent;
+ PURB purb;
+ ULONG status, i;
+ PHCD hcd;
+ USE_IRQL;
- purb->flags = 0;
- purb->status = STATUS_SUCCESS;
- hub_ext = hub_ext_from_dev( pdev );
- purb->data_buffer = hub_ext->int_data_buf;
- purb->data_length = ( hub_ext->port_count + 7 ) / 8;
+ if (pdev == NULL || context == NULL)
+ return;
- hub_if_from_dev( pdev, pif );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_start_int_request(): pdev=0x%x, pif=0x%x\n", pdev, pif ) );
- purb->pendp = &pif->endp[ 0 ];
- purb->pdev = pdev;
+ purb = (PURB) context;
- purb->completion = hub_int_completion;
- purb->context = hub_ext;
+ lock_dev(pdev, TRUE);
- purb->pirp = NULL;
- purb->reference = 0;
- hcd = pdev->hcd;
- unlock_dev( pdev, FALSE );
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ pdev->ref_count -= 2; // one for timer_svc and one for urb, for those rh requests
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("rh_timer_svc_int_completion(): the dev is zomb, 0x%x\n", pdev));
+ return;
+ }
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
- purb = NULL;
- }
+ hcd = pdev->hcd;
+ if (purb->data_length < 1)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ unlock_dev(pdev, TRUE);
+ goto LBL_OUT;
+ }
- return status;
+ pdev->hcd->hcd_dispatch(pdev->hcd, HCD_DISP_READ_RH_DEV_CHANGE, purb->data_buffer);
+ purb->status = STATUS_SUCCESS;
+ unlock_dev(pdev, TRUE);
+
+ LBL_OUT:
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, TRUE);
+ pdev->ref_count -= 2;
+ // one for timer_svc and one for urb, for those rh requests
+ // that completed immediately, the ref_count of the dev for
+ // that urb won't increment and for normal hub request
+ // completion, hcd_generic_urb_completion will be called
+ // by the xhci_dpc_callback, and the ref_count for the urb
+ // is maintained there. So only rh's timer-svc cares refcount
+ // when hcd_generic_urb_completion is called.
+ usb_dbg_print(DBGLVL_MAXIMUM, ("rh_timer_svc_int_completion(): rh's ref_count=0x%x\n", pdev->ref_count));
+ unlock_dev(pdev, TRUE);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("rh_timer_svc_int_completion(): exitiing...\n"));
+ return;
}
-void
-hub_int_completion(
-PURB purb,
-PVOID pcontext
-)
+VOID
+rh_timer_svc_reset_port_completion(PUSB_DEV pdev, PVOID context)
{
+ PURB purb;
+ ULONG i;
+ USHORT port_num;
+ PHUB2_EXTENSION hub_ext;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_DEV pdev;
- PHUB2_EXTENSION hub_ext;
- ULONG port_idx;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- LONG i;
- PHCD hcd;
-
- USE_IRQL;
-
- if( purb == NULL )
- return;
-
- if( pcontext == NULL )
- {
- usb_free_mem( purb );
- return;
- }
-
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_int_completion(): entering...\n" ) );
-
- pdev = purb->pdev;
- hub_ext = pcontext;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- return;
- }
-
- hcd = pdev->hcd;
-
- if( purb->status == STATUS_SUCCESS )
- {
-
- for( i = 1; i <= hub_ext->port_count; i++ )
- {
- if( hub_ext->int_data_buf[ i >> 3 ] & ( 1 << i ) )
- {
- break;
- }
- }
- if( i > hub_ext->port_count )
- {
- //no status change, re-initialize the int request
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- hub_start_int_request( pdev );
- return;
- }
-
- port_idx = ( ULONG )i;
-
- //re-use the urb to get port status
- purb->pendp = &pdev->default_endp;
- purb->data_buffer = ( PUCHAR )&hub_ext->port_status;
-
- purb->data_length = sizeof( USB_PORT_STATUS );
- purb->pdev = pdev;
-
- purb->context = hub_ext;
- purb->pdev = pdev;
- purb->completion = hub_get_port_status_completion;
- purb->reference = port_idx;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- psetup->bmRequestType = 0xa3; //host-device class other recepient
- psetup->bRequest = USB_REQ_GET_STATUS;
- psetup->wValue = 0;
- psetup->wIndex = ( USHORT )port_idx;
- psetup->wLength = 4;
-
- purb->pirp = NULL;
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- if( usb_error( status ) )
- {
- usb_free_mem( purb );
- purb = NULL;
- }
- else if( status == STATUS_SUCCESS )
- {
- // this is for root hub
- hcd->hcd_generic_urb_completion( purb, purb->context );
- }
- return;
- }
- else
- {
- unlock_dev( pdev, TRUE );
- if( usb_halted( purb->status ) )
- {
- //let's reset pipe
- usb_reset_pipe( pdev, purb->pendp, hub_reset_pipe_completion, NULL );
- }
- //unexpected error
- usb_free_mem( purb );
- purb = NULL;
- }
- return;
-}
+ USE_IRQL;
-VOID
-hub_get_port_status_completion(
-PURB purb,
-PVOID context
-)
-{
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- BYTE port_idx;
- PHUB2_EXTENSION hub_ext;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- PHCD hcd;
-
- USE_IRQL;
-
- if( purb == NULL || context == NULL )
- return;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_get_port_feature_completion(): entering...\n" ) );
-
- pdev = purb->pdev;
- pendp = purb->pendp;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- return;
- }
-
- hcd = pdev->hcd;
- if( usb_error( purb->status ) )
- {
- unlock_dev( pdev, TRUE );
-
- purb->status = 0;
- //simply retry the request refer to item 55 in document
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- if( status != STATUS_PENDING )
- {
- if( status == STATUS_SUCCESS )
- {
- hcd->hcd_generic_urb_completion( purb, purb->context );
-
- }
- else
- {
- //
- // must be fatal error
- // FIXME: better to pass it to the completion for further
- // processing?
- //
- usb_free_mem( purb );
- }
- }
- return;
- }
-
- hub_ext = hub_ext_from_dev( pdev );
- port_idx = ( BYTE )purb->reference;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_get_port_stataus_completion(): port_idx=0x%x, hcd =0x%x, \
- pdev=0x%x, purb=0x%x, hub_ext=0x%x, portsc=0x%x \n", \
- port_idx, \
- pdev->hcd, \
- pdev, \
- purb, \
- hub_ext,\
- *( ( PULONG ) purb->data_buffer ) ) );
-
- psq_enqueue( &hub_ext->port_status_queue[ port_idx ],
- *( ( PULONG )purb->data_buffer ) );
-
- //reuse the urb to clear the feature
- RtlZeroMemory( purb, sizeof( URB ) );
-
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->pendp = &pdev->default_endp;
- purb->pdev = pdev;
-
- purb->context = ( PVOID )&hub_ext->port_status ;
- purb->pdev = pdev;
- purb->completion = hub_clear_port_feature_completion;
- purb->reference = port_idx;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- psetup->bmRequestType = 0x23; //host-device class port recepient
- psetup->bRequest = USB_REQ_CLEAR_FEATURE;
- psetup->wIndex = port_idx;
- psetup->wLength = 0;
- purb->pirp = NULL;
-
- if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION )
- {
- psetup->wValue = USB_PORT_FEAT_C_CONNECTION;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE )
- {
- psetup->wValue = USB_PORT_FEAT_C_ENABLE;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND )
- {
- psetup->wValue = USB_PORT_FEAT_C_SUSPEND;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT )
- {
- psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET )
- {
- psetup->wValue = USB_PORT_FEAT_C_RESET;
- }
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
-
- // if( status != STATUS_SUCCESS )
- if( status != STATUS_PENDING )
- {
- hcd->hcd_generic_urb_completion( purb, purb->context );
- }
- /*else if( usb_error( status ) )
- {
- usb_free_mem( purb );
- return;
- }*/
- return;
+ if (pdev == NULL || context == NULL)
+ return;
-}
+ dev_mgr = dev_mgr_from_dev(pdev); //readonly and hold ref_count
-VOID
-hub_clear_port_feature_completion(
-PURB purb,
-PVOID context
-)
-{
- BYTE port_idx;
- LONG i;
- BOOL bReset, event_post, brh;
- ULONG pc;
- PHCD hcd;
- NTSTATUS status;
- PUSB_DEV pdev, pdev2;
- PUSB_EVENT pevent;
- PUSB_ENDPOINT pendp;
- PUSB_INTERFACE pif;
- PHUB2_EXTENSION hub_ext;
- PUSB_DEV_MANAGER dev_mgr;
-
- PUSB_CTRL_SETUP_PACKET psetup;
-
- USE_IRQL;
-
- if( purb == NULL )
- return;
-
- if( context == NULL )
- {
- usb_free_mem( purb );
- return;
- }
-
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_clear_port_feature_completion(): entering...\n" ) );
-
- pdev = purb->pdev;
- port_idx = ( BYTE )purb->reference;
-
- lock_dev( pdev, TRUE );
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
- brh = ( dev_class( pdev ) == USB_DEV_CLASS_ROOT_HUB );
-
- if( usb_error( purb->status ) )
- {
- unlock_dev( pdev, TRUE );
-
- purb->status = 0;
-
- // retry the request
- status = hcd->hcd_submit_urb( hcd, purb->pdev, purb->pendp, purb );
- if( status != STATUS_PENDING )
- {
- if( status == STATUS_SUCCESS )
- {
- hcd->hcd_generic_urb_completion( purb, purb->context );
- }
- else
- {
- //
- // FIXME: should we pass the error to the completion directly
- // instead of forstall it here?
- //
- // do not think the device is workable, no requests to it any more.
- // including the int polling
- //
- // usb_free_mem( purb );
- //
- goto LBL_SCAN_PORT_STAT;
- }
- }
- return;
- }
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- return;
- }
-
- pc = ( ( PUSB_PORT_STATUS ) context )->wPortChange;
-
- if( pc )
- {
- // the bits are tested in ascending order
- if( pc & USB_PORT_STAT_C_CONNECTION )
- {
- pc &= ~USB_PORT_STAT_C_CONNECTION;
- }
- else if( pc & USB_PORT_STAT_C_ENABLE )
- {
- pc &= ~USB_PORT_STAT_C_ENABLE;
- }
- else if( pc & USB_PORT_STAT_C_SUSPEND )
- {
- pc &= ~USB_PORT_STAT_C_SUSPEND;
- }
- else if( pc & USB_PORT_STAT_C_OVERCURRENT )
- {
- pc &= ~USB_PORT_STAT_C_OVERCURRENT;
- }
- else if( pc & USB_PORT_STAT_C_RESET )
- {
- pc &= ~USB_PORT_STAT_C_RESET;
- }
- }
- ( ( PUSB_PORT_STATUS ) context )->wPortChange = ( USHORT )pc;
-
- hub_ext = hub_ext_from_dev( pdev );
-
- if( pc )
- {
- //some other status change on the port still active
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION )
- {
- psetup->wValue = USB_PORT_FEAT_C_CONNECTION;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE )
- {
- psetup->wValue = USB_PORT_FEAT_C_ENABLE;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND )
- {
- psetup->wValue = USB_PORT_FEAT_C_SUSPEND;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT )
- {
- psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT;
- }
- else if( hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET )
- {
- psetup->wValue = USB_PORT_FEAT_C_RESET;
- }
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- if( status != STATUS_PENDING )
- {
- if( status == STATUS_SUCCESS )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_clear_port_stataus_completion(): port_idx=0x%x, hcd=0x%x, \
- pdev=0x%x, purb=0x%x, hub_ext=0x%x, wPortChange=0x%x \n", \
- port_idx, \
- pdev->hcd, \
- pdev, \
- purb, \
- hub_ext,\
- pc ) );
-
- hcd->hcd_generic_urb_completion( purb, purb->context );
- }
- else
- {
- usb_dbg_print( DBGLVL_MAXIMUM, (" hub_clear_port_feature_completion(): \
- error=0x%x\n", status ) );
-
- // usb_free_mem( purb );
- goto LBL_SCAN_PORT_STAT;
- }
- }
- return;
- }
-
- for( i = 1; i <= hub_ext->port_count; i++ )
- {
- if( hub_ext->int_data_buf[ i >> 3 ] & ( 1 << i ) )
- {
- break;
- }
- }
-
- //clear the port-change map, we have get port i's status.
- hub_ext->int_data_buf[ i >> 3 ] &= ~( 1 << i );
-
- //rescan to find some other port that has status change
- for( i = 1; i <= hub_ext->port_count; i++ )
- {
- if( hub_ext->int_data_buf[ i >> 3 ] & ( 1 << i ) )
- {
- break;
- }
- }
-
- if( i <= hub_ext->port_count )
- {
- //still has port-change pending, get the port status change
- port_idx = ( UCHAR )i;
-
- //re-use the urb
- purb->data_buffer = ( PUCHAR )&hub_ext->port_status;
- purb->data_length = sizeof( USB_PORT_STATUS );
- purb->pendp = &pdev->default_endp;
- purb->pdev = pdev;
-
- purb->context = hub_ext;
- purb->pdev = pdev;
- purb->completion = hub_get_port_status_completion;
- purb->reference = port_idx;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- psetup->bmRequestType = 0xa3; //host-device class other recepient
- psetup->bRequest = USB_REQ_GET_STATUS;
- psetup->wValue = 0;
- psetup->wIndex = port_idx;
- psetup->wLength = 4;
-
- purb->pirp = NULL;
-
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- if( status != STATUS_PENDING )
- {
- if( status == STATUS_SUCCESS )
- {
- hcd->hcd_generic_urb_completion( purb, purb->context );
- }
- else
- { //must be fatal error
- // usb_free_mem( purb );
- goto LBL_SCAN_PORT_STAT;
- }
- }
- return;
- }
-
- unlock_dev( pdev, TRUE );
+ //block the rh polling
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
+ if (IsListEmpty(&dev_mgr->timer_svc_list) == FALSE)
+ {
+ ListFirst(&dev_mgr->timer_svc_list, pthis);
+ while (pthis)
+ {
+ if (((PTIMER_SVC) pthis)->pdev == pdev && ((PTIMER_SVC) pthis)->threshold == RH_INTERVAL)
+ {
+ ((PTIMER_SVC) pthis)->threshold = RH_INTERVAL + 0x800000;
+ break;
+ }
+
+ ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
+ pthis = pnext;
+ }
+ }
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
-LBL_SCAN_PORT_STAT:
+ purb = (PURB) context;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
- //all status changes are cleared
- if( purb )
- usb_free_mem( purb );
-
- purb = NULL;
-
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- //
- // if reset is in process, the dev_mgr_disconnect_dev will continue
- // the following resets
- //
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- return;
- }
-
- //at last we wake up thread if some port have status change to process
- port_idx = 0;
- for( i = 1, event_post = FALSE; i <= hub_ext->port_count; i++ )
- {
- if( psq_is_empty( &hub_ext->port_status_queue[ i ]) == FALSE )
- {
- if( port_state( hub_ext->port_status_queue[ i ].port_flags ) == STATE_IDLE ||
- port_state( hub_ext->port_status_queue[ i ].port_flags ) == STATE_WAIT_ADDRESSED )
- {
- // have status in the queue pending
- // STATE_WAIT_ADDRESSED is added to avoid some bad mannered
- // hub to disturb the reset process
- hub_post_esq_event( pdev, ( BYTE )i, hub_event_examine_status_que );
- }
- else if( port_state( hub_ext->port_status_queue[ i ].port_flags ) == STATE_WAIT_RESET_COMPLETE )
- {
- //there is only one reset at one time
- port_idx = ( BYTE )i;
- }
- }
- }
-
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
-
-
- if( port_idx )
- hub_check_reset_port_status(
- pdev,
- port_idx );
-
- //reinitialize the int request, here to reduce some uncertainty of concurrency
- hub_start_int_request( pdev );
-
- return;
-}
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ //purb->status = STATUS_ERROR;
+ //pdev->hcd->hcd_generic_urb_completion( purb, purb->context );
-VOID
-hub_event_examine_status_que(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context, //hub_ext
-ULONG param //port_idx
-)
-{
- PHUB2_EXTENSION hub_ext;
- USB_PORT_STATUS ps;
- PUSB_DEV pchild_dev;
- PTIMER_SVC ptimer;
- PUSB_DEV_MANAGER dev_mgr;
-
- USE_IRQL;
-
- if( pdev == NULL || context == 0 || param == 0 )
- return;
-
- while( TRUE )
- {
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- break;
- }
-
- dev_mgr = dev_mgr_from_dev( pdev );
- hub_ext = hub_ext_from_dev( pdev );
-
- if( psq_is_empty( &hub_ext->port_status_queue[ param ] ) )
- {
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_IDLE );
- unlock_dev( pdev, FALSE );
- break;
- }
-
- *( ( ULONG* )&ps ) = psq_outqueue( &hub_ext->port_status_queue[ param ] );
-
-
- pchild_dev = hub_ext->child_dev[ param ];
- hub_ext->child_dev[ param ] = 0;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_event_examine_status_queue(): dev_addr=0x%x, port=0x%x, wPortChange=0x%x, wPortStatus=0x%x\n", \
- pdev->dev_addr, \
- param,
- ps.wPortChange, \
- ps.wPortStatus ) );
-
- unlock_dev( pdev, FALSE );
-
- if( pchild_dev != NULL )
- dev_mgr_disconnect_dev( pchild_dev );
-
- if( ( ( ps.wPortChange & USB_PORT_STAT_C_ENABLE ) &&
- ( ( pdev->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_ROOT_HUB ) )
- || ( ps.wPortChange & USB_PORT_STAT_C_OVERCURRENT )
- || ( ps.wPortChange & USB_PORT_STAT_C_RESET )
- || ( ( ps.wPortChange & USB_PORT_STAT_C_CONNECTION ) &&
- !( ps.wPortStatus & USB_PORT_STAT_CONNECTION ) ) )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): error occured, portc=0x%x, ports=0x%x\n", \
- ps.wPortChange,\
- ps.wPortStatus ) );
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- break;
- }
- if( psq_is_empty( &hub_ext->port_status_queue[ param ] ) )
- {
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_IDLE );
- }
- else
- {
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_EXAMINE_STATUS_QUE );
- }
- unlock_dev( pdev, FALSE );
- continue;
-
- }
- else if( ( ps.wPortChange & USB_PORT_STAT_C_CONNECTION )
- && ( ps.wPortStatus & USB_PORT_STAT_CONNECTION )
- && psq_is_empty( &hub_ext->port_status_queue[ param ] ) )
- {
- KeAcquireSpinLock( &dev_mgr->timer_svc_list_lock, &old_irql );
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): dev lost\n" ) );
- break;
- }
- ptimer = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- if( ptimer == NULL )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): timer can not allocated\n" ) );
- break;
- }
-
- //a new connection
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): new connection comes\n" ) );
+ pdev->ref_count -= 2;
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ return;
+ }
- ptimer->counter = 0;
- ptimer->threshold = 21; //100 ms
-
- if( ps.wPortStatus & USB_PORT_STAT_LOW_SPEED )
- ptimer->threshold = 51; //500 ms
-
- ptimer->context = param;
- ptimer->pdev = pdev;
- ptimer->func = hub_timer_wait_dev_stable;
- InsertTailList( &dev_mgr->timer_svc_list, &ptimer->timer_svc_link );
- pdev->ref_count ++;
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_WAIT_STABLE );
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- break;
+ i = pdev->hcd->hcd_rh_reset_port(pdev->hcd, (UCHAR) psetup->wIndex);
+
+ hub_ext = hub_ext_from_dev(pdev);
+ {
+ USHORT temp;
+ PUCHAR pbuf;
+ if (psetup->wIndex < 16)
+ {
+ temp = 1 << psetup->wIndex;
+ pbuf = (PUCHAR) & temp;
+ if (temp > 128)
+ pbuf++;
+ hub_ext->int_data_buf[psetup->wIndex / 8] |= *pbuf;
+ if (i == TRUE)
+ hub_ext->rh_port_status[psetup->wIndex].wPortChange |= USB_PORT_STAT_C_RESET;
+ else // notify that is not a high speed device, will lost definitely
+ hub_ext->rh_port_status[psetup->wIndex].wPortChange |= USB_PORT_STAT_C_CONNECTION;
+ }
+ }
+
+ //???how to construct port status map
+ // decrease the timer_svc ref-count
+ pdev->ref_count--;
+ unlock_dev(pdev, TRUE);
+
+ purb->status = STATUS_SUCCESS;
+ //we delegate the completion to the rh_timer_svc_int_completion.
+ //this function is equivalent to hub_start_reset_port_completion
+
+ usb_free_mem(purb);
+
+ //expire the rh polling timer
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
+ if (IsListEmpty(&dev_mgr->timer_svc_list) == FALSE)
+ {
+ ListFirst(&dev_mgr->timer_svc_list, pthis);
+ while (pthis)
+ {
+ if (((PTIMER_SVC) pthis)->pdev == pdev &&
+ ((PTIMER_SVC) pthis)->threshold == RH_INTERVAL + 0x800000)
+ {
+ ((PTIMER_SVC) pthis)->counter = RH_INTERVAL;
+ ((PTIMER_SVC) pthis)->threshold = RH_INTERVAL;
+ break;
+ }
+
+ ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
+ pthis = pnext;
}
- else
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): unknown error\n" ) );
- continue;
- }
}
- return;
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
+
+ lock_dev(pdev, TRUE);
+ pdev->ref_count--;
+ unlock_dev(pdev, TRUE);
+ return;
}
+//called when a disconnect is detected on the port
VOID
-hub_timer_wait_dev_stable(
-PUSB_DEV pdev,
-PVOID context //port-index
-)
+dev_mgr_disconnect_dev(PUSB_DEV pdev)
{
+ PLIST_ENTRY pthis, pnext;
+ PHUB2_EXTENSION phub_ext;
+ PUSB_CONFIGURATION pconfig;
+ PUSB_INTERFACE pif;
+ PUSB_DEV_MANAGER dev_mgr;
+ PHCD hcd;
+ BOOL is_hub, found;
+ ULONG dev_id;
+ int i;
+
+ USE_IRQL;
+
+ if (pdev == NULL)
+ return;
+
+ found = FALSE;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_disconnect_dev(): entering, pdev=0x%x\n", pdev));
+ lock_dev(pdev, FALSE);
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_BEFORE_ZOMB;
+ dev_mgr = dev_mgr_from_dev(pdev);
+ unlock_dev(pdev, FALSE);
+
+ // notify dev_driver that the dev stops function before any operations
+ if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_stop)
+ pdev->dev_driver->disp_tbl.dev_stop(dev_mgr, dev_handle_from_dev(pdev));
+
+ //safe to use the dev pointer in this function.
+ lock_dev(pdev, FALSE);
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_ZOMB;
+ hcd = pdev->hcd;
+ dev_id = pdev->dev_id;
+ unlock_dev(pdev, FALSE);
+
+ if (dev_mgr == NULL)
+ return;
+
+ hcd->hcd_remove_device(hcd, pdev);
+
+ //disconnect its children
+ if ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB ||
+ (pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_ROOT_HUB)
+ {
+ phub_ext = hub_ext_from_dev(pdev);
+ if (phub_ext)
+ {
+ for(i = 1; i <= phub_ext->port_count; i++)
+ {
+ if (phub_ext->child_dev[i])
+ {
+ dev_mgr_disconnect_dev(phub_ext->child_dev[i]);
+ phub_ext->child_dev[i] = NULL;
+ }
+ }
+ }
+ }
- PHUB2_EXTENSION hub_ext;
- PUSB_INTERFACE pif;
- PUSB_EVENT pevent;
- ULONG param;
- PUSB_DEV_MANAGER dev_mgr;
+ pconfig = pdev->usb_config;
- USE_IRQL;
+ //remove event belong to the dev
+ is_hub = ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB);
- if( pdev == NULL || context == 0 )
- return;
+ if (phub_ext && is_hub)
+ {
+ for(i = 1; i <= phub_ext->port_count; i++)
+ {
+ found = hub_remove_reset_event(pdev, i, FALSE);
+ if (found)
+ break;
+ }
+ }
- dev_mgr = dev_mgr_from_dev( pdev );
- param = ( ULONG ) context;
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- lock_dev( pdev, TRUE );
+ //free event of the dev from the event list
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+ ListFirst(&dev_mgr->event_list, pthis);
+ while (pthis)
+ {
+ ListNext(&dev_mgr->event_list, pthis, pnext);
+ if (((PUSB_EVENT) pthis)->pdev == pdev)
+ {
+ PLIST_ENTRY p1;
+ RemoveEntryList(pthis);
+ if ((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE) != USB_EVENT_FLAG_NOQUE)
+ {
+ //has a queue, re-insert the queue
+ if (p1 = (PLIST_ENTRY) ((PUSB_EVENT) pthis)->pnext)
+ {
+ InsertHeadList(&dev_mgr->event_list, p1);
+ free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link));
+ pthis = p1;
+ //note: this queue will be examined again in the next loop
+ //to find the matched dev in the queue
+ continue;
+ }
+ }
+ free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link));
+ }
+ else if (((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE)
+ != USB_EVENT_FLAG_NOQUE) && ((PUSB_EVENT) pthis)->pnext)
+ {
+ //has a queue, examine the queue
+ PUSB_EVENT p1, p2;
+ p1 = (PUSB_EVENT) pthis;
+ p2 = p1->pnext;
+ while (p2)
+ {
+ if (p2->pdev == pdev)
+ {
+ p1->pnext = p2->pnext;
+ p2->pnext = NULL;
+ free_event(&dev_mgr->event_pool, p2);
+ p2 = p1->pnext;
+ }
+ else
+ {
+ p1 = p2;
+ p2 = p2->pnext;
+ }
+ }
+ }
+ pthis = pnext;
+ }
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
- pdev->ref_count--;
+ // found indicates the reset event on one of the dev's port in process
+ if (found)
+ hub_start_next_reset_port(dev_mgr_from_dev(pdev), FALSE);
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- goto LBL_OUT;
- }
+ // remove timer-svc belonging to the dev
+ KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
+ ListFirst(&dev_mgr->timer_svc_list, pthis);
+ i = 0;
+ while (pthis)
+ {
+ ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
+ if (((PUSB_EVENT) pthis)->pdev == pdev)
+ {
+ RemoveEntryList(pthis);
+ free_timer_svc(&dev_mgr->timer_svc_pool, struct_ptr(pthis, TIMER_SVC, timer_svc_link));
+ i++;
+ }
+ pthis = pnext;
+ }
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
- hub_ext = hub_ext_from_dev( pdev );
+ // release the refcount
+ if (i)
+ {
+ lock_dev(pdev, FALSE);
+ pdev->ref_count -= i;
+ unlock_dev(pdev, FALSE);
+ }
- if( !psq_is_empty( &hub_ext->port_status_queue[ param ] ) )
- {
- //error occured, normally we should not receive event here
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_EXAMINE_STATUS_QUE );
+ // wait for all the reference count be released
+ for(;;)
+ {
+ LARGE_INTEGER interval;
- hub_post_esq_event( pdev, ( BYTE )param, hub_event_examine_status_que );
- }
- else
- {
- set_port_state( hub_ext->port_status_queue[ param ].port_flags,
- STATE_WAIT_RESET );
+ lock_dev(pdev, FALSE);
+ if (pdev->ref_count == 0)
+ {
+ unlock_dev(pdev, FALSE);
+ break;
+ }
+ unlock_dev(pdev, FALSE);
+ // Wait two ms.
+ interval.QuadPart = -20000;
+ KeDelayExecutionThread(KernelMode, FALSE, &interval);
+ }
- hub_post_esq_event( pdev, ( BYTE )param, hub_event_dev_stable );
+ if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_disconnect)
+ pdev->dev_driver->disp_tbl.dev_disconnect(dev_mgr, dev_handle_from_dev(pdev));
- }
+ // we put it here to let handle valid before disconnect
+ KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
+ ListFirst(&dev_mgr->dev_list, pthis);
+ while (pthis)
+ {
+ if (((PUSB_DEV) pthis) == pdev)
+ {
+ RemoveEntryList(pthis);
+ break;
+ }
+ ListNext(&dev_mgr->dev_list, pthis, pnext);
+ pthis = pnext;
+ }
+ KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
- LBL_OUT:
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- return;
-}
-VOID
-hub_event_dev_stable(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context, //hub_ext
-ULONG param //port_idx
-)
-{
+ if (pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd))
+ {
+ dev_mgr_free_device(dev_mgr, pdev);
+ }
+ else
+ {
+ //rh_destroy( pdev );
+ //TRAP();
+ //destroy it in dev_mgr_destroy
+ }
- PHUB2_EXTENSION hub_ext;
- PUSB_EVENT pevent, pevent1;
- PLIST_ENTRY pthis, pnext;
- BOOL que_exist;
- PHCD hcd;
- PUSB_DEV_MANAGER dev_mgr;
- NTSTATUS status;
- PURB purb;
- PUSB_CTRL_SETUP_PACKET psetup;
-
- USE_IRQL;
-
- if( pdev == NULL || context == 0 || param == 0 )
- return;
-
- dev_mgr = dev_mgr_from_dev( pdev );
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- goto LBL_OUT;
-
- hub_ext = hub_ext_from_dev( pdev );
- hcd = pdev->hcd;
-
- pevent = alloc_event( &dev_mgr->event_pool, 1 );
- if( pevent == NULL )
- goto LBL_OUT;
-
- pevent->event = USB_EVENT_WAIT_RESET_PORT;
- pevent->pdev = pdev;
- pevent->context = ( ULONG )hub_ext;
- pevent->param = param;
- pevent->flags = USB_EVENT_FLAG_QUE_RESET;
- pevent->process_event = NULL; //hub_event_reset_port_complete;
- pevent->process_queue = NULL; //hub_event_reset_process_queue;
- pevent->pnext = NULL;
-
- ListFirst( &dev_mgr->event_list, pthis );
- que_exist = FALSE;
-
- while( pthis )
- {
- //insert the event in to the wait-queue
- pevent1 = ( PUSB_EVENT ) pthis;
- if( pevent1->event == USB_EVENT_WAIT_RESET_PORT )
- {
- while( pevent1->pnext )
- pevent1 = pevent1->pnext;
-
- pevent1->pnext = pevent;
- que_exist = TRUE;
- break;
- }
- ListNext( &dev_mgr->event_list, pthis, pnext );
- pthis = pnext;
- }
-
- if( !que_exist )
- {
- //Let's start a reset port request
- InsertHeadList( &dev_mgr->event_list, &pevent->event_link );
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- RtlZeroMemory( purb, sizeof( URB ) );
-
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->pendp = &pdev->default_endp;
-
- purb->context = hub_ext;
- purb->pdev = pdev;
- purb->completion = hub_start_reset_port_completion; //hub_int_completion;
- purb->reference = param;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- psetup->bmRequestType = 0x23; //host-device other recepient
- psetup->bRequest = USB_REQ_SET_FEATURE;
- psetup->wValue = USB_PORT_FEAT_RESET;
- psetup->wIndex = ( USHORT )param;
- psetup->wLength = 0;
-
- purb->pirp = NULL;
- //enter another state
- set_port_state( hub_ext->port_status_queue[ param ].port_flags, STATE_WAIT_RESET_COMPLETE );
-
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb ) ;
- if( status != STATUS_PENDING )
- {
- //must be fatal error
- usb_free_mem( purb );
- hub_reexamine_port_status_queue( pdev, param, FALSE );
- if( hub_remove_reset_event( pdev, param, FALSE ) )
- hub_start_next_reset_port( dev_mgr, FALSE );
- }
- return;
- }
-
- LBL_OUT:
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- return;
+ return;
}
-VOID
-hub_start_reset_port_completion(
-PURB purb,
-PVOID context
-)
+BOOL
+hub_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- PUSB_DEV_MANAGER dev_mgr;
- NTSTATUS status;
- ULONG port_idx;
- PHCD hcd;
-
- USE_IRQL;
- if( purb == NULL )
- return;
-
- if( context == NULL )
- {
- //fatal error no retry.
- usb_free_mem( purb );
- return;
- }
-
- pdev = purb->pdev;
- pendp = purb->pendp;
- port_idx = purb->reference;
-
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- goto LBL_FREE_EVENT;
- }
-
- hcd = pdev->hcd;
- dev_mgr = dev_mgr_from_dev( pdev );
- unlock_dev( pdev, TRUE );
-
- status = purb->status;
- usb_free_mem( purb );
-
- if( !usb_error( status ) )
- {
- return;
- }
-
- LBL_FREE_EVENT:
- //since we have no patient to retry the dev, we should remove the event of
- //wait_reset_port on the port from the event list. and if possible, start
- //another reset process. note other port on the dev still have chance to be
- //reset if necessary.
- hub_reexamine_port_status_queue( pdev, port_idx, TRUE );
- if( hub_remove_reset_event( pdev, port_idx, TRUE ) )
- hub_start_next_reset_port( dev_mgr, TRUE );
- return;
+ //init driver structure, no PNP table functions
+ 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 = 0xffff; // 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 = USB_CLASS_HUB; // 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 hub"; // Driver name for Name Registry
+ pdriver->driver_desc.dev_class = USB_CLASS_HUB;
+ pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
+ pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
+
+ //pdriver->driver_init = hub_driver_init; // initialized in dev_mgr_init_driver
+ //pdriver->driver_destroy = hub_driver_destroy;
+
+ pdriver->driver_ext = 0;
+ pdriver->driver_ext_size = 0;
+
+ pdriver->disp_tbl.version = 1;
+ pdriver->disp_tbl.dev_connect = hub_connect;
+ pdriver->disp_tbl.dev_disconnect = hub_disconnect;
+ pdriver->disp_tbl.dev_stop = hub_stop;
+ pdriver->disp_tbl.dev_reserved = NULL;
+
+ return TRUE;
}
-
-VOID
-hub_set_address_completion(
-PURB purb,
-PVOID context
-)
+BOOL
+hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUSB_DEV pdev, hub_dev;
- PUSB_ENDPOINT pendp;
- PUSB_DEV_MANAGER dev_mgr;
- NTSTATUS status;
- ULONG port_idx;
- PHCD hcd;
-
- USE_IRQL;
-
- if( purb == NULL )
- return;
-
- if( context == NULL )
- {
- //fatal error no retry.
- usb_free_mem( purb );
- return;
- }
-
- pdev = purb->pdev;
- pendp = purb->pendp;
- port_idx = purb->reference;
-
- lock_dev( pdev, TRUE );
-
- hcd = pdev->hcd;
- dev_mgr = dev_mgr_from_dev( pdev );
- hub_dev = pdev->parent_dev;
- port_idx = pdev->port_idx;
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- //some error occured, let's start the next reset event
- goto LBL_RESET_NEXT;
- }
-
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_ADDRESSED;
-
- unlock_dev( pdev, TRUE );
- status = purb->status;
-
- if( usb_error( status ) )
- {
- //retry the urb
- purb->status = 0;
- hcd_dbg_print( DBGLVL_MAXIMUM, ( "hub_set_address_completion: can not set address\n" ) );
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- //some error occured, disable the port
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
- status = hub_disable_port_request( hub_dev, ( UCHAR )port_idx );
- }
- return;
- }
-
- usb_free_mem( purb );
- //let address settle
- usb_wait_ms_dpc( 10 );
-
- //let's config the dev
- dev_mgr_start_config_dev( pdev );
-
- LBL_RESET_NEXT:
-
- //second, remove the event in the queue
- hub_reexamine_port_status_queue( hub_dev, port_idx, TRUE );
- if( hub_remove_reset_event( hub_dev, port_idx, TRUE ) )
- hub_start_next_reset_port( dev_mgr, TRUE );
- return;
-};
+ pdriver->driver_ext = NULL;
+ return TRUE;
+}
-VOID
-hub_disable_port_completion(
-PURB purb,
-PVOID pcontext
-)
+void
+hub_reset_pipe_completion(PURB purb, //only for reference, can not be released
+ PVOID context)
{
- PHUB2_EXTENSION hub_ext;
- PUSB_DEV pdev;
- PUSB_DEV_MANAGER dev_mgr;
- UCHAR port_idx;
- PUSB_ENDPOINT pendp;
- PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ NTSTATUS status;
- if( purb == NULL )
- return;
+ USE_IRQL;
- pdev = purb->pdev;
- pendp = purb->pendp;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- port_idx = ( UCHAR )psetup->wIndex;
+ if (purb == NULL)
+ {
+ return;
+ }
- dev_mgr = dev_mgr_from_dev( pdev );
+ pdev = purb->pdev;
+ pendp = purb->pendp;
- usb_free_mem( purb );
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ return;
+ }
- hub_reexamine_port_status_queue( pdev, port_idx, TRUE );
- if( hub_remove_reset_event( pdev, port_idx, TRUE ) )
- hub_start_next_reset_port( dev_mgr, TRUE );
+ if (usb_error(purb->status))
+ {
+ //simply retry it
+ unlock_dev(pdev, TRUE);
+ //usb_free_mem( purb );
+ return;
+ }
+ unlock_dev(pdev, TRUE);
- return;
+ pdev = purb->pdev;
+ hub_start_int_request(pdev);
+ return;
}
NTSTATUS
-hub_disable_port_request(
-PUSB_DEV pdev,
-UCHAR port_idx
-)
-//caller should guarantee the validity of the dev
+hub_start_int_request(PUSB_DEV pdev)
{
- PURB purb;
- PUSB_ENDPOINT pendp;
- PHUB2_EXTENSION hub_ext;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- PHCD hcd;
- USE_IRQL;
-
- if( pdev == NULL || port_idx == 0 )
- return STATUS_INVALID_PARAMETER;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb == NULL )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_NO_MEMORY;
- }
-
- RtlZeroMemory( purb, sizeof( URB ) );
-
- purb->flags = 0;
- purb->status = STATUS_SUCCESS;
-
- hub_ext = hub_ext_from_dev( pdev );
-
- purb->data_buffer = NULL;
- purb->data_length = 0;
-
- pendp = purb->pendp = &pdev->default_endp;
- purb->pdev = pdev;
+ PURB purb;
+ PUSB_INTERFACE pif;
+ PHUB2_EXTENSION hub_ext;
+ NTSTATUS status;
+ PHCD hcd;
+ USE_IRQL;
+
+ if (pdev == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ RtlZeroMemory(purb, sizeof(URB));
- purb->completion = hub_disable_port_completion;
+ if (purb == NULL)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_NO_MEMORY;
+ }
+
+ purb->flags = 0;
+ purb->status = STATUS_SUCCESS;
+ hub_ext = hub_ext_from_dev(pdev);
+ purb->data_buffer = hub_ext->int_data_buf;
+ purb->data_length = (hub_ext->port_count + 7) / 8;
+
+ hub_if_from_dev(pdev, pif);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_start_int_request(): pdev=0x%x, pif=0x%x\n", pdev, pif));
+ purb->pendp = &pif->endp[0];
+ purb->pdev = pdev;
+
+ purb->completion = hub_int_completion;
purb->context = hub_ext;
purb->pirp = NULL;
purb->reference = 0;
+ hcd = pdev->hcd;
+ unlock_dev(pdev, FALSE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ }
+
+ return status;
+}
+
+void
+hub_int_completion(PURB purb, PVOID pcontext)
+{
+
+ PUSB_DEV pdev;
+ PHUB2_EXTENSION hub_ext;
+ ULONG port_idx;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ LONG i;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (purb == NULL)
+ return;
+
+ if (pcontext == NULL)
+ {
+ usb_free_mem(purb);
+ return;
+ }
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_int_completion(): entering...\n"));
+
+ pdev = purb->pdev;
+ hub_ext = pcontext;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ return;
+ }
- psetup->bmRequestType = 0x23; //host-device other recepient
- psetup->bRequest = USB_REQ_CLEAR_FEATURE; //clear_feature
- psetup->wValue = USB_PORT_FEAT_ENABLE;
- psetup->wIndex = ( USHORT )port_idx;
- psetup->wLength = 0;
+ hcd = pdev->hcd;
+
+ if (purb->status == STATUS_SUCCESS)
+ {
+
+ for(i = 1; i <= hub_ext->port_count; i++)
+ {
+ if (hub_ext->int_data_buf[i >> 3] & (1 << i))
+ {
+ break;
+ }
+ }
+ if (i > hub_ext->port_count)
+ {
+ //no status change, re-initialize the int request
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ hub_start_int_request(pdev);
+ return;
+ }
- purb->pirp = NULL;
- //enter another state
- hcd = pdev->hcd;
- unlock_dev( pdev, FALSE );
+ port_idx = (ULONG)i;
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- if( status == STATUS_PENDING )
- return status;
+ //re-use the urb to get port status
+ purb->pendp = &pdev->default_endp;
+ purb->data_buffer = (PUCHAR) & hub_ext->port_status;
- usb_free_mem( purb );
- return status;
+ purb->data_length = sizeof(USB_PORT_STATUS);
+ purb->pdev = pdev;
+
+ purb->context = hub_ext;
+ purb->pdev = pdev;
+ purb->completion = hub_get_port_status_completion;
+ purb->reference = port_idx;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0xa3; //host-device class other recepient
+ psetup->bRequest = USB_REQ_GET_STATUS;
+ psetup->wValue = 0;
+ psetup->wIndex = (USHORT) port_idx;
+ psetup->wLength = 4;
+
+ purb->pirp = NULL;
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (usb_error(status))
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ }
+ else if (status == STATUS_SUCCESS)
+ {
+ // this is for root hub
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+ }
+ return;
+ }
+ else
+ {
+ unlock_dev(pdev, TRUE);
+ if (usb_halted(purb->status))
+ {
+ //let's reset pipe
+ usb_reset_pipe(pdev, purb->pendp, hub_reset_pipe_completion, NULL);
+ }
+ //unexpected error
+ usb_free_mem(purb);
+ purb = NULL;
+ }
+ return;
}
+VOID
+hub_get_port_status_completion(PURB purb, PVOID context)
+{
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ BYTE port_idx;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (purb == NULL || context == NULL)
+ return;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_get_port_feature_completion(): entering...\n"));
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ return;
+ }
+
+ hcd = pdev->hcd;
+ if (usb_error(purb->status))
+ {
+ unlock_dev(pdev, TRUE);
+
+ purb->status = 0;
+ //simply retry the request refer to item 55 in document
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ if (status == STATUS_SUCCESS)
+ {
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+
+ }
+ else
+ {
+ //
+ // must be fatal error
+ // FIXME: better to pass it to the completion for further
+ // processing?
+ //
+ usb_free_mem(purb);
+ }
+ }
+ return;
+ }
+
+ hub_ext = hub_ext_from_dev(pdev);
+ port_idx = (BYTE) purb->reference;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_get_port_stataus_completion(): port_idx=0x%x, hcd =0x%x, \
+ pdev=0x%x, purb=0x%x, hub_ext=0x%x, portsc=0x%x \n", port_idx, pdev->hcd, pdev,
+ purb, hub_ext, *((PULONG) purb->data_buffer)));
+
+ psq_enqueue(&hub_ext->port_status_queue[port_idx], *((PULONG) purb->data_buffer));
+
+ //reuse the urb to clear the feature
+ RtlZeroMemory(purb, sizeof(URB));
+
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->pendp = &pdev->default_endp;
+ purb->pdev = pdev;
+
+ purb->context = (PVOID) & hub_ext->port_status;
+ purb->pdev = pdev;
+ purb->completion = hub_clear_port_feature_completion;
+ purb->reference = port_idx;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0x23; //host-device class port recepient
+ psetup->bRequest = USB_REQ_CLEAR_FEATURE;
+ psetup->wIndex = port_idx;
+ psetup->wLength = 0;
+ purb->pirp = NULL;
+
+ if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_CONNECTION;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_ENABLE;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_SUSPEND;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_RESET;
+ }
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+
+ // if( status != STATUS_SUCCESS )
+ if (status != STATUS_PENDING)
+ {
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+ }
+ /*else if( usb_error( status ) )
+ {
+ usb_free_mem( purb );
+ return;
+ } */
+ return;
+
+}
+
+VOID
+hub_clear_port_feature_completion(PURB purb, PVOID context)
+{
+ BYTE port_idx;
+ LONG i;
+ BOOL bReset, event_post, brh;
+ ULONG pc;
+ PHCD hcd;
+ NTSTATUS status;
+ PUSB_DEV pdev, pdev2;
+ PUSB_EVENT pevent;
+ PUSB_ENDPOINT pendp;
+ PUSB_INTERFACE pif;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+
+ PUSB_CTRL_SETUP_PACKET psetup;
+
+ USE_IRQL;
+
+ if (purb == NULL)
+ return;
+
+ if (context == NULL)
+ {
+ usb_free_mem(purb);
+ return;
+ }
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_clear_port_feature_completion(): entering...\n"));
+
+ pdev = purb->pdev;
+ port_idx = (BYTE) purb->reference;
+
+ lock_dev(pdev, TRUE);
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+ brh = (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB);
+
+ if (usb_error(purb->status))
+ {
+ unlock_dev(pdev, TRUE);
+
+ purb->status = 0;
+
+ // retry the request
+ status = hcd->hcd_submit_urb(hcd, purb->pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ if (status == STATUS_SUCCESS)
+ {
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+ }
+ else
+ {
+ //
+ // FIXME: should we pass the error to the completion directly
+ // instead of forstall it here?
+ //
+ // do not think the device is workable, no requests to it any more.
+ // including the int polling
+ //
+ // usb_free_mem( purb );
+ //
+ goto LBL_SCAN_PORT_STAT;
+ }
+ }
+ return;
+ }
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ return;
+ }
+
+ pc = ((PUSB_PORT_STATUS) context)->wPortChange;
+
+ if (pc)
+ {
+ // the bits are tested in ascending order
+ if (pc & USB_PORT_STAT_C_CONNECTION)
+ {
+ pc &= ~USB_PORT_STAT_C_CONNECTION;
+ }
+ else if (pc & USB_PORT_STAT_C_ENABLE)
+ {
+ pc &= ~USB_PORT_STAT_C_ENABLE;
+ }
+ else if (pc & USB_PORT_STAT_C_SUSPEND)
+ {
+ pc &= ~USB_PORT_STAT_C_SUSPEND;
+ }
+ else if (pc & USB_PORT_STAT_C_OVERCURRENT)
+ {
+ pc &= ~USB_PORT_STAT_C_OVERCURRENT;
+ }
+ else if (pc & USB_PORT_STAT_C_RESET)
+ {
+ pc &= ~USB_PORT_STAT_C_RESET;
+ }
+ }
+ ((PUSB_PORT_STATUS) context)->wPortChange = (USHORT) pc;
+
+ hub_ext = hub_ext_from_dev(pdev);
+
+ if (pc)
+ {
+ //some other status change on the port still active
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_CONNECTION;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_ENABLE;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_SUSPEND;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT;
+ }
+ else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET)
+ {
+ psetup->wValue = USB_PORT_FEAT_C_RESET;
+ }
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ if (status == STATUS_SUCCESS)
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_clear_port_stataus_completion(): port_idx=0x%x, hcd=0x%x, \
+ pdev=0x%x, purb=0x%x, hub_ext=0x%x, wPortChange=0x%x \n",
+ port_idx, pdev->hcd, pdev, purb, hub_ext, pc));
+
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+ }
+ else
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, (" hub_clear_port_feature_completion(): \
+ error=0x%x\n", status));
+
+ // usb_free_mem( purb );
+ goto LBL_SCAN_PORT_STAT;
+ }
+ }
+ return;
+ }
+
+ for(i = 1; i <= hub_ext->port_count; i++)
+ {
+ if (hub_ext->int_data_buf[i >> 3] & (1 << i))
+ {
+ break;
+ }
+ }
+
+ //clear the port-change map, we have get port i's status.
+ hub_ext->int_data_buf[i >> 3] &= ~(1 << i);
+
+ //rescan to find some other port that has status change
+ for(i = 1; i <= hub_ext->port_count; i++)
+ {
+ if (hub_ext->int_data_buf[i >> 3] & (1 << i))
+ {
+ break;
+ }
+ }
+
+ if (i <= hub_ext->port_count)
+ {
+ //still has port-change pending, get the port status change
+ port_idx = (UCHAR) i;
+
+ //re-use the urb
+ purb->data_buffer = (PUCHAR) & hub_ext->port_status;
+ purb->data_length = sizeof(USB_PORT_STATUS);
+ purb->pendp = &pdev->default_endp;
+ purb->pdev = pdev;
+
+ purb->context = hub_ext;
+ purb->pdev = pdev;
+ purb->completion = hub_get_port_status_completion;
+ purb->reference = port_idx;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0xa3; //host-device class other recepient
+ psetup->bRequest = USB_REQ_GET_STATUS;
+ psetup->wValue = 0;
+ psetup->wIndex = port_idx;
+ psetup->wLength = 4;
+
+ purb->pirp = NULL;
+
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ if (status == STATUS_SUCCESS)
+ {
+ hcd->hcd_generic_urb_completion(purb, purb->context);
+ }
+ else
+ { //must be fatal error
+ // usb_free_mem( purb );
+ goto LBL_SCAN_PORT_STAT;
+ }
+ }
+ return;
+ }
+
+ unlock_dev(pdev, TRUE);
+
+LBL_SCAN_PORT_STAT:
+
+ //all status changes are cleared
+ if (purb)
+ usb_free_mem(purb);
+
+ purb = NULL;
+
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ //
+ // if reset is in process, the dev_mgr_disconnect_dev will continue
+ // the following resets
+ //
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ return;
+ }
+
+ //at last we wake up thread if some port have status change to process
+ port_idx = 0;
+ for(i = 1, event_post = FALSE; i <= hub_ext->port_count; i++)
+ {
+ if (psq_is_empty(&hub_ext->port_status_queue[i]) == FALSE)
+ {
+ if (port_state(hub_ext->port_status_queue[i].port_flags) == STATE_IDLE ||
+ port_state(hub_ext->port_status_queue[i].port_flags) == STATE_WAIT_ADDRESSED)
+ {
+ // have status in the queue pending
+ // STATE_WAIT_ADDRESSED is added to avoid some bad mannered
+ // hub to disturb the reset process
+ hub_post_esq_event(pdev, (BYTE) i, hub_event_examine_status_que);
+ }
+ else if (port_state(hub_ext->port_status_queue[i].port_flags) == STATE_WAIT_RESET_COMPLETE)
+ {
+ //there is only one reset at one time
+ port_idx = (BYTE) i;
+ }
+ }
+ }
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+
+
+ if (port_idx)
+ hub_check_reset_port_status(pdev, port_idx);
+
+ //reinitialize the int request, here to reduce some uncertainty of concurrency
+ hub_start_int_request(pdev);
+
+ return;
+}
+
+VOID
+hub_event_examine_status_que(PUSB_DEV pdev,
+ ULONG event,
+ ULONG context, //hub_ext
+ ULONG param //port_idx
+ )
+{
+ PHUB2_EXTENSION hub_ext;
+ USB_PORT_STATUS ps;
+ PUSB_DEV pchild_dev;
+ PTIMER_SVC ptimer;
+ PUSB_DEV_MANAGER dev_mgr;
+
+ USE_IRQL;
+
+ if (pdev == NULL || context == 0 || param == 0)
+ return;
+
+ while (TRUE)
+ {
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ break;
+ }
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hub_ext = hub_ext_from_dev(pdev);
+
+ if (psq_is_empty(&hub_ext->port_status_queue[param]))
+ {
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_IDLE);
+ unlock_dev(pdev, FALSE);
+ break;
+ }
+
+ *((ULONG *) & ps) = psq_outqueue(&hub_ext->port_status_queue[param]);
+
+
+ pchild_dev = hub_ext->child_dev[param];
+ hub_ext->child_dev[param] = 0;
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_event_examine_status_queue(): dev_addr=0x%x, port=0x%x, wPortChange=0x%x, wPortStatus=0x%x\n",
+ pdev->dev_addr, param, ps.wPortChange, ps.wPortStatus));
+
+ unlock_dev(pdev, FALSE);
+
+ if (pchild_dev != NULL)
+ dev_mgr_disconnect_dev(pchild_dev);
+
+ if (((ps.wPortChange & USB_PORT_STAT_C_ENABLE) &&
+ ((pdev->flags & USB_DEV_CLASS_MASK) != USB_DEV_CLASS_ROOT_HUB))
+ || (ps.wPortChange & USB_PORT_STAT_C_OVERCURRENT)
+ || (ps.wPortChange & USB_PORT_STAT_C_RESET)
+ || ((ps.wPortChange & USB_PORT_STAT_C_CONNECTION) &&
+ !(ps.wPortStatus & USB_PORT_STAT_CONNECTION)))
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_event_examine_status_queue(): error occured, portc=0x%x, ports=0x%x\n",
+ ps.wPortChange, ps.wPortStatus));
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ break;
+ }
+ if (psq_is_empty(&hub_ext->port_status_queue[param]))
+ {
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_IDLE);
+ }
+ else
+ {
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_EXAMINE_STATUS_QUE);
+ }
+ unlock_dev(pdev, FALSE);
+ continue;
+
+ }
+ else if ((ps.wPortChange & USB_PORT_STAT_C_CONNECTION)
+ && (ps.wPortStatus & USB_PORT_STAT_CONNECTION)
+ && psq_is_empty(&hub_ext->port_status_queue[param]))
+ {
+ KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): dev lost\n"));
+ break;
+ }
+ ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ if (ptimer == NULL)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_event_examine_status_queue(): timer can not allocated\n"));
+ break;
+ }
+
+ //a new connection
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): new connection comes\n"));
+
+ ptimer->counter = 0;
+ ptimer->threshold = 21; //100 ms
+
+ if (ps.wPortStatus & USB_PORT_STAT_LOW_SPEED)
+ ptimer->threshold = 51; //500 ms
+
+ ptimer->context = param;
+ ptimer->pdev = pdev;
+ ptimer->func = hub_timer_wait_dev_stable;
+ InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link);
+ pdev->ref_count++;
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_STABLE);
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ break;
+
+ }
+ else
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): unknown error\n"));
+ continue;
+ }
+ }
+ return;
+}
+
+VOID
+hub_timer_wait_dev_stable(PUSB_DEV pdev,
+ PVOID context //port-index
+ )
+{
+
+ PHUB2_EXTENSION hub_ext;
+ PUSB_INTERFACE pif;
+ PUSB_EVENT pevent;
+ ULONG param;
+ PUSB_DEV_MANAGER dev_mgr;
+
+ USE_IRQL;
+
+ if (pdev == NULL || context == 0)
+ return;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ param = (ULONG) context;
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ lock_dev(pdev, TRUE);
+
+ pdev->ref_count--;
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ goto LBL_OUT;
+ }
+
+ hub_ext = hub_ext_from_dev(pdev);
+
+ if (!psq_is_empty(&hub_ext->port_status_queue[param]))
+ {
+ //error occured, normally we should not receive event here
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_EXAMINE_STATUS_QUE);
+
+ hub_post_esq_event(pdev, (BYTE) param, hub_event_examine_status_que);
+ }
+ else
+ {
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_RESET);
+
+ hub_post_esq_event(pdev, (BYTE) param, hub_event_dev_stable);
+
+ }
+
+LBL_OUT:
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ return;
+}
+
+VOID
+hub_event_dev_stable(PUSB_DEV pdev,
+ ULONG event,
+ ULONG context, //hub_ext
+ ULONG param //port_idx
+ )
+{
+
+ PHUB2_EXTENSION hub_ext;
+ PUSB_EVENT pevent, pevent1;
+ PLIST_ENTRY pthis, pnext;
+ BOOL que_exist;
+ PHCD hcd;
+ PUSB_DEV_MANAGER dev_mgr;
+ NTSTATUS status;
+ PURB purb;
+ PUSB_CTRL_SETUP_PACKET psetup;
+
+ USE_IRQL;
+
+ if (pdev == NULL || context == 0 || param == 0)
+ return;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ goto LBL_OUT;
+
+ hub_ext = hub_ext_from_dev(pdev);
+ hcd = pdev->hcd;
+
+ pevent = alloc_event(&dev_mgr->event_pool, 1);
+ if (pevent == NULL)
+ goto LBL_OUT;
+
+ pevent->event = USB_EVENT_WAIT_RESET_PORT;
+ pevent->pdev = pdev;
+ pevent->context = (ULONG) hub_ext;
+ pevent->param = param;
+ pevent->flags = USB_EVENT_FLAG_QUE_RESET;
+ pevent->process_event = NULL; //hub_event_reset_port_complete;
+ pevent->process_queue = NULL; //hub_event_reset_process_queue;
+ pevent->pnext = NULL;
+
+ ListFirst(&dev_mgr->event_list, pthis);
+ que_exist = FALSE;
+
+ while (pthis)
+ {
+ //insert the event in to the wait-queue
+ pevent1 = (PUSB_EVENT) pthis;
+ if (pevent1->event == USB_EVENT_WAIT_RESET_PORT)
+ {
+ while (pevent1->pnext)
+ pevent1 = pevent1->pnext;
+
+ pevent1->pnext = pevent;
+ que_exist = TRUE;
+ break;
+ }
+ ListNext(&dev_mgr->event_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ if (!que_exist)
+ {
+ //Let's start a reset port request
+ InsertHeadList(&dev_mgr->event_list, &pevent->event_link);
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ RtlZeroMemory(purb, sizeof(URB));
+
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->pendp = &pdev->default_endp;
+
+ purb->context = hub_ext;
+ purb->pdev = pdev;
+ purb->completion = hub_start_reset_port_completion; //hub_int_completion;
+ purb->reference = param;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0x23; //host-device other recepient
+ psetup->bRequest = USB_REQ_SET_FEATURE;
+ psetup->wValue = USB_PORT_FEAT_RESET;
+ psetup->wIndex = (USHORT) param;
+ psetup->wLength = 0;
+
+ purb->pirp = NULL;
+ //enter another state
+ set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_RESET_COMPLETE);
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ //must be fatal error
+ usb_free_mem(purb);
+ hub_reexamine_port_status_queue(pdev, param, FALSE);
+ if (hub_remove_reset_event(pdev, param, FALSE))
+ hub_start_next_reset_port(dev_mgr, FALSE);
+ }
+ return;
+ }
+
+LBL_OUT:
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ return;
+}
+
+VOID
+hub_start_reset_port_completion(PURB purb, PVOID context)
+{
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ PUSB_DEV_MANAGER dev_mgr;
+ NTSTATUS status;
+ ULONG port_idx;
+ PHCD hcd;
+
+ USE_IRQL;
+ if (purb == NULL)
+ return;
+
+ if (context == NULL)
+ {
+ //fatal error no retry.
+ usb_free_mem(purb);
+ return;
+ }
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+ port_idx = purb->reference;
+
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ goto LBL_FREE_EVENT;
+ }
+
+ hcd = pdev->hcd;
+ dev_mgr = dev_mgr_from_dev(pdev);
+ unlock_dev(pdev, TRUE);
+
+ status = purb->status;
+ usb_free_mem(purb);
+
+ if (!usb_error(status))
+ {
+ return;
+ }
+
+LBL_FREE_EVENT:
+ //since we have no patient to retry the dev, we should remove the event of
+ //wait_reset_port on the port from the event list. and if possible, start
+ //another reset process. note other port on the dev still have chance to be
+ //reset if necessary.
+ hub_reexamine_port_status_queue(pdev, port_idx, TRUE);
+ if (hub_remove_reset_event(pdev, port_idx, TRUE))
+ hub_start_next_reset_port(dev_mgr, TRUE);
+ return;
+}
+
+
+VOID
+hub_set_address_completion(PURB purb, PVOID context)
+{
+ PUSB_DEV pdev, hub_dev;
+ PUSB_ENDPOINT pendp;
+ PUSB_DEV_MANAGER dev_mgr;
+ NTSTATUS status;
+ ULONG port_idx;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (purb == NULL)
+ return;
+
+ if (context == NULL)
+ {
+ //fatal error no retry.
+ usb_free_mem(purb);
+ return;
+ }
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+ port_idx = purb->reference;
+
+ lock_dev(pdev, TRUE);
+
+ hcd = pdev->hcd;
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hub_dev = pdev->parent_dev;
+ port_idx = pdev->port_idx;
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ //some error occured, let's start the next reset event
+ goto LBL_RESET_NEXT;
+ }
+
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_ADDRESSED;
+
+ unlock_dev(pdev, TRUE);
+ status = purb->status;
+
+ if (usb_error(status))
+ {
+ //retry the urb
+ purb->status = 0;
+ hcd_dbg_print(DBGLVL_MAXIMUM, ("hub_set_address_completion: can not set address\n"));
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ //some error occured, disable the port
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ status = hub_disable_port_request(hub_dev, (UCHAR) port_idx);
+ }
+ return;
+ }
+
+ usb_free_mem(purb);
+ //let address settle
+ usb_wait_ms_dpc(10);
+
+ //let's config the dev
+ dev_mgr_start_config_dev(pdev);
+
+LBL_RESET_NEXT:
+ //second, remove the event in the queue
+ hub_reexamine_port_status_queue(hub_dev, port_idx, TRUE);
+ if (hub_remove_reset_event(hub_dev, port_idx, TRUE))
+ hub_start_next_reset_port(dev_mgr, TRUE);
+ return;
+};
+
+VOID
+hub_disable_port_completion(PURB purb, PVOID pcontext)
+{
+ PHUB2_EXTENSION hub_ext;
+ PUSB_DEV pdev;
+ PUSB_DEV_MANAGER dev_mgr;
+ UCHAR port_idx;
+ PUSB_ENDPOINT pendp;
+ PUSB_CTRL_SETUP_PACKET psetup;
+
+ if (purb == NULL)
+ return;
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ port_idx = (UCHAR) psetup->wIndex;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ usb_free_mem(purb);
+
+ hub_reexamine_port_status_queue(pdev, port_idx, TRUE);
+ if (hub_remove_reset_event(pdev, port_idx, TRUE))
+ hub_start_next_reset_port(dev_mgr, TRUE);
+
+ return;
+}
+
+//caller should guarantee the validity of the dev
+NTSTATUS
+hub_disable_port_request(PUSB_DEV pdev, UCHAR port_idx)
+{
+ PURB purb;
+ PUSB_ENDPOINT pendp;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ PHCD hcd;
+ USE_IRQL;
+
+ if (pdev == NULL || port_idx == 0)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb == NULL)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlZeroMemory(purb, sizeof(URB));
+
+ purb->flags = 0;
+ purb->status = STATUS_SUCCESS;
+
+ hub_ext = hub_ext_from_dev(pdev);
+
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+
+ pendp = purb->pendp = &pdev->default_endp;
+ purb->pdev = pdev;
+
+ purb->completion = hub_disable_port_completion;
+ purb->context = hub_ext;
+
+ purb->pirp = NULL;
+ purb->reference = 0;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0x23; //host-device other recepient
+ psetup->bRequest = USB_REQ_CLEAR_FEATURE; //clear_feature
+ psetup->wValue = USB_PORT_FEAT_ENABLE;
+ psetup->wIndex = (USHORT) port_idx;
+ psetup->wLength = 0;
+
+ purb->pirp = NULL;
+ //enter another state
+ hcd = pdev->hcd;
+ unlock_dev(pdev, FALSE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ if (status == STATUS_PENDING)
+ return status;
+
+ usb_free_mem(purb);
+ return status;
+}
BOOL
-hub_remove_reset_event(
-PUSB_DEV pdev,
-ULONG port_idx,
-BOOL from_dpc
-)
+hub_remove_reset_event(PUSB_DEV pdev, ULONG port_idx, BOOL from_dpc)
{
- PUSB_DEV_MANAGER dev_mgr;
- PLIST_ENTRY pthis, pnext;
- PUSB_EVENT pevent, pnext_event;
- BOOL found;
-
- KIRQL old_irql;
-
- if( pdev == NULL )
- return FALSE;
-
- if( port_idx == 0 )
- return FALSE;
-
- dev_mgr = dev_mgr_from_dev( pdev );
- found = FALSE;
-
- if( from_dpc )
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- else
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
-
- ListFirst( &dev_mgr->event_list, pthis );
- while( pthis )
- {
- pevent = ( PUSB_EVENT )pthis;
- if( pevent->event == USB_EVENT_WAIT_RESET_PORT &&
- ( pevent->flags & USB_EVENT_FLAG_QUE_TYPE ) == USB_EVENT_FLAG_QUE_RESET )
- {
- if( pevent->pdev == pdev && pevent->param == port_idx )
- {
- //remove it
- RemoveEntryList( &pevent->event_link );
- pnext_event = pevent->pnext;
- free_event( &dev_mgr->event_pool, pevent );
-
- if( pnext_event )
- InsertHeadList( &dev_mgr->event_list, &pnext_event->event_link );
-
- found = TRUE;
- break;
- }
- }
- ListNext( &dev_mgr->event_list, pthis, pnext );
- pthis = pnext;
- }
-
- if( from_dpc )
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- else
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- return found;
+ PUSB_DEV_MANAGER dev_mgr;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_EVENT pevent, pnext_event;
+ BOOL found;
+
+ KIRQL old_irql;
+
+ if (pdev == NULL)
+ return FALSE;
+
+ if (port_idx == 0)
+ return FALSE;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ found = FALSE;
+
+ if (from_dpc)
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+
+ ListFirst(&dev_mgr->event_list, pthis);
+ while (pthis)
+ {
+ pevent = (PUSB_EVENT) pthis;
+ if (pevent->event == USB_EVENT_WAIT_RESET_PORT &&
+ (pevent->flags & USB_EVENT_FLAG_QUE_TYPE) == USB_EVENT_FLAG_QUE_RESET)
+ {
+ if (pevent->pdev == pdev && pevent->param == port_idx)
+ {
+ //remove it
+ RemoveEntryList(&pevent->event_link);
+ pnext_event = pevent->pnext;
+ free_event(&dev_mgr->event_pool, pevent);
+
+ if (pnext_event)
+ InsertHeadList(&dev_mgr->event_list, &pnext_event->event_link);
+
+ found = TRUE;
+ break;
+ }
+ }
+ ListNext(&dev_mgr->event_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ if (from_dpc)
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ return found;
}
BOOL
-hub_start_next_reset_port(
-PUSB_DEV_MANAGER dev_mgr,
-BOOL from_dpc
-)
+hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr, BOOL from_dpc)
{
- PLIST_ENTRY pthis, pnext;
- PUSB_EVENT pevent, pnext_event;
- PUSB_DEV pdev;
- PHUB2_EXTENSION hub_ext;
- BOOL bret;
- PURB purb;
- BOOL processed;
- PUSB_CTRL_SETUP_PACKET psetup;
- PHCD hcd;
-
- USE_IRQL;
-
- if( dev_mgr == NULL )
- return FALSE;
-
- bret = FALSE;
- processed = FALSE;
-
- if( from_dpc )
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- else
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
-
- ListFirst( &dev_mgr->event_list, pthis);
-
- while( pevent = ( PUSB_EVENT )pthis )
- {
- while( pevent->event == USB_EVENT_WAIT_RESET_PORT &&
- ( pevent->flags & USB_EVENT_FLAG_QUE_TYPE ) == USB_EVENT_FLAG_QUE_RESET )
- {
-
- processed = TRUE;
-
- pdev = pevent->pdev;
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- pnext_event = pevent->pnext;
- free_event( &dev_mgr->event_pool, pevent );
- pevent = pnext_event;
- if( pevent == NULL )
- {
- bret = FALSE;
- break;
- }
- continue;
- }
-
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- RtlZeroMemory( purb, sizeof( URB ) );
-
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->pendp = &pdev->default_endp;
-
- hub_ext = hub_ext_from_dev( pdev );
- purb->context = hub_ext;
- purb->pdev = pdev;
- purb->completion = hub_start_reset_port_completion;
- purb->reference = pevent->param;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- psetup->bmRequestType = 0x23; //host-device other recepient
- psetup->bRequest = 3; //set_feature
- psetup->wValue = USB_PORT_FEAT_RESET;
- psetup->wIndex = ( USHORT )pevent->param;
- psetup->wLength = 0;
-
- purb->pirp = NULL;
- hcd = pdev->hcd;
- set_port_state( hub_ext->port_status_queue[ pevent->param ].port_flags, STATE_WAIT_RESET_COMPLETE );
- unlock_dev( pdev, TRUE );
-
- bret = TRUE;
- break;
- }
-
- if( !processed )
- {
- ListNext( &dev_mgr->event_list, pthis, pnext );
- pthis = pnext;
- }
- else
- break;
- }
-
- if( from_dpc )
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- else
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
-
- if( processed && bret )
- {
- if( hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb ) != STATUS_PENDING )
- {
- //fatal error
- usb_free_mem( purb );
- bret = FALSE;
- //do not know what to do
- }
- }
-
- if( pthis == NULL )
- bret = TRUE;
-
- return bret;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_EVENT pevent, pnext_event;
+ PUSB_DEV pdev;
+ PHUB2_EXTENSION hub_ext;
+ BOOL bret;
+ PURB purb;
+ BOOL processed;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (dev_mgr == NULL)
+ return FALSE;
+
+ bret = FALSE;
+ processed = FALSE;
+
+ if (from_dpc)
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+
+ ListFirst(&dev_mgr->event_list, pthis);
+
+ while (pevent = (PUSB_EVENT) pthis)
+ {
+ while (pevent->event == USB_EVENT_WAIT_RESET_PORT &&
+ (pevent->flags & USB_EVENT_FLAG_QUE_TYPE) == USB_EVENT_FLAG_QUE_RESET)
+ {
+
+ processed = TRUE;
+
+ pdev = pevent->pdev;
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ pnext_event = pevent->pnext;
+ free_event(&dev_mgr->event_pool, pevent);
+ pevent = pnext_event;
+ if (pevent == NULL)
+ {
+ bret = FALSE;
+ break;
+ }
+ continue;
+ }
+
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ RtlZeroMemory(purb, sizeof(URB));
+
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->pendp = &pdev->default_endp;
+
+ hub_ext = hub_ext_from_dev(pdev);
+ purb->context = hub_ext;
+ purb->pdev = pdev;
+ purb->completion = hub_start_reset_port_completion;
+ purb->reference = pevent->param;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ psetup->bmRequestType = 0x23; //host-device other recepient
+ psetup->bRequest = 3; //set_feature
+ psetup->wValue = USB_PORT_FEAT_RESET;
+ psetup->wIndex = (USHORT) pevent->param;
+ psetup->wLength = 0;
+
+ purb->pirp = NULL;
+ hcd = pdev->hcd;
+ set_port_state(hub_ext->port_status_queue[pevent->param].port_flags, STATE_WAIT_RESET_COMPLETE);
+ unlock_dev(pdev, TRUE);
+
+ bret = TRUE;
+ break;
+ }
+
+ if (!processed)
+ {
+ ListNext(&dev_mgr->event_list, pthis, pnext);
+ pthis = pnext;
+ }
+ else
+ break;
+ }
+
+ if (from_dpc)
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+
+ if (processed && bret)
+ {
+ if (hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb) != STATUS_PENDING)
+ {
+ //fatal error
+ usb_free_mem(purb);
+ bret = FALSE;
+ //do not know what to do
+ }
+ }
+
+ if (pthis == NULL)
+ bret = TRUE;
+
+ return bret;
}
//
//must have event-list-lock and dev-lock acquired
//
VOID
-hub_post_esq_event(
-PUSB_DEV pdev,
-BYTE port_idx,
-PROCESS_EVENT pe
-)
+hub_post_esq_event(PUSB_DEV pdev, BYTE port_idx, PROCESS_EVENT pe)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_EVENT pevent;
-
- if( pdev == NULL || port_idx == 0 || pe == NULL )
- return;
-
- dev_mgr = dev_mgr_from_dev( pdev );
-
- pevent = alloc_event( &dev_mgr->event_pool, 1 );
- pevent->event = USB_EVENT_DEFAULT;
- pevent->process_queue = event_list_default_process_queue;
- pevent->process_event = pe;
- pevent->context = ( ULONG )hub_ext_from_dev( pdev );
- pevent->param = port_idx;
- pevent->flags = USB_EVENT_FLAG_ACTIVE;
- pevent->pdev = pdev;
- pevent->pnext = NULL;
-
- InsertTailList( &dev_mgr->event_list, &pevent->event_link );
- KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE );
- // usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_post_esq_event(): current element in event list is 0x%x\n", \
- // dbg_count_list( &dev_mgr->event_list ) ) );
- return;
-
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_EVENT pevent;
+
+ if (pdev == NULL || port_idx == 0 || pe == NULL)
+ return;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ pevent = alloc_event(&dev_mgr->event_pool, 1);
+ pevent->event = USB_EVENT_DEFAULT;
+ pevent->process_queue = event_list_default_process_queue;
+ pevent->process_event = pe;
+ pevent->context = (ULONG) hub_ext_from_dev(pdev);
+ pevent->param = port_idx;
+ pevent->flags = USB_EVENT_FLAG_ACTIVE;
+ pevent->pdev = pdev;
+ pevent->pnext = NULL;
+
+ InsertTailList(&dev_mgr->event_list, &pevent->event_link);
+ KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
+ // usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_post_esq_event(): current element in event list is 0x%x\n", \
+ // dbg_count_list( &dev_mgr->event_list ) ) );
+ return;
}
-BOOL
-hub_check_reset_port_status(
-PUSB_DEV pdev,
-LONG port_idx
-)
// called only in hub_clear_port_feature_completion
+BOOL
+hub_check_reset_port_status(PUSB_DEV pdev, LONG port_idx)
{
- PUSB_DEV_MANAGER dev_mgr;
- PHUB2_EXTENSION hub_ext;
- BOOL bReset;
- USB_PORT_STATUS port_status;
- PUSB_DEV pdev2;
- PURB purb2;
- PHCD hcd;
-
- PUSB_CTRL_SETUP_PACKET psetup;
- ULONG status;
- LARGE_INTEGER delay;
-
- USE_IRQL;
-
- //let's check whether the status change is a reset complete
- usb_dbg_print( DBGLVL_MAXIMUM, ("hub_check_reset_port_status(): entering...\n" ) );
- dev_mgr = dev_mgr_from_dev( pdev );
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->dev_list_lock );
- lock_dev( pdev, TRUE );
-
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->dev_list_lock );
- return FALSE;
- }
-
- hub_ext = hub_ext_from_dev( pdev );
- port_status = psq_peek( &hub_ext->port_status_queue[ port_idx ], 0 );
-
- bReset = FALSE;
- if( port_status.wPortChange & USB_PORT_STAT_C_RESET )
- bReset = TRUE;
-
- pdev2 = NULL;
- purb2 = NULL;
-
- if( bReset
- && port_state( hub_ext->port_status_queue[ port_idx ].port_flags ) == STATE_WAIT_RESET_COMPLETE
- && psq_count( &hub_ext->port_status_queue[ port_idx ] ) == 1 )
- {
- // a port-reset complete, empty the queue, keep the state
- psq_outqueue( &hub_ext->port_status_queue[ port_idx ] );
- set_port_state( hub_ext->port_status_queue[ port_idx ].port_flags,
- STATE_WAIT_ADDRESSED );
-
- //let's new a dev, and start the set-addr request
- if( hub_ext->child_dev[ port_idx ] == 0 )
- {
- pdev2 = hub_ext->child_dev[ port_idx ]
- = dev_mgr_alloc_device( dev_mgr, hcd );
- if( pdev2 )
- {
- purb2 = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( !purb2 )
- {
- dev_mgr_free_device( dev_mgr, pdev2 );
- pdev2 = hub_ext->child_dev[ port_idx ] = NULL;
- }
- else
- {
- if( port_status.wPortStatus & USB_PORT_STAT_LOW_SPEED )
- {
- pdev2->flags |= USB_DEV_FLAG_LOW_SPEED;
- }
- else if( port_status.wPortStatus & USB_PORT_STAT_HIGH_SPEED )
- pdev2->flags |= USB_DEV_FLAG_HIGH_SPEED;
-
- pdev2->parent_dev = pdev;
- pdev2->port_idx = ( UCHAR )port_idx;
- pdev2->ref_count++;
-
- RtlZeroMemory( purb2, sizeof( URB ) );
-
- purb2->pdev = pdev2;
- purb2->pendp = &pdev2->default_endp;
- purb2->context = hub_ext;
- purb2->completion = hub_set_address_completion;
-
- InitializeListHead( &purb2->trasac_list );
- purb2->reference = port_idx;
- purb2->pirp = 0;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb2->setup_packet;
- psetup->bmRequestType = 0;
- psetup->bRequest = USB_REQ_SET_ADDRESS;
- psetup->wValue = pdev2->dev_addr;
- }
- }
- }
-
- if( pdev2 && purb2 )
- {
- //creation success, emit the urb
- //add to dev list
- InsertTailList( &dev_mgr->dev_list, &pdev2->dev_link );
-
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->dev_list_lock );
-
- status = hcd->hcd_submit_urb( hcd, pdev2, purb2->pendp, purb2 );
-
- lock_dev( pdev2, TRUE );
- pdev2->ref_count--;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_check_reset_port_status(): new dev ref_count=0x%x\n", pdev2->ref_count ) );
- unlock_dev( pdev2, TRUE );
-
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb2 );
- //??? do we need to lock it for SMP?
- //dev_mgr_free_device( dev_mgr, pdev2 ), let dev_mgr_thread to clean it;
- // disable the port
- if( hub_disable_port_request( pdev, ( UCHAR )port_idx ) != STATUS_PENDING )
- goto LBL_RESET_FAIL;
- }
-
- return TRUE;
- }
- }
- else
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_check_reset_port_status(): not a correct reset status\n" ) );
- }
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->dev_list_lock );
+ PUSB_DEV_MANAGER dev_mgr;
+ PHUB2_EXTENSION hub_ext;
+ BOOL bReset;
+ USB_PORT_STATUS port_status;
+ PUSB_DEV pdev2;
+ PURB purb2;
+ PHCD hcd;
+
+ PUSB_CTRL_SETUP_PACKET psetup;
+ ULONG status;
+ LARGE_INTEGER delay;
+
+ USE_IRQL;
+
+ //let's check whether the status change is a reset complete
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_check_reset_port_status(): entering...\n"));
+ dev_mgr = dev_mgr_from_dev(pdev);
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->dev_list_lock);
+ lock_dev(pdev, TRUE);
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock);
+ return FALSE;
+ }
+
+ hub_ext = hub_ext_from_dev(pdev);
+ port_status = psq_peek(&hub_ext->port_status_queue[port_idx], 0);
+
+ bReset = FALSE;
+ if (port_status.wPortChange & USB_PORT_STAT_C_RESET)
+ bReset = TRUE;
+
+ pdev2 = NULL;
+ purb2 = NULL;
+
+ if (bReset
+ && (port_state(hub_ext->port_status_queue[port_idx].port_flags) == STATE_WAIT_RESET_COMPLETE)
+ && (psq_count(&hub_ext->port_status_queue[port_idx]) == 1))
+ {
+ // a port-reset complete, empty the queue, keep the state
+ psq_outqueue(&hub_ext->port_status_queue[port_idx]);
+ set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_WAIT_ADDRESSED);
+
+ //let's new a dev, and start the set-addr request
+ if (hub_ext->child_dev[port_idx] == 0)
+ {
+ pdev2 = hub_ext->child_dev[port_idx] = dev_mgr_alloc_device(dev_mgr, hcd);
+ if (pdev2)
+ {
+ purb2 = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (!purb2)
+ {
+ dev_mgr_free_device(dev_mgr, pdev2);
+ pdev2 = hub_ext->child_dev[port_idx] = NULL;
+ }
+ else
+ {
+ if (port_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)
+ {
+ pdev2->flags |= USB_DEV_FLAG_LOW_SPEED;
+ }
+ else if (port_status.wPortStatus & USB_PORT_STAT_HIGH_SPEED)
+ pdev2->flags |= USB_DEV_FLAG_HIGH_SPEED;
+
+ pdev2->parent_dev = pdev;
+ pdev2->port_idx = (UCHAR) port_idx;
+ pdev2->ref_count++;
+
+ RtlZeroMemory(purb2, sizeof(URB));
+
+ purb2->pdev = pdev2;
+ purb2->pendp = &pdev2->default_endp;
+ purb2->context = hub_ext;
+ purb2->completion = hub_set_address_completion;
+
+ InitializeListHead(&purb2->trasac_list);
+ purb2->reference = port_idx;
+ purb2->pirp = 0;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb2->setup_packet;
+ psetup->bmRequestType = 0;
+ psetup->bRequest = USB_REQ_SET_ADDRESS;
+ psetup->wValue = pdev2->dev_addr;
+ }
+ }
+ }
+
+ if (pdev2 && purb2)
+ {
+ //creation success, emit the urb
+ //add to dev list
+ InsertTailList(&dev_mgr->dev_list, &pdev2->dev_link);
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock);
+
+ status = hcd->hcd_submit_urb(hcd, pdev2, purb2->pendp, purb2);
+
+ lock_dev(pdev2, TRUE);
+ pdev2->ref_count--;
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_check_reset_port_status(): new dev ref_count=0x%x\n", pdev2->ref_count));
+ unlock_dev(pdev2, TRUE);
+
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb2);
+ //??? do we need to lock it for SMP?
+ //dev_mgr_free_device( dev_mgr, pdev2 ), let dev_mgr_thread to clean it;
+ // disable the port
+ if (hub_disable_port_request(pdev, (UCHAR) port_idx) != STATUS_PENDING)
+ goto LBL_RESET_FAIL;
+ }
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, ("hub_check_reset_port_status(): not a correct reset status\n"));
+ }
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock);
LBL_RESET_FAIL:
- //Any event other than reset cause the reset process stall and another
- //pending reset-port requeset is serviced
- hub_reexamine_port_status_queue( pdev, port_idx, TRUE );
- if( hub_remove_reset_event( pdev, port_idx, TRUE ) )
- hub_start_next_reset_port( dev_mgr, TRUE);
+ //Any event other than reset cause the reset process stall and another
+ //pending reset-port requeset is serviced
+ hub_reexamine_port_status_queue(pdev, port_idx, TRUE);
+ if (hub_remove_reset_event(pdev, port_idx, TRUE))
+ hub_start_next_reset_port(dev_mgr, TRUE);
- return FALSE;
+ return FALSE;
}
VOID
-hub_reexamine_port_status_queue(
-PUSB_DEV hub_dev,
-ULONG port_idx,
-BOOL from_dpc
-)
+hub_reexamine_port_status_queue(PUSB_DEV hub_dev, ULONG port_idx, BOOL from_dpc)
{
- PHUB2_EXTENSION hub_ext;
- PUSB_DEV_MANAGER dev_mgr;
-
- USE_IRQL;
-
- if( hub_dev == NULL || port_idx == 0 )
- return;
-
- dev_mgr = dev_mgr_from_dev( hub_dev );
- if( from_dpc )
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- else
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
-
- lock_dev( hub_dev, TRUE );
- if( dev_state( hub_dev ) != USB_DEV_STATE_ZOMB )
- {
-
- hub_ext = hub_ext_from_dev( hub_dev );
- if( psq_is_empty( &hub_ext->port_status_queue[ port_idx ] ) )
- {
- set_port_state( hub_ext->port_status_queue[ port_idx ].port_flags,
- STATE_IDLE );
-
- }
- else
- {
- set_port_state( hub_ext->port_status_queue[ port_idx ].port_flags,
- STATE_EXAMINE_STATUS_QUE );
-
- hub_post_esq_event( hub_dev, ( UCHAR )port_idx, hub_event_examine_status_que );
- }
- }
- unlock_dev( hub_dev, TRUE );
-
- if( from_dpc )
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- else
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- return;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+
+ USE_IRQL;
+
+ if (hub_dev == NULL || port_idx == 0)
+ return;
+
+ dev_mgr = dev_mgr_from_dev(hub_dev);
+ if (from_dpc)
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+
+ lock_dev(hub_dev, TRUE);
+ if (dev_state(hub_dev) != USB_DEV_STATE_ZOMB)
+ {
+
+ hub_ext = hub_ext_from_dev(hub_dev);
+ if (psq_is_empty(&hub_ext->port_status_queue[port_idx]))
+ {
+ set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_IDLE);
+
+ }
+ else
+ {
+ set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_EXAMINE_STATUS_QUE);
+
+ hub_post_esq_event(hub_dev, (UCHAR) port_idx, hub_event_examine_status_que);
+ }
+ }
+ unlock_dev(hub_dev, TRUE);
+
+ if (from_dpc)
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ else
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ return;
}
-BOOL
-dev_mgr_start_config_dev(
-PUSB_DEV pdev
-)
//called in hub_set_address_completion
+BOOL
+dev_mgr_start_config_dev(PUSB_DEV pdev)
{
- PUSB_DEV_MANAGER dev_mgr;
- PBYTE data_buf;
- PUSB_CTRL_SETUP_PACKET psetup;
- PURB purb;
- PHCD hcd;
+ PUSB_DEV_MANAGER dev_mgr;
+ PBYTE data_buf;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PURB purb;
+ PHCD hcd;
- USE_IRQL;
+ USE_IRQL;
- if( pdev == NULL )
- return FALSE;
+ if (pdev == NULL)
+ return FALSE;
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- return FALSE;
- }
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ return FALSE;
+ }
- hcd = pdev->hcd;
+ hcd = pdev->hcd;
- //first, get device descriptor
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- data_buf = usb_alloc_mem( NonPagedPool, 512 );
- if( purb == NULL )
- {
- unlock_dev( pdev, TRUE );
- return FALSE;
- }
+ //first, get device descriptor
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ data_buf = usb_alloc_mem(NonPagedPool, 512);
+ if (purb == NULL)
+ {
+ unlock_dev(pdev, TRUE);
+ return FALSE;
+ }
- RtlZeroMemory( purb, sizeof( URB ) );
- RtlZeroMemory( data_buf, 512 );
+ RtlZeroMemory(purb, sizeof(URB));
+ RtlZeroMemory(data_buf, 512);
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
- purb->data_buffer = data_buf; // user data
- purb->data_length = 8; // get partial desc
+ purb->data_buffer = data_buf; // user data
+ purb->data_length = 8; // get partial desc
- pdev->desc_buf = data_buf;
- pdev->desc_buf_size = 512;
+ pdev->desc_buf = data_buf;
+ pdev->desc_buf_size = 512;
- purb->pdev = pdev;
- purb->pendp = &pdev->default_endp; //pipe for current transfer
+ purb->pdev = pdev;
+ purb->pendp = &pdev->default_endp; //pipe for current transfer
purb->completion = dev_mgr_get_desc_completion;
- purb->reference = 0;
-
- InitializeListHead( &purb->trasac_list );
-
- psetup->bmRequestType = 0x80;
- psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
- psetup->wValue = ( USB_DT_DEVICE << 8 ) | 0;
- psetup->wIndex = 0;
- psetup->wLength = 8; //sizeof( USB_DEVICE_DESC );
- unlock_dev( pdev, TRUE );
-
- if( hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb ) != STATUS_PENDING )
- {
- usb_free_mem( purb );
- usb_free_mem( data_buf );
- return FALSE;
- }
- return TRUE;
+ purb->reference = 0;
+
+ InitializeListHead(&purb->trasac_list);
+
+ psetup->bmRequestType = 0x80;
+ psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
+ psetup->wValue = (USB_DT_DEVICE << 8) | 0;
+ psetup->wIndex = 0;
+ psetup->wLength = 8; //sizeof( USB_DEVICE_DESC );
+ unlock_dev(pdev, TRUE);
+
+ if (hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb) != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ usb_free_mem(data_buf);
+ return FALSE;
+ }
+ return TRUE;
}
VOID
-dev_mgr_get_desc_completion(
-PURB purb,
-PVOID context
-)
+dev_mgr_get_desc_completion(PURB purb, PVOID context)
{
- PUSB_DEV pdev;
+ PUSB_DEV pdev;
PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_ENDPOINT pendp;
- PUSB_DEV_MANAGER dev_mgr;
- NTSTATUS status;
- PUSB_CTRL_SETUP_PACKET psetup;
- LONG i;
- PHCD hcd;
-
- USE_IRQL;
-
- if( purb == NULL )
- return;
-
- pdev = purb->pdev;
- pendp = purb->pendp;
-
- if( pdev == NULL || pendp == NULL )
- {
- usb_free_mem( purb );
- purb = NULL;
- return;
- }
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- goto LBL_OUT;
- }
-
- pendp = &pdev->default_endp;
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- if( usb_error( purb->status ) )
- {
- unlock_dev( pdev, TRUE );
- hcd_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_get_desc_completion: can not get dev desc ref=0x%x, status=0x%x\n", purb->reference, purb->status ) );
- goto LBL_OUT;
- }
-
- switch( purb->reference )
- {
- case 0:
- {
- //only partial dev_desc
- //enable the dev specific default endp maxpacketsize
- pdev->pusb_dev_desc = ( PUSB_DEVICE_DESC )purb->data_buffer;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- psetup->wLength = sizeof( USB_DEVICE_DESC );
-
- //get the complete dev_desc
- purb->reference = 1;
- purb->status = 0;
- purb->data_length = sizeof( USB_DEVICE_DESC );
-
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- if( status != STATUS_PENDING )
- {
- goto LBL_OUT;
- }
- return;
- }
- case 1:
- {
- //let's begin to get config descriptors.
- if( pdev->pusb_dev_desc->bNumConfigurations == 0 )
- {
- unlock_dev( pdev, TRUE );
- goto LBL_OUT;
- }
-
- purb->data_buffer += sizeof( USB_DEVICE_DESC );
- purb->data_length = 8;
- purb->reference++;
- purb->context = ( PVOID )sizeof( USB_DEVICE_DESC );
- purb->status = 0;
-
- psetup->wValue = ( USB_DT_CONFIG << 8 ) | 0;
- psetup->wLength = 8;
- unlock_dev( pdev, TRUE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
-
- if( status != STATUS_PENDING )
- {
- goto LBL_OUT;
- }
- return;
- }
- default:
- {
- LONG config_idx;
- config_idx = ( purb->reference >> 1 ) - 1;
- if( ( purb->reference & 1 ) == 0 )
- {
- //partial config desc is obtained.
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )purb->data_buffer;
- if( pconfig_desc->wTotalLength >= 1024 )
- {
- //treat as an error
- unlock_dev( pdev, TRUE );
- goto LBL_OUT;
-
- }
-
- if( pconfig_desc->wTotalLength > ( USHORT )( pdev->desc_buf_size - ( LONG ) purb->context ) )
- {
- //rewind the 8-byte hdr
- *( ( PULONG )&context ) -= 8;
- realloc_buf( pdev, purb );
- }
- purb->data_length = pconfig_desc->wTotalLength;
- psetup->wLength = pconfig_desc->wTotalLength;
- purb->reference ++;
- unlock_dev( pdev, TRUE );
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- if( status != STATUS_PENDING )
- goto LBL_OUT;
-
- }
- else
- {
- //complete desc is returned.
- if( config_idx + 1 < pdev->pusb_dev_desc->bNumConfigurations )
- {
- //still have configurations left
- *( ( PULONG )&context ) += psetup->wLength;
- purb->data_buffer = &pdev->desc_buf[ ( LONG ) context ];
- purb->data_length = 8;
- psetup->wLength = 8;
- psetup->wValue = ( ( ( USB_DT_CONFIG ) << 8 ) | ( config_idx + 1 ) );
- purb->reference ++;
- purb->context = context;
-
- if( ( ( LONG )context ) + 8 > pdev->desc_buf_size )
- realloc_buf( pdev, purb );
-
- purb->status = 0;
- unlock_dev( pdev, TRUE );
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb );
- if( status != STATUS_PENDING )
- goto LBL_OUT;
- }
- else
- {
- //config descriptors have all been fetched
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- purb = NULL;
- dev_mgr_start_select_driver( pdev );
- }
- }
- return;
- }
- }
-
- LBL_OUT:
- usb_free_mem( purb );
- purb = NULL;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) != USB_DEV_STATE_ZOMB )
- {
- if( pdev->desc_buf )
- {
- usb_free_mem( pdev->desc_buf );
- pdev->desc_buf_size = 0;
- pdev->desc_buf = NULL;
- pdev->pusb_dev_desc = NULL;
- pdev->usb_config = NULL;
- }
- }
- unlock_dev( pdev, TRUE );
-
- return;
+ PUSB_ENDPOINT pendp;
+ PUSB_DEV_MANAGER dev_mgr;
+ NTSTATUS status;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ LONG i;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (purb == NULL)
+ return;
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+
+ if (pdev == NULL || pendp == NULL)
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ return;
+ }
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ goto LBL_OUT;
+ }
+
+ pendp = &pdev->default_endp;
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ if (usb_error(purb->status))
+ {
+ unlock_dev(pdev, TRUE);
+ hcd_dbg_print(DBGLVL_MAXIMUM,
+ ("dev_mgr_get_desc_completion: can not get dev desc ref=0x%x, status=0x%x\n",
+ purb->reference, purb->status));
+ goto LBL_OUT;
+ }
+
+ switch (purb->reference)
+ {
+ case 0:
+ {
+ //only partial dev_desc
+ //enable the dev specific default endp maxpacketsize
+ pdev->pusb_dev_desc = (PUSB_DEVICE_DESC) purb->data_buffer;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ psetup->wLength = sizeof(USB_DEVICE_DESC);
+
+ //get the complete dev_desc
+ purb->reference = 1;
+ purb->status = 0;
+ purb->data_length = sizeof(USB_DEVICE_DESC);
+
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ goto LBL_OUT;
+ }
+ return;
+ }
+ case 1:
+ {
+ //let's begin to get config descriptors.
+ if (pdev->pusb_dev_desc->bNumConfigurations == 0)
+ {
+ unlock_dev(pdev, TRUE);
+ goto LBL_OUT;
+ }
+
+ purb->data_buffer += sizeof(USB_DEVICE_DESC);
+ purb->data_length = 8;
+ purb->reference++;
+ purb->context = (PVOID) sizeof(USB_DEVICE_DESC);
+ purb->status = 0;
+
+ psetup->wValue = (USB_DT_CONFIG << 8) | 0;
+ psetup->wLength = 8;
+ unlock_dev(pdev, TRUE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+
+ if (status != STATUS_PENDING)
+ {
+ goto LBL_OUT;
+ }
+ return;
+ }
+ default:
+ {
+ LONG config_idx;
+ config_idx = (purb->reference >> 1) - 1;
+ if ((purb->reference & 1) == 0)
+ {
+ //partial config desc is obtained.
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) purb->data_buffer;
+ if (pconfig_desc->wTotalLength >= 1024)
+ {
+ //treat as an error
+ unlock_dev(pdev, TRUE);
+ goto LBL_OUT;
+
+ }
+
+ if (pconfig_desc->wTotalLength > (USHORT) (pdev->desc_buf_size - (LONG) purb->context))
+ {
+ //rewind the 8-byte hdr
+ *((PULONG) & context) -= 8;
+ realloc_buf(pdev, purb);
+ }
+ purb->data_length = pconfig_desc->wTotalLength;
+ psetup->wLength = pconfig_desc->wTotalLength;
+ purb->reference++;
+ unlock_dev(pdev, TRUE);
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ if (status != STATUS_PENDING)
+ goto LBL_OUT;
+
+ }
+ else
+ {
+ //complete desc is returned.
+ if (config_idx + 1 < pdev->pusb_dev_desc->bNumConfigurations)
+ {
+ //still have configurations left
+ *((PULONG) & context) += psetup->wLength;
+ purb->data_buffer = &pdev->desc_buf[(LONG) context];
+ purb->data_length = 8;
+ psetup->wLength = 8;
+ psetup->wValue = (((USB_DT_CONFIG) << 8) | (config_idx + 1));
+ purb->reference++;
+ purb->context = context;
+
+ if (((LONG) context) + 8 > pdev->desc_buf_size)
+ realloc_buf(pdev, purb);
+
+ purb->status = 0;
+ unlock_dev(pdev, TRUE);
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
+ if (status != STATUS_PENDING)
+ goto LBL_OUT;
+ }
+ else
+ {
+ //config descriptors have all been fetched
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ purb = NULL;
+ dev_mgr_start_select_driver(pdev);
+ }
+ }
+ return;
+ }
+ }
+
+LBL_OUT:
+ usb_free_mem(purb);
+ purb = NULL;
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
+ {
+ if (pdev->desc_buf)
+ {
+ usb_free_mem(pdev->desc_buf);
+ pdev->desc_buf_size = 0;
+ pdev->desc_buf = NULL;
+ pdev->pusb_dev_desc = NULL;
+ pdev->usb_config = NULL;
+ }
+ }
+ unlock_dev(pdev, TRUE);
+
+ return;
}
BOOL
-dev_mgr_start_select_driver(
-PUSB_DEV pdev
-)
+dev_mgr_start_select_driver(PUSB_DEV pdev)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_EVENT pevent;
- BOOL bret;
-
- USE_IRQL;
-
- if( pdev == NULL )
- return FALSE;
-
- dev_mgr = dev_mgr_from_dev( pdev );
- KeAcquireSpinLockAtDpcLevel( &dev_mgr->event_list_lock );
- lock_dev( pdev, TRUE );
-
- 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 = dev_mgr_event_select_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 );
- bret = TRUE;
-
- LBL_OUT:
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLockFromDpcLevel( &dev_mgr->event_list_lock );
- return bret;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_EVENT pevent;
+ BOOL bret;
+
+ USE_IRQL;
+
+ if (pdev == NULL)
+ return FALSE;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
+ lock_dev(pdev, TRUE);
+
+ 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 = dev_mgr_event_select_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);
+ bret = TRUE;
+
+LBL_OUT:
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
+ return bret;
}
BOOL
-dev_mgr_connect_to_dev(
-PVOID Parameter
-)
+dev_mgr_connect_to_dev(PVOID Parameter)
{
- PUSB_DEV pdev;
- DEV_HANDLE dev_handle;
- NTSTATUS status;
- PUSB_DRIVER pdriver;
- PCONNECT_DATA pcd = ( PCONNECT_DATA )Parameter;
- PUSB_DEV_MANAGER dev_mgr;
- CONNECT_DATA param;
-
- USE_IRQL;
-
- if( pcd == NULL )
- return FALSE;
- dev_handle = pcd->dev_handle;
- pdriver = pcd->pdriver;
- dev_mgr = pcd->dev_mgr;
-
- param.dev_mgr = dev_mgr;
- param.pdriver = pdriver;
- param.dev_handle = 0; //not used
-
- status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
- if( status != STATUS_SUCCESS )
- return FALSE;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_connect_to_dev(): about to call driver's dev_connect\n" ) );
- status = pdriver->disp_tbl.dev_connect( ¶m, dev_handle );
- usb_unlock_dev( pdev );
- return status;
+ PUSB_DEV pdev;
+ DEV_HANDLE dev_handle;
+ NTSTATUS status;
+ PUSB_DRIVER pdriver;
+ PCONNECT_DATA pcd = (PCONNECT_DATA) Parameter;
+ PUSB_DEV_MANAGER dev_mgr;
+ CONNECT_DATA param;
+
+ USE_IRQL;
+
+ if (pcd == NULL)
+ return FALSE;
+ dev_handle = pcd->dev_handle;
+ pdriver = pcd->pdriver;
+ dev_mgr = pcd->dev_mgr;
+
+ param.dev_mgr = dev_mgr;
+ param.pdriver = pdriver;
+ param.dev_handle = 0; //not used
+
+ status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ return FALSE;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_connect_to_dev(): about to call driver's dev_connect\n"));
+ status = pdriver->disp_tbl.dev_connect(¶m, dev_handle);
+ usb_unlock_dev(pdev);
+ return status;
}
VOID
-dev_mgr_event_select_driver(
-PUSB_DEV pdev,
-ULONG event,
-ULONG context,
-ULONG param
-)
+dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param)
{
- PUSB_DEV_MANAGER dev_mgr;
- PLIST_ENTRY pthis, pnext;
- PUSB_DRIVER pdriver, pcand;
- LONG credit, match, i;
- DEV_HANDLE handle;
- CONNECT_DATA cd;
-
- USE_IRQL;
-
- if( pdev == NULL )
- return;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return;
- }
- dev_mgr = dev_mgr_from_dev( pdev );
-
- pcand = NULL;
- match = 0;
- for( i = HUB_DRIVER_IDX; i < DEVMGR_MAX_DRIVERS; i++ )
- {
- //bypass root-hub driver with idx zero
- pdriver = ( PUSB_DRIVER ) &dev_mgr->driver_list[ i ];
-
- if( pdriver->driver_desc.flags & USB_DRIVER_FLAG_DEV_CAPABLE )
- credit = dev_mgr_score_driver_for_dev( dev_mgr, pdriver, pdev->pusb_dev_desc );
- else
- {
- continue;
- }
- if( credit > match )
- pcand = pdriver, match = credit;
-
- }
-
- if( match )
- {
- // we set class driver here
- // pdev->dev_driver = pcand;
- handle = usb_make_handle( pdev->dev_id, 0, 0 );
- }
- unlock_dev( pdev, FALSE );
-
- if( match )
- {
-
- cd.dev_handle = handle;
- cd.pdriver = pcand;
- cd.dev_mgr = dev_mgr;
-
- if( dev_mgr_connect_to_dev( &cd ) )
- return;
-
- // ExInitializeWorkItem( pwork_item, dev_mgr_connect_to_dev, ( PVOID )pcd );
- // ExQueueWorkItem( pwork_item, DelayedWorkQueue );
- }
- cd.dev_handle = handle;
- cd.pdriver = &dev_mgr->driver_list[ GEN_DRIVER_IDX ];
- cd.dev_mgr = dev_mgr;
- dev_mgr_connect_to_dev( &cd );
- return;
+ PUSB_DEV_MANAGER dev_mgr;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_DRIVER pdriver, pcand;
+ LONG credit, match, i;
+ DEV_HANDLE handle;
+ CONNECT_DATA cd;
+
+ USE_IRQL;
+
+ if (pdev == NULL)
+ return;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return;
+ }
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ pcand = NULL;
+ match = 0;
+ for(i = HUB_DRIVER_IDX; i < DEVMGR_MAX_DRIVERS; i++)
+ {
+ //bypass root-hub driver with idx zero
+ pdriver = (PUSB_DRIVER) & dev_mgr->driver_list[i];
+
+ if (pdriver->driver_desc.flags & USB_DRIVER_FLAG_DEV_CAPABLE)
+ credit = dev_mgr_score_driver_for_dev(dev_mgr, pdriver, pdev->pusb_dev_desc);
+ else
+ {
+ continue;
+ }
+ if (credit > match)
+ pcand = pdriver, match = credit;
+
+ }
+
+ if (match)
+ {
+ // we set class driver here
+ // pdev->dev_driver = pcand;
+ handle = usb_make_handle(pdev->dev_id, 0, 0);
+ }
+ unlock_dev(pdev, FALSE);
+
+ if (match)
+ {
+
+ cd.dev_handle = handle;
+ cd.pdriver = pcand;
+ cd.dev_mgr = dev_mgr;
+
+ if (dev_mgr_connect_to_dev(&cd))
+ return;
+
+ // ExInitializeWorkItem( pwork_item, dev_mgr_connect_to_dev, ( PVOID )pcd );
+ // ExQueueWorkItem( pwork_item, DelayedWorkQueue );
+ }
+ cd.dev_handle = handle;
+ cd.pdriver = &dev_mgr->driver_list[GEN_DRIVER_IDX];
+ cd.dev_mgr = dev_mgr;
+ dev_mgr_connect_to_dev(&cd);
+ return;
}
BOOL
-dev_mgr_build_usb_endp(
-PUSB_INTERFACE pif,
-PUSB_ENDPOINT pendp,
-PUSB_ENDPOINT_DESC pendp_desc
-)
+dev_mgr_build_usb_endp(PUSB_INTERFACE pif, PUSB_ENDPOINT pendp, PUSB_ENDPOINT_DESC pendp_desc)
{
- if( pendp == NULL || pif == NULL || pendp_desc == NULL )
- return FALSE;
+ if (pendp == NULL || pif == NULL || pendp_desc == NULL)
+ return FALSE;
pendp->flags = 0;
- InitializeListHead( &pendp->urb_list ); //pending urb queue
- pendp->pusb_if = pif;
+ InitializeListHead(&pendp->urb_list); //pending urb queue
+ pendp->pusb_if = pif;
pendp->pusb_endp_desc = pendp_desc;
- return TRUE;
+ return TRUE;
}
BOOL
-dev_mgr_build_usb_if(
-PUSB_CONFIGURATION pcfg,
-PUSB_INTERFACE pif,
-PUSB_INTERFACE_DESC pif_desc,
-BOOL alt_if
-)
+dev_mgr_build_usb_if(PUSB_CONFIGURATION pcfg, PUSB_INTERFACE pif, PUSB_INTERFACE_DESC pif_desc, BOOL alt_if)
{
- LONG i;
- PUSB_ENDPOINT_DESC pendp_desc;
-
- if( pcfg == NULL || pif == NULL || pif_desc == NULL )
- return FALSE;
-
- if( alt_if == FALSE )
- {
- pif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
- ? MAX_ENDPS_PER_IF
- : pif_desc->bNumEndpoints;
-
- pif->pif_drv = NULL;
- pif->pusb_config = pcfg;
- pif->pusb_if_desc = pif_desc;
- pif->if_ext_size = 0;
- pif->if_ext = NULL;
-
- InitializeListHead( &pif->altif_list );
- pif->altif_count = 0;
-
- pendp_desc = ( PUSB_ENDPOINT_DESC )( &( ( PBYTE )pif_desc )[ sizeof( USB_INTERFACE_DESC ) ] );
-
- for( i = 0; i < pif->endp_count; i++, pendp_desc++ )
- {
- dev_mgr_build_usb_endp( pif, &pif->endp[ i ], pendp_desc );
- }
- }
- else
- {
- PUSB_INTERFACE paltif;
- PLIST_ENTRY pthis, pnext;
-
- pif->altif_count++;
- paltif = usb_alloc_mem( NonPagedPool, sizeof( USB_INTERFACE ) );
- RtlZeroMemory( paltif, sizeof( USB_INTERFACE ) );
- InsertTailList( &pif->altif_list, &paltif->altif_list );
- paltif->pif_drv = NULL;
- paltif->pusb_config = pcfg;
- paltif->pusb_if_desc = pif_desc;
- paltif->if_ext_size = 0;
- paltif->if_ext = NULL;
- paltif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
- ? MAX_ENDPS_PER_IF
- : pif_desc->bNumEndpoints;
-
- ListFirst( &pif->altif_list, pthis );
-
- while( pthis )
- {
- //synchronize the altif_count;
- PUSB_INTERFACE pthis_if;
- pthis_if =( PUSB_INTERFACE )( ( ( PBYTE )pthis ) - offsetof( USB_INTERFACE, altif_list ) );
- pthis_if->altif_count = pif->altif_count;
- ListNext( &pif->altif_list, pthis, pnext );
- }
-
- }
- return TRUE;
+ LONG i;
+ PUSB_ENDPOINT_DESC pendp_desc;
+
+ if (pcfg == NULL || pif == NULL || pif_desc == NULL)
+ return FALSE;
+
+ if (alt_if == FALSE)
+ {
+ pif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
+ ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;
+
+ pif->pif_drv = NULL;
+ pif->pusb_config = pcfg;
+ pif->pusb_if_desc = pif_desc;
+ pif->if_ext_size = 0;
+ pif->if_ext = NULL;
+
+ InitializeListHead(&pif->altif_list);
+ pif->altif_count = 0;
+
+ pendp_desc = (PUSB_ENDPOINT_DESC) (&((PBYTE) pif_desc)[sizeof(USB_INTERFACE_DESC)]);
+
+ for(i = 0; i < pif->endp_count; i++, pendp_desc++)
+ {
+ dev_mgr_build_usb_endp(pif, &pif->endp[i], pendp_desc);
+ }
+ }
+ else
+ {
+ PUSB_INTERFACE paltif;
+ PLIST_ENTRY pthis, pnext;
+
+ pif->altif_count++;
+ paltif = usb_alloc_mem(NonPagedPool, sizeof(USB_INTERFACE));
+ RtlZeroMemory(paltif, sizeof(USB_INTERFACE));
+ InsertTailList(&pif->altif_list, &paltif->altif_list);
+ paltif->pif_drv = NULL;
+ paltif->pusb_config = pcfg;
+ paltif->pusb_if_desc = pif_desc;
+ paltif->if_ext_size = 0;
+ paltif->if_ext = NULL;
+ paltif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
+ ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;
+
+ ListFirst(&pif->altif_list, pthis);
+
+ while (pthis)
+ {
+ //synchronize the altif_count;
+ PUSB_INTERFACE pthis_if;
+ pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
+ pthis_if->altif_count = pif->altif_count;
+ ListNext(&pif->altif_list, pthis, pnext);
+ }
+
+ }
+ return TRUE;
}
NTSTATUS
-dev_mgr_build_usb_config(
-PUSB_DEV pdev,
-PBYTE pbuf,
-ULONG config_val,
-LONG config_count
-)
+dev_mgr_build_usb_config(PUSB_DEV pdev, PBYTE pbuf, ULONG config_val, LONG config_count)
{
- PUSB_CONFIGURATION pcfg;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_INTERFACE pif;
- int i;
- LONG if_count;
-
- if( pdev == NULL || pbuf == NULL )
- return STATUS_INVALID_PARAMETER;
-
-
- pdev->usb_config = usb_alloc_mem( NonPagedPool, sizeof( USB_CONFIGURATION ) );
- pcfg = pdev->usb_config;
-
- if( pdev->usb_config == NULL )
- return STATUS_NO_MEMORY;
-
- RtlZeroMemory( pcfg, sizeof( USB_CONFIGURATION ) );
- pcfg->pusb_config_desc = usb_find_config_desc_by_val( pbuf,
- config_val,
- config_count );
-
- if( pcfg->pusb_config_desc == NULL )
- {
- usb_free_mem( pcfg );
- pdev->usb_config = NULL;
- return STATUS_UNSUCCESSFUL;
- }
- pcfg->if_count = pcfg->pusb_config_desc->bNumInterfaces;
+ PUSB_CONFIGURATION pcfg;
+ PUSB_INTERFACE_DESC pif_desc;
+ PUSB_INTERFACE pif;
+ int i;
+ LONG if_count;
+
+ if (pdev == NULL || pbuf == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+
+ pdev->usb_config = usb_alloc_mem(NonPagedPool, sizeof(USB_CONFIGURATION));
+ pcfg = pdev->usb_config;
+
+ if (pdev->usb_config == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(pcfg, sizeof(USB_CONFIGURATION));
+ pcfg->pusb_config_desc = usb_find_config_desc_by_val(pbuf, config_val, config_count);
+
+ if (pcfg->pusb_config_desc == NULL)
+ {
+ usb_free_mem(pcfg);
+ pdev->usb_config = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+ pcfg->if_count = pcfg->pusb_config_desc->bNumInterfaces;
pcfg->pusb_dev = pdev;
- pif_desc = ( PUSB_INTERFACE_DESC )&( ( PBYTE )pcfg->pusb_config_desc )[ sizeof( USB_CONFIGURATION_DESC ) ];
- if_count = pcfg->if_count;
-
- for( i = 0 ; i < if_count; i++, pif_desc++ )
- {
- if( pif_desc->bAlternateSetting == 0)
- {
- dev_mgr_build_usb_if( pcfg, &pcfg->interf[ i ], pif_desc, FALSE );
- }
- else
- {
- i--;
- pif = &pcfg->interf[ i ];
- dev_mgr_build_usb_if( pcfg, pif, pif_desc, TRUE );
- }
- }
- return STATUS_SUCCESS;
+ pif_desc = (PUSB_INTERFACE_DESC) & ((PBYTE) pcfg->pusb_config_desc)[sizeof(USB_CONFIGURATION_DESC)];
+ if_count = pcfg->if_count;
+
+ for(i = 0; i < if_count; i++, pif_desc++)
+ {
+ if (pif_desc->bAlternateSetting == 0)
+ {
+ dev_mgr_build_usb_if(pcfg, &pcfg->interf[i], pif_desc, FALSE);
+ }
+ else
+ {
+ i--;
+ pif = &pcfg->interf[i];
+ dev_mgr_build_usb_if(pcfg, pif, pif_desc, TRUE);
+ }
+ }
+ return STATUS_SUCCESS;
}
NTSTATUS
-dev_mgr_destroy_usb_config(
-PUSB_CONFIGURATION pcfg
-)
+dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg)
{
- long i;
- PLIST_ENTRY pthis, pnext;
- PUSB_INTERFACE pif;
-
- if( pcfg == NULL )
- return FALSE;
-
- for( i = 0; i < pcfg->if_count; i++ )
- {
- pif = &pcfg->interf[ i ];
-
- if( pif->altif_count )
- {
- ListFirst( &pif->altif_list, pthis );
- while( pthis )
- {
- PUSB_INTERFACE pthis_if;
- pthis_if =( PUSB_INTERFACE )( ( ( PBYTE )pthis ) - offsetof( USB_INTERFACE, altif_list ) );
- RemoveEntryList( pthis );
- usb_free_mem( pthis_if );
- if( IsListEmpty( &pif->altif_list ) == TRUE )
- break;
-
- ListFirst( &pif->altif_list, pthis );
- }
- }
- }
- usb_free_mem( pcfg );
- return TRUE;
+ long i;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_INTERFACE pif;
+
+ if (pcfg == NULL)
+ return FALSE;
+
+ for(i = 0; i < pcfg->if_count; i++)
+ {
+ pif = &pcfg->interf[i];
+
+ if (pif->altif_count)
+ {
+ ListFirst(&pif->altif_list, pthis);
+ while (pthis)
+ {
+ PUSB_INTERFACE pthis_if;
+ pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
+ RemoveEntryList(pthis);
+ usb_free_mem(pthis_if);
+ if (IsListEmpty(&pif->altif_list) == TRUE)
+ break;
+
+ ListFirst(&pif->altif_list, pthis);
+ }
+ }
+ }
+ usb_free_mem(pcfg);
+ return TRUE;
}
#define is_dev_product_match( pdriVER, pdev_DESC ) \
&& ( pdriVER )->driver_desc.product_id == ( pdev_DESC )->idProduct )
LONG
-dev_mgr_score_driver_for_dev(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver,
-PUSB_DEVICE_DESC pdev_desc
-)
+dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc)
{
- LONG credit = 0;
-
- //assume supports all the sub_class are supported if sub_class is zero
- if( pdriver->driver_desc.dev_class == pdev_desc->bDeviceClass )
- {
- if( pdriver->driver_desc.dev_sub_class == 0 && pdriver->driver_desc.dev_protocol == 0 )
- credit = 3;
- else if( pdriver->driver_desc.dev_sub_class == pdev_desc->bDeviceSubClass )
- {
- if( pdriver->driver_desc.dev_protocol == 0 )
- credit = 6;
- else if( pdriver->driver_desc.dev_protocol == pdev_desc->bDeviceProtocol )
- credit = 9;
- }
- }
-
- if( is_dev_product_match( pdriver, pdev_desc ) )
- credit += 20;
-
- return credit;
+ LONG credit = 0;
+
+ //assume supports all the sub_class are supported if sub_class is zero
+ if (pdriver->driver_desc.dev_class == pdev_desc->bDeviceClass)
+ {
+ if (pdriver->driver_desc.dev_sub_class == 0 && pdriver->driver_desc.dev_protocol == 0)
+ credit = 3;
+ else if (pdriver->driver_desc.dev_sub_class == pdev_desc->bDeviceSubClass)
+ {
+ if (pdriver->driver_desc.dev_protocol == 0)
+ credit = 6;
+ else if (pdriver->driver_desc.dev_protocol == pdev_desc->bDeviceProtocol)
+ credit = 9;
+ }
+ }
+
+ if (is_dev_product_match(pdriver, pdev_desc))
+ credit += 20;
+
+ return credit;
}
LONG
-dev_mgr_score_driver_for_if(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver,
-PUSB_INTERFACE_DESC pif_desc
-)
+dev_mgr_score_driver_for_if(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_INTERFACE_DESC pif_desc)
{
- LONG credit;
-
- if( pdriver == NULL
- || !( pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE )
- || pif_desc == NULL
- || dev_mgr == NULL )
- return 0;
-
- if( is_header_match( ( PBYTE )pif_desc, USB_DT_INTERFACE ) == FALSE )
- {
- return 0;
- }
-
- credit = 0;
- if( ( pdriver->driver_desc.if_class == pif_desc->bInterfaceClass ) )
- {
- if( pdriver->driver_desc.if_sub_class == 0 && pdriver->driver_desc.if_protocol == 0 )
- credit = 2;
- if( pdriver->driver_desc.if_sub_class == pif_desc->bInterfaceSubClass )
- {
- if( pdriver->driver_desc.if_protocol == 0 )
- credit = 4;
- if( pdriver->driver_desc.if_protocol == pif_desc->bInterfaceProtocol )
- credit = 6;
- }
- }
- else
- credit = 1;
-
- return credit;
+ LONG credit;
+
+ if (pdriver == NULL
+ || !(pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) || pif_desc == NULL || dev_mgr == NULL)
+ return 0;
+
+ if (is_header_match((PBYTE) pif_desc, USB_DT_INTERFACE) == FALSE)
+ {
+ return 0;
+ }
+
+ credit = 0;
+ if ((pdriver->driver_desc.if_class == pif_desc->bInterfaceClass))
+ {
+ if (pdriver->driver_desc.if_sub_class == 0 && pdriver->driver_desc.if_protocol == 0)
+ credit = 2;
+ if (pdriver->driver_desc.if_sub_class == pif_desc->bInterfaceSubClass)
+ {
+ if (pdriver->driver_desc.if_protocol == 0)
+ credit = 4;
+ if (pdriver->driver_desc.if_protocol == pif_desc->bInterfaceProtocol)
+ credit = 6;
+ }
+ }
+ else
+ credit = 1;
+
+ return credit;
}
#define is_equal_driver( pd1, pd2, ret ) \
}\
}
-UCHAR
-dev_mgr_register_hcd(
-PUSB_DEV_MANAGER dev_mgr,
-PHCD hcd
-)
//return value is the hcd id
+UCHAR
+dev_mgr_register_hcd(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
{
- if( dev_mgr == NULL || hcd == NULL )
- return 0xff;
+ if (dev_mgr == NULL || hcd == NULL)
+ return 0xff;
- if( dev_mgr->hcd_count >= MAX_HCDS )
- return 0xff;
+ if (dev_mgr->hcd_count >= MAX_HCDS)
+ return 0xff;
- dev_mgr->hcd_array[ dev_mgr->hcd_count++ ] = hcd;
- return dev_mgr->hcd_count - 1;
+ dev_mgr->hcd_array[dev_mgr->hcd_count++] = hcd;
+ return dev_mgr->hcd_count - 1;
}
BOOL
-dev_mgr_register_irp(
-PUSB_DEV_MANAGER dev_mgr,
-PIRP pirp,
-PURB purb
-)
+dev_mgr_register_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp, PURB purb)
{
- KIRQL old_irql;
- if( dev_mgr == NULL )
- return FALSE;
-
- if( add_irp_to_list( &dev_mgr->irp_list, pirp, purb ) )
- {
- return TRUE;
- }
- TRAP();
- return FALSE;
+ KIRQL old_irql;
+ if (dev_mgr == NULL)
+ return FALSE;
+
+ if (add_irp_to_list(&dev_mgr->irp_list, pirp, purb))
+ {
+ return TRUE;
+ }
+ TRAP();
+ return FALSE;
}
-PURB
-dev_mgr_remove_irp(
-PUSB_DEV_MANAGER dev_mgr,
-PIRP pirp
-)
//caller must guarantee that when this func is called,
//the urb associated must exist.
+PURB
+dev_mgr_remove_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp)
{
- PURB purb;
- KIRQL old_irql;
- if( dev_mgr == NULL )
- return NULL;
+ PURB purb;
+ KIRQL old_irql;
+ if (dev_mgr == NULL)
+ return NULL;
- purb = remove_irp_from_list( &dev_mgr->irp_list, pirp, NULL );
- return purb;
+ purb = remove_irp_from_list(&dev_mgr->irp_list, pirp, NULL);
+ return purb;
}
VOID
-dev_mgr_cancel_irp(
-PDEVICE_OBJECT dev_obj,
-PIRP pirp
-)
+dev_mgr_cancel_irp(PDEVICE_OBJECT dev_obj, PIRP pirp)
{
- PUSB_DEV_MANAGER dev_mgr;
- PDEVEXT_HEADER pdev_ext_hdr;
- ULONG i;
-
- pdev_ext_hdr = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
- dev_mgr = pdev_ext_hdr->dev_mgr;
-
- if( dev_obj->CurrentIrp == pirp )
- {
- IoReleaseCancelSpinLock( pirp->CancelIrql );
- // we did not IoStartNextPacket, leave it for the urb completion
- }
- else
- {
- KeRemoveEntryDeviceQueue( &dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry );
- IoReleaseCancelSpinLock( pirp->CancelIrql );
-
- pirp->IoStatus.Information = 0;
- pirp->IoStatus.Status = STATUS_CANCELLED;
- IoCompleteRequest( pirp, IO_NO_INCREMENT );
- // the device queue is moved on, no need to call IoStartNextPacket
- return;
- }
-
- //
- // remove the irp and call the dev_mgr_cancel_irp
- // the completion will be done in urb completion
- //
- remove_irp_from_list( &dev_mgr->irp_list, pirp, dev_mgr );
- return;
+ PUSB_DEV_MANAGER dev_mgr;
+ PDEVEXT_HEADER pdev_ext_hdr;
+ ULONG i;
+
+ pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+ dev_mgr = pdev_ext_hdr->dev_mgr;
+
+ if (dev_obj->CurrentIrp == pirp)
+ {
+ IoReleaseCancelSpinLock(pirp->CancelIrql);
+ // we did not IoStartNextPacket, leave it for the urb completion
+ }
+ else
+ {
+ KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
+ IoReleaseCancelSpinLock(pirp->CancelIrql);
+
+ pirp->IoStatus.Information = 0;
+ pirp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(pirp, IO_NO_INCREMENT);
+ // the device queue is moved on, no need to call IoStartNextPacket
+ return;
+ }
+
+ //
+ // remove the irp and call the dev_mgr_cancel_irp
+ // the completion will be done in urb completion
+ //
+ remove_irp_from_list(&dev_mgr->irp_list, pirp, dev_mgr);
+ return;
}
-VOID
-dev_mgr_release_hcd(
-PUSB_DEV_MANAGER dev_mgr
-)
// release the hcd
+VOID
+dev_mgr_release_hcd(PUSB_DEV_MANAGER dev_mgr)
{
- LONG i;
- PHCD hcd;
- for( i = 0; i < dev_mgr->hcd_count; i++ )
- {
- hcd = dev_mgr->hcd_array[ i ];
- hcd->hcd_release( hcd );
- dev_mgr->hcd_array[ i ] = 0;
- }
- dev_mgr->hcd_count = 0;
- return;
+ LONG i;
+ PHCD hcd;
+ for(i = 0; i < dev_mgr->hcd_count; i++)
+ {
+ hcd = dev_mgr->hcd_array[i];
+ hcd->hcd_release(hcd);
+ dev_mgr->hcd_array[i] = 0;
+ }
+ dev_mgr->hcd_count = 0;
+ return;
}
VOID
-dev_mgr_start_hcd(
-PUSB_DEV_MANAGER dev_mgr
-)
+dev_mgr_start_hcd(PUSB_DEV_MANAGER dev_mgr)
{
- LONG i;
- PHCD hcd;
- for( i = 0; i < dev_mgr->hcd_count; i++ )
- {
- hcd = dev_mgr->hcd_array[ i ];
- hcd->hcd_start( hcd );
- }
- return;
+ LONG i;
+ PHCD hcd;
+ for(i = 0; i < dev_mgr->hcd_count; i++)
+ {
+ hcd = dev_mgr->hcd_array[i];
+ hcd->hcd_start(hcd);
+ }
+ return;
}
BOOL
-hub_connect(
-PCONNECT_DATA param,
-DEV_HANDLE dev_handle
-)
+hub_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle)
{
- URB urb, *purb;
- CHAR buf[ 512 ];
- DEV_HANDLE endp_handle;
- USB_DEVICE_DESC dev_desc;
- PUSB_CONFIGURATION_DESC pcfg_desc;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- LONG i, j, found, cfg_val;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DEV pdev;
- USE_IRQL;
-
-
- if( param == NULL || dev_handle == 0 )
- return FALSE;
-
- dev_mgr = param->dev_mgr;
-
- pcfg_desc = ( PUSB_CONFIGURATION_DESC ) buf;
- endp_handle = dev_handle | 0xffff;
- UsbBuildGetDescriptorRequest(&urb,
- endp_handle,
- USB_DT_DEVICE,
- 0,
- 0,
- ( &dev_desc ),
- ( sizeof( USB_DEVICE_DESC ) ),
- NULL,
- 0,
- 0 );
-
- status = usb_submit_urb( dev_mgr, &urb );
- if( status != STATUS_SUCCESS )
- return FALSE;
-
- found = FALSE;
- for( i = 0; i < dev_desc.bNumConfigurations; i++ )
- {
- UsbBuildGetDescriptorRequest(&urb,
- endp_handle,
- USB_DT_CONFIG,
- ( USHORT )i,
- 0,
- buf,
- 512,
- NULL,
- 0,
- 0 );
-
- status = usb_submit_urb( dev_mgr, &urb );
- if( status != STATUS_SUCCESS )
- {
- return FALSE;
- }
-
- status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
- if( status != STATUS_SUCCESS )
- return FALSE;
-
- pif_desc = ( PUSB_INTERFACE_DESC )&buf[ sizeof( USB_CONFIGURATION_DESC ) ];
- for( j = 0; j < pcfg_desc->bNumInterfaces; j++ )
- {
- if( pif_desc->bInterfaceClass == USB_CLASS_HUB
- && pif_desc->bInterfaceSubClass == 0
- && pif_desc->bNumEndpoints == 1 )
- {
- if( ( pif_desc->bInterfaceProtocol > 0 && pif_desc->bInterfaceProtocol < 3 )
- || ( pif_desc->bInterfaceProtocol == 0 && pdev->flags & USB_DEV_FLAG_HIGH_SPEED )
- || ( pif_desc->bInterfaceProtocol == 0 && !usb2( pdev->hcd ) ) )
- {
- found = TRUE;
- cfg_val = pcfg_desc->bConfigurationValue;
- break;
- }
- }
- if( usb_skip_if_and_altif( ( PBYTE* )&pif_desc ) == FALSE )
- {
- break;
- }
- }
- usb_unlock_dev( pdev );
-
- if( found )
- break;
-
- if( usb_skip_one_config( ( PBYTE* )&pcfg_desc ) == FALSE )
- {
- break;
- }
-
- }
- if( found )
- {
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb == NULL )
- return FALSE;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- urb_init( ( purb ) );
-
- purb->endp_handle = endp_handle;
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->completion = hub_set_cfg_completion;
- purb->context = dev_mgr;
- purb->reference = ( LONG )param->pdriver;
- psetup->bmRequestType = 0;
- psetup->bRequest = USB_REQ_SET_CONFIGURATION;
- psetup->wValue = ( USHORT )cfg_val;
- psetup->wIndex = 0;
- psetup->wLength = 0;
-
- status = usb_submit_urb( dev_mgr, purb );
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
- return FALSE;
- }
- return TRUE;
- }
-
- return FALSE;
+ URB urb, *purb;
+ CHAR buf[512];
+ DEV_HANDLE endp_handle;
+ USB_DEVICE_DESC dev_desc;
+ PUSB_CONFIGURATION_DESC pcfg_desc;
+ PUSB_INTERFACE_DESC pif_desc;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ LONG i, j, found, cfg_val;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DEV pdev;
+ USE_IRQL;
+
+
+ if (param == NULL || dev_handle == 0)
+ return FALSE;
+
+ dev_mgr = param->dev_mgr;
+
+ pcfg_desc = (PUSB_CONFIGURATION_DESC) buf;
+ endp_handle = dev_handle | 0xffff;
+ UsbBuildGetDescriptorRequest(&urb,
+ endp_handle,
+ USB_DT_DEVICE, 0, 0, (&dev_desc), (sizeof(USB_DEVICE_DESC)), NULL, 0, 0);
+
+ status = usb_submit_urb(dev_mgr, &urb);
+ if (status != STATUS_SUCCESS)
+ return FALSE;
+
+ found = FALSE;
+ for(i = 0; i < dev_desc.bNumConfigurations; i++)
+ {
+ UsbBuildGetDescriptorRequest(&urb, endp_handle, USB_DT_CONFIG, (USHORT) i, 0, buf, 512, NULL, 0, 0);
+
+ status = usb_submit_urb(dev_mgr, &urb);
+ if (status != STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ return FALSE;
+
+ pif_desc = (PUSB_INTERFACE_DESC) & buf[sizeof(USB_CONFIGURATION_DESC)];
+ for(j = 0; j < pcfg_desc->bNumInterfaces; j++)
+ {
+ if (pif_desc->bInterfaceClass == USB_CLASS_HUB
+ && pif_desc->bInterfaceSubClass == 0 && pif_desc->bNumEndpoints == 1)
+ {
+ if ((pif_desc->bInterfaceProtocol > 0 && pif_desc->bInterfaceProtocol < 3)
+ || (pif_desc->bInterfaceProtocol == 0 && pdev->flags & USB_DEV_FLAG_HIGH_SPEED)
+ || (pif_desc->bInterfaceProtocol == 0 && !usb2(pdev->hcd)))
+ {
+ found = TRUE;
+ cfg_val = pcfg_desc->bConfigurationValue;
+ break;
+ }
+ }
+ if (usb_skip_if_and_altif((PBYTE *) & pif_desc) == FALSE)
+ {
+ break;
+ }
+ }
+ usb_unlock_dev(pdev);
+
+ if (found)
+ break;
+
+ if (usb_skip_one_config((PBYTE *) & pcfg_desc) == FALSE)
+ {
+ break;
+ }
+
+ }
+ if (found)
+ {
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb == NULL)
+ return FALSE;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ urb_init((purb));
+
+ purb->endp_handle = endp_handle;
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->completion = hub_set_cfg_completion;
+ purb->context = dev_mgr;
+ purb->reference = (LONG) param->pdriver;
+ psetup->bmRequestType = 0;
+ psetup->bRequest = USB_REQ_SET_CONFIGURATION;
+ psetup->wValue = (USHORT) cfg_val;
+ psetup->wIndex = 0;
+ psetup->wLength = 0;
+
+ status = usb_submit_urb(dev_mgr, purb);
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
}
-void
-hub_set_interface_completion(
-PURB purb,
-PVOID pcontext
-);
+VOID hub_set_interface_completion(PURB purb, PVOID pcontext);
-void
-hub_set_cfg_completion(
-PURB purb,
-PVOID pcontext
-)
+VOID
+hub_set_cfg_completion(PURB purb, PVOID pcontext)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DRIVER pdriver;
- ULONG endp_handle, dev_handle;
- PUSB_CTRL_SETUP_PACKET psetup;
- UCHAR if_idx, if_alt_idx;
- PUSB_DEV pdev;
- PUSB_INTERFACE pif;
- BOOL high_speed, multiple_tt;
- NTSTATUS status;
- USE_IRQL;
-
- if( purb == NULL || pcontext == NULL )
- return;
-
- //pdev = NULL;
- dev_mgr = ( PUSB_DEV_MANAGER )pcontext;
- endp_handle = purb->endp_handle;
- dev_handle = endp_handle & 0xffff0000;
- pdriver = ( PUSB_DRIVER )purb->reference;
- high_speed = FALSE;
- multiple_tt = FALSE;
-
- if( purb->status != STATUS_SUCCESS )
- {
- goto LBL_ERROR;
- }
-
- status = usb_query_and_lock_dev( dev_mgr, purb->endp_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- usb_unlock_dev( pdev );
- goto LBL_ERROR;
- }
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- usb_unlock_dev( pdev );
- goto LBL_ERROR;
- }
- if( pdev->flags & USB_DEV_FLAG_HIGH_SPEED )
- {
- high_speed = TRUE;
- hub_if_from_dev( pdev, pif );
- if( pif->altif_count )
- {
- multiple_tt = TRUE;
- if_idx = pif - &pdev->usb_config->interf[ 0 ];
- }
- }
- unlock_dev( pdev, TRUE );
- usb_unlock_dev( pdev );
-
- if( !high_speed || !multiple_tt )
- {
- hub_set_interface_completion( purb, pcontext );
- return;
- }
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- urb_init( ( purb ) );
-
- // set the mult-tt if exist
- purb->endp_handle = endp_handle;
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->completion = hub_set_interface_completion;
- purb->context = dev_mgr;
- purb->reference = ( LONG )pdriver;
- psetup->bmRequestType = 0;
- psetup->bRequest = USB_REQ_SET_INTERFACE;
- psetup->wValue = ( USHORT )1; // alternate tt
- psetup->wIndex = if_idx; // if index
- psetup->wLength = 0;
-
- status = usb_submit_urb( dev_mgr, purb );
- if( status == STATUS_PENDING )
- return;
-
-LBL_ERROR:
- usb_free_mem( purb );
- purb = NULL;
- return;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DRIVER pdriver;
+ ULONG endp_handle, dev_handle;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ UCHAR if_idx, if_alt_idx;
+ PUSB_DEV pdev;
+ PUSB_INTERFACE pif;
+ BOOL high_speed, multiple_tt;
+ NTSTATUS status;
+ USE_IRQL;
+
+ if (purb == NULL || pcontext == NULL)
+ return;
+
+ //pdev = NULL;
+ dev_mgr = (PUSB_DEV_MANAGER) pcontext;
+ endp_handle = purb->endp_handle;
+ dev_handle = endp_handle & 0xffff0000;
+ pdriver = (PUSB_DRIVER) purb->reference;
+ high_speed = FALSE;
+ multiple_tt = FALSE;
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ goto LBL_ERROR;
+ }
+
+ status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ usb_unlock_dev(pdev);
+ goto LBL_ERROR;
+ }
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ usb_unlock_dev(pdev);
+ goto LBL_ERROR;
+ }
+ if (pdev->flags & USB_DEV_FLAG_HIGH_SPEED)
+ {
+ high_speed = TRUE;
+ hub_if_from_dev(pdev, pif);
+ if (pif->altif_count)
+ {
+ multiple_tt = TRUE;
+ if_idx = pif - &pdev->usb_config->interf[0];
+ }
+ }
+ unlock_dev(pdev, TRUE);
+ usb_unlock_dev(pdev);
+
+ if (!high_speed || !multiple_tt)
+ {
+ hub_set_interface_completion(purb, pcontext);
+ return;
+ }
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ urb_init((purb));
+
+ // set the mult-tt if exist
+ purb->endp_handle = endp_handle;
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->completion = hub_set_interface_completion;
+ purb->context = dev_mgr;
+ purb->reference = (LONG) pdriver;
+ psetup->bmRequestType = 0;
+ psetup->bRequest = USB_REQ_SET_INTERFACE;
+ psetup->wValue = (USHORT) 1; // alternate tt
+ psetup->wIndex = if_idx; // if index
+ psetup->wLength = 0;
+
+ status = usb_submit_urb(dev_mgr, purb);
+ if (status == STATUS_PENDING)
+ return;
+
+ LBL_ERROR:
+ usb_free_mem(purb);
+ purb = NULL;
+ return;
}
void
-hub_set_interface_completion(
-PURB purb,
-PVOID pcontext
-)
+hub_set_interface_completion(PURB purb, PVOID pcontext)
{
- PUSB_ENDPOINT pendp;
- NTSTATUS status;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_DEV_MANAGER dev_mgr;
- PBYTE dev_ext;
- DEV_HANDLE endp_handle;
- PUSB_DRIVER pdriver;
-
- if( purb == NULL || pcontext == NULL )
- return;
-
- //pdev = NULL;
- dev_mgr = ( PUSB_DEV_MANAGER )pcontext;
- endp_handle = purb->endp_handle;
- pdriver = ( PUSB_DRIVER )purb->reference;
-
- if( purb->status != STATUS_SUCCESS )
- {
- usb_free_mem( purb );
- return;
- }
-
- dev_ext = usb_alloc_mem( NonPagedPool, sizeof( HUB2_EXTENSION ) );
- if( dev_ext == NULL )
- {
- goto LBL_OUT;
- }
-
- //
- //acquire hub descriptor
- //
- RtlZeroMemory( dev_ext, sizeof( HUB2_EXTENSION ) );
- urb_init( purb );
-
- purb->data_buffer = ( PUCHAR )&( ( HUB2_EXTENSION* ) dev_ext )->hub_desc;
- purb->endp_handle = endp_handle;
- purb->data_length = sizeof( USB_HUB_DESCRIPTOR );
- purb->completion = hub_get_hub_desc_completion;
- purb->context = ( PVOID )dev_mgr;
- purb->reference = ( ULONG )dev_ext;
- purb->pirp = ( PIRP )pdriver;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET ) purb->setup_packet;
- psetup->bmRequestType = 0xa0;
- psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
- psetup->wValue = ( 0x29 << 8 );
- psetup->wLength = sizeof( USB_HUB_DESCRIPTOR );
- status = usb_submit_urb( dev_mgr, purb );
-
- if( status != STATUS_PENDING )
- {
- usb_free_mem( dev_ext );
- goto LBL_OUT;
- }
- return;
-
- LBL_OUT:
-
- //clear the dev_driver fields in the dev.
- usb_free_mem( purb );
- return;
+ PUSB_ENDPOINT pendp;
+ NTSTATUS status;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_DEV_MANAGER dev_mgr;
+ PBYTE dev_ext;
+ DEV_HANDLE endp_handle;
+ PUSB_DRIVER pdriver;
+
+ if (purb == NULL || pcontext == NULL)
+ return;
+
+ //pdev = NULL;
+ dev_mgr = (PUSB_DEV_MANAGER) pcontext;
+ endp_handle = purb->endp_handle;
+ pdriver = (PUSB_DRIVER) purb->reference;
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ usb_free_mem(purb);
+ return;
+ }
+
+ dev_ext = usb_alloc_mem(NonPagedPool, sizeof(HUB2_EXTENSION));
+ if (dev_ext == NULL)
+ {
+ goto LBL_OUT;
+ }
+
+ //
+ //acquire hub descriptor
+ //
+ RtlZeroMemory(dev_ext, sizeof(HUB2_EXTENSION));
+ urb_init(purb);
+
+ purb->data_buffer = (PUCHAR) & ((HUB2_EXTENSION *) dev_ext)->hub_desc;
+ purb->endp_handle = endp_handle;
+ purb->data_length = sizeof(USB_HUB_DESCRIPTOR);
+ purb->completion = hub_get_hub_desc_completion;
+ purb->context = (PVOID) dev_mgr;
+ purb->reference = (ULONG) dev_ext;
+ purb->pirp = (PIRP) pdriver;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ psetup->bmRequestType = 0xa0;
+ psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
+ psetup->wValue = (0x29 << 8);
+ psetup->wLength = sizeof(USB_HUB_DESCRIPTOR);
+ status = usb_submit_urb(dev_mgr, purb);
+
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(dev_ext);
+ goto LBL_OUT;
+ }
+ return;
+
+LBL_OUT:
+ //clear the dev_driver fields in the dev.
+ usb_free_mem(purb);
+ return;
}
-void
-hub_power_on_port_completion(
-PURB purb,
-PVOID pcontext
-)
+VOID
+hub_power_on_port_completion(PURB purb, PVOID pcontext)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DEV pdev;
- if( purb == NULL )
- return;
- if( pcontext == NULL )
- goto LBL_OUT;
-
- dev_mgr = ( PUSB_DEV_MANAGER ) pcontext;
-
- if( purb->status != STATUS_SUCCESS )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_power_on_port_completion(): port%d power on failed\n", purb->reference ) );
- }
- else
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_power_on_port_completion(): port%d power on succeed\n", purb->reference ) );
- }
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DEV pdev;
+ if (purb == NULL)
+ return;
+ if (pcontext == NULL)
+ goto LBL_OUT;
+
+ dev_mgr = (PUSB_DEV_MANAGER) pcontext;
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_power_on_port_completion(): port%d power on failed\n", purb->reference));
+ }
+ else
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("hub_power_on_port_completion(): port%d power on succeed\n", purb->reference));
+ }
LBL_OUT:
- usb_free_mem( purb );
- return;
+ usb_free_mem(purb);
+ return;
}
NTSTATUS
-hub_power_on_port(
-PUSB_DEV pdev,
-UCHAR port_idx
-)
+hub_power_on_port(PUSB_DEV pdev, UCHAR port_idx)
{
+ PUSB_ENDPOINT pendp;
+ NTSTATUS status;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_DEV_MANAGER dev_mgr;
+ PBYTE dev_ext;
+ DEV_HANDLE endp_handle;
+ PURB purb;
+ PHCD hcd;
+
+ USE_IRQL;
+ if (pdev == NULL || port_idx == 0)
+ return STATUS_INVALID_PARAMETER;
+
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb == NULL)
+ return STATUS_NO_MEMORY;
+
+ urb_init(purb);
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ status = STATUS_DEVICE_DOES_NOT_EXIST;
+ goto LBL_OUT;
+ }
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+
+ purb->completion = hub_power_on_port_completion;
+ purb->context = (PVOID) dev_mgr;
+ purb->reference = (ULONG) port_idx;
+ purb->pdev = pdev;
+ purb->pendp = &pdev->default_endp;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ psetup->bmRequestType = 0x23;
+ psetup->bRequest = USB_REQ_SET_FEATURE;
+ psetup->wValue = USB_PORT_FEAT_POWER;
+ psetup->wIndex = (WORD) port_idx;
+ psetup->wLength = 0;
- PUSB_ENDPOINT pendp;
- NTSTATUS status;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_DEV_MANAGER dev_mgr;
- PBYTE dev_ext;
- DEV_HANDLE endp_handle;
- PURB purb;
- PHCD hcd;
-
- USE_IRQL;
- if( pdev == NULL || port_idx == 0 )
- return STATUS_INVALID_PARAMETER;
-
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb == NULL )
- return STATUS_NO_MEMORY;
-
- urb_init( purb );
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- status = STATUS_DEVICE_DOES_NOT_EXIST;
- goto LBL_OUT;
- }
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
-
- purb->completion = hub_power_on_port_completion;
- purb->context = ( PVOID )dev_mgr;
- purb->reference = ( ULONG )port_idx;
- purb->pdev = pdev;
- purb->pendp = &pdev->default_endp;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET ) purb->setup_packet;
- psetup->bmRequestType = 0x23;
- psetup->bRequest = USB_REQ_SET_FEATURE;
- psetup->wValue = USB_PORT_FEAT_POWER;
- psetup->wIndex = ( WORD )port_idx;
- psetup->wLength = 0;
-
- unlock_dev( pdev, FALSE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
-
- if( status != STATUS_PENDING )
- {
- goto LBL_OUT;
- }
- return STATUS_PENDING;
-
- LBL_OUT:
-
- usb_free_mem( purb );
- return status;
+ unlock_dev(pdev, FALSE);
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+
+ if (status != STATUS_PENDING)
+ {
+ goto LBL_OUT;
+ }
+ return STATUS_PENDING;
+
+LBL_OUT:
+ usb_free_mem(purb);
+ return status;
}
void
-hub_get_hub_desc_completion(
-PURB purb,
-PVOID pcontext
-)
+hub_get_hub_desc_completion(PURB purb, PVOID pcontext)
{
- PUSB_DEV_MANAGER dev_mgr;
- PHUB2_EXTENSION hub_ext;
- PUSB_DEV pdev;
- LONG i;
- PUSB_INTERFACE pif;
- ULONG status;
- LONG port_count;
- PUSB_DRIVER pdriver;
- DEV_HANDLE dev_handle;
-
- USE_IRQL;
-
- if( purb == NULL )
- {
- return;
- }
-
- dev_mgr = ( PUSB_DEV_MANAGER ) pcontext;
- hub_ext = ( PHUB2_EXTENSION )purb->reference;
- pdriver = ( PUSB_DRIVER )purb->pirp;
- dev_handle = purb->endp_handle & 0xffff0000;
-
- if( pcontext == NULL || purb->reference == 0 )
- goto LBL_OUT;
-
- if( purb->status != STATUS_SUCCESS )
- {
- goto LBL_OUT;
- }
-
- // obtain the pointer to the dev
- status = usb_query_and_lock_dev( dev_mgr, purb->endp_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- usb_unlock_dev( pdev );
- goto LBL_OUT;
- }
- // 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_ZOMB ||
- dev_mgr_set_driver( dev_mgr, dev_handle, pdriver, pdev ) == FALSE )
- {
- unlock_dev( pdev, TRUE );
- goto LBL_OUT;
- }
-
- //transit the state to configured
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_CONFIGURED;
-
- pdev->dev_ext = ( PBYTE )hub_ext;
- pdev->dev_ext_size = sizeof( HUB2_EXTENSION );
-
- port_count = hub_ext->port_count = hub_ext->hub_desc.bNbrPorts;
- hub_ext->pdev = pdev;
- for( i = 0; i < pdev->usb_config->if_count; i++ )
- {
- pif = &pdev->usb_config->interf[ i ];
- if( pif->pusb_if_desc->bInterfaceClass == USB_CLASS_HUB
- && pif->pusb_if_desc->bInterfaceSubClass == 0
- && pif->pusb_if_desc->bInterfaceProtocol < 3
- && pif->pusb_if_desc->bNumEndpoints == 1 )
- {
- hub_ext->pif = pif;
- break;
- }
- }
- for( i = 0; i < MAX_HUB_PORTS + 1; i++ )
- {
- psq_init( ( PPORT_STATUS_QUEUE )hub_ext->port_status_queue );
- }
-
- hub_ext->multiple_tt = ( pif->pusb_if_desc->bInterfaceProtocol == 2 );
-
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
-
- hub_start_int_request( pdev );
-
- for( i = 0; i < port_count; i ++ )
- {
- hub_power_on_port( pdev, ( UCHAR )( i + 1 ) );
- }
- return;
-
- LBL_OUT:
- if( purb )
- usb_free_mem( purb );
-
- if( hub_ext )
- usb_free_mem( hub_ext );
- return;
+ PUSB_DEV_MANAGER dev_mgr;
+ PHUB2_EXTENSION hub_ext;
+ PUSB_DEV pdev;
+ LONG i;
+ PUSB_INTERFACE pif;
+ ULONG status;
+ LONG port_count;
+ PUSB_DRIVER pdriver;
+ DEV_HANDLE dev_handle;
+
+ USE_IRQL;
+
+ if (purb == NULL)
+ {
+ return;
+ }
+
+ dev_mgr = (PUSB_DEV_MANAGER) pcontext;
+ hub_ext = (PHUB2_EXTENSION) purb->reference;
+ pdriver = (PUSB_DRIVER) purb->pirp;
+ dev_handle = purb->endp_handle & 0xffff0000;
+
+ if (pcontext == NULL || purb->reference == 0)
+ goto LBL_OUT;
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ goto LBL_OUT;
+ }
+
+ // obtain the pointer to the dev
+ status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ usb_unlock_dev(pdev);
+ goto LBL_OUT;
+ }
+ // 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_ZOMB ||
+ dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
+ {
+ unlock_dev(pdev, TRUE);
+ goto LBL_OUT;
+ }
+
+ //transit the state to configured
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_CONFIGURED;
+
+ pdev->dev_ext = (PBYTE) hub_ext;
+ pdev->dev_ext_size = sizeof(HUB2_EXTENSION);
+
+ port_count = hub_ext->port_count = hub_ext->hub_desc.bNbrPorts;
+ hub_ext->pdev = pdev;
+ for(i = 0; i < pdev->usb_config->if_count; i++)
+ {
+ pif = &pdev->usb_config->interf[i];
+ if (pif->pusb_if_desc->bInterfaceClass == USB_CLASS_HUB
+ && pif->pusb_if_desc->bInterfaceSubClass == 0
+ && pif->pusb_if_desc->bInterfaceProtocol < 3 && pif->pusb_if_desc->bNumEndpoints == 1)
+ {
+ hub_ext->pif = pif;
+ break;
+ }
+ }
+ for(i = 0; i < MAX_HUB_PORTS + 1; i++)
+ {
+ psq_init((PPORT_STATUS_QUEUE) hub_ext->port_status_queue);
+ }
+
+ hub_ext->multiple_tt = (pif->pusb_if_desc->bInterfaceProtocol == 2);
+
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+
+ hub_start_int_request(pdev);
+
+ for(i = 0; i < port_count; i++)
+ {
+ hub_power_on_port(pdev, (UCHAR) (i + 1));
+ }
+ return;
+
+LBL_OUT:
+ if (purb)
+ usb_free_mem(purb);
+
+ if (hub_ext)
+ usb_free_mem(hub_ext);
+ return;
}
BOOL
-hub_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+hub_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- return TRUE;
+ return TRUE;
}
BOOL
-hub_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+hub_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- PUSB_DEV pdev;
- //special use of usb_query and lock dev
- if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) != STATUS_SUCCESS )
- {
- //will never be success, since the dev is already in zomb state
- //at this point, the dev is valid, ref_count is of none use,
- //no need to lock it
- if( pdev )
- {
- usb_free_mem( pdev->dev_ext );
- }
- }
-
- return TRUE;
+ PUSB_DEV pdev;
+ //special use of usb_query and lock dev
+ if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
+ {
+ //will never be success, since the dev is already in zomb state
+ //at this point, the dev is valid, ref_count is of none use,
+ //no need to lock it
+ if (pdev)
+ {
+ usb_free_mem(pdev->dev_ext);
+ }
+ }
+
+ return TRUE;
}
static BOOL
-hub_lock_unlock_tt(
-PUSB_DEV pdev,
-UCHAR port_idx,
-UCHAR type,
-BOOL lock
-)
+hub_lock_unlock_tt(PUSB_DEV pdev, UCHAR port_idx, UCHAR type, BOOL lock)
{
- PUSB_INTERFACE pif;
- PHUB2_EXTENSION dev_ext;
- PULONG pmap;
-
- USE_IRQL;
-
- if( pdev == NULL || port_idx > 127 )
- return FALSE;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return FALSE;
- }
-
- dev_ext = hub_ext_from_dev( pdev );
- if( dev_ext == NULL )
- {
- unlock_dev( pdev, FALSE );
- return FALSE;
- }
- if( type == USB_ENDPOINT_XFER_INT || \
- type == USB_ENDPOINT_XFER_ISOC )
- {
- pmap = dev_ext->tt_status_map;
- }
- else if( type == USB_ENDPOINT_XFER_BULK || \
- type == USB_ENDPOINT_XFER_CONTROL )
- {
- pmap = dev_ext->tt_bulk_map;
- }
-
- if( lock )
- {
- if( pmap[ port_idx >> 5 ] & ( 1 << port_idx ) )
- {
- unlock_dev( pdev, FALSE );
- return FALSE;
- }
- pmap[ port_idx >> 5 ] |= ( 1 << port_idx );
- }
- else
- {
- pmap[ port_idx >> 5 ] &= ~( 1 << port_idx );
- }
-
- unlock_dev( pdev, FALSE );
- return TRUE;
+ PUSB_INTERFACE pif;
+ PHUB2_EXTENSION dev_ext;
+ PULONG pmap;
+
+ USE_IRQL;
+
+ if (pdev == NULL || port_idx > 127)
+ return FALSE;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return FALSE;
+ }
+
+ dev_ext = hub_ext_from_dev(pdev);
+ if (dev_ext == NULL)
+ {
+ unlock_dev(pdev, FALSE);
+ return FALSE;
+ }
+ if (type == USB_ENDPOINT_XFER_INT || type == USB_ENDPOINT_XFER_ISOC)
+ {
+ pmap = dev_ext->tt_status_map;
+ }
+ else if (type == USB_ENDPOINT_XFER_BULK || type == USB_ENDPOINT_XFER_CONTROL)
+ {
+ pmap = dev_ext->tt_bulk_map;
+ }
+
+ if (lock)
+ {
+ if (pmap[port_idx >> 5] & (1 << port_idx))
+ {
+ unlock_dev(pdev, FALSE);
+ return FALSE;
+ }
+ pmap[port_idx >> 5] |= (1 << port_idx);
+ }
+ else
+ {
+ pmap[port_idx >> 5] &= ~(1 << port_idx);
+ }
+
+ unlock_dev(pdev, FALSE);
+ return TRUE;
}
BOOL
-hub_lock_tt(
-PUSB_DEV pdev,
-UCHAR port_idx,
-UCHAR type // transfer type
-)
+hub_lock_tt(PUSB_DEV pdev,
+ UCHAR port_idx,
+ UCHAR type // transfer type
+ )
{
- return hub_lock_unlock_tt( pdev, port_idx, type, TRUE );
+ return hub_lock_unlock_tt(pdev, port_idx, type, TRUE);
}
BOOL
-hub_unlock_tt(
-PUSB_DEV pdev,
-UCHAR port_idx,
-UCHAR type
-)
+hub_unlock_tt(PUSB_DEV pdev, UCHAR port_idx, UCHAR type)
{
- return hub_lock_unlock_tt( pdev, port_idx, type, FALSE );
+ return hub_lock_unlock_tt(pdev, port_idx, type, FALSE);
}
VOID
-hub_clear_tt_buffer_completion(
-PURB purb,
-PVOID context
-)
+hub_clear_tt_buffer_completion(PURB purb, PVOID context)
{
- PUSB_CTRL_SETUP_PACKET psetup;
- PURB_HS_PIPE_CONTENT pipe_content;
- PHUB2_EXTENSION hub_ext;
- PHCD hcd;
-
- if( purb == NULL || context == NULL )
- return;
-
- hub_ext = ( PHUB2_EXTENSION )context;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- pipe_content = ( PURB_HS_PIPE_CONTENT )&purb->reference;
- hub_unlock_tt( purb->pdev, ( UCHAR )psetup->wIndex, ( UCHAR )pipe_content->trans_type );
- usb_free_mem( purb );
- purb = NULL;
- hcd = hub_ext->pdev->hcd;
-
- // let those blocked urbs ( sharing the same tt )have chance to be scheduled
- if( hcd && usb2( hcd ) )
- hcd->hcd_submit_urb( hcd, NULL, NULL, NULL );
-
- return;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PURB_HS_PIPE_CONTENT pipe_content;
+ PHUB2_EXTENSION hub_ext;
+ PHCD hcd;
+
+ if (purb == NULL || context == NULL)
+ return;
+
+ hub_ext = (PHUB2_EXTENSION) context;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ pipe_content = (PURB_HS_PIPE_CONTENT) & purb->reference;
+ hub_unlock_tt(purb->pdev, (UCHAR) psetup->wIndex, (UCHAR) pipe_content->trans_type);
+ usb_free_mem(purb);
+ purb = NULL;
+ hcd = hub_ext->pdev->hcd;
+
+ // let those blocked urbs ( sharing the same tt )have chance to be scheduled
+ if (hcd && usb2(hcd))
+ hcd->hcd_submit_urb(hcd, NULL, NULL, NULL);
+
+ return;
}
-BOOL
-hub_clear_tt_buffer(
-PUSB_DEV pdev,
-URB_HS_PIPE_CONTENT pipe_content,
-UCHAR port_idx
-)
// send CLEAR_TT_BUFFER to the hub
+BOOL
+hub_clear_tt_buffer(PUSB_DEV pdev, URB_HS_PIPE_CONTENT pipe_content, UCHAR port_idx)
{
- PURB purb;
- PUSB_CTRL_SETUP_PACKET psetup;
- PHUB2_EXTENSION hub_ext;
- PHCD hcd;
- NTSTATUS status;
- USE_IRQL;
-
- if( pdev == NULL )
- return FALSE;
-
- if( pipe_content.speed_high )
- return FALSE;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return FALSE;
- }
-
- hub_ext = hub_ext_from_dev( pdev );
- if( hub_ext == NULL )
- {
- unlock_dev( pdev, FALSE );
- return FALSE;
- }
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- RtlZeroMemory( purb, sizeof( URB ) );
-
- if( purb == NULL )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_NO_MEMORY;
- }
+ PURB purb;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PHUB2_EXTENSION hub_ext;
+ PHCD hcd;
+ NTSTATUS status;
+ USE_IRQL;
+
+ if (pdev == NULL)
+ return FALSE;
+
+ if (pipe_content.speed_high)
+ return FALSE;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return FALSE;
+ }
+
+ hub_ext = hub_ext_from_dev(pdev);
+ if (hub_ext == NULL)
+ {
+ unlock_dev(pdev, FALSE);
+ return FALSE;
+ }
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ RtlZeroMemory(purb, sizeof(URB));
+
+ if (purb == NULL)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_NO_MEMORY;
+ }
purb->flags = 0;
- purb->status = STATUS_SUCCESS;
- purb->data_buffer = NULL;
- purb->data_length = 0; // ( hub_ext->port_count + 7 ) / 8;
+ purb->status = STATUS_SUCCESS;
+ purb->data_buffer = NULL;
+ purb->data_length = 0; // ( hub_ext->port_count + 7 ) / 8;
- // hub_if_from_dev( pdev, pif );
- purb->pendp = &pdev->default_endp;
- purb->pdev = pdev;
+ // hub_if_from_dev( pdev, pif );
+ purb->pendp = &pdev->default_endp;
+ purb->pdev = pdev;
purb->completion = hub_clear_tt_buffer_completion;
purb->context = hub_ext;
- purb->reference = *( ( PLONG )&pipe_content );
+ purb->reference = *((PLONG) & pipe_content);
purb->pirp = NULL;
- hcd = pdev->hcd;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- psetup->bmRequestType = 0x23; //host-device class other recepient
- psetup->bRequest = HUB_REQ_CLEAR_TT_BUFFER;
- psetup->wValue = ( USHORT )( ( pipe_content.endp_addr ) | ( pipe_content.dev_addr << 4 )| \
- ( pipe_content.trans_type << 10 ) | ( pipe_content.trans_dir << 15 ) );
-
- if( hub_ext->multiple_tt )
- {
- psetup->wIndex = ( USHORT )port_idx;
- }
- else
- psetup->wIndex = 1;
-
- psetup->wLength = 0;
- unlock_dev( pdev, FALSE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
- purb = NULL;
- return FALSE;
- }
- return TRUE;
+ hcd = pdev->hcd;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ psetup->bmRequestType = 0x23; //host-device class other recepient
+ psetup->bRequest = HUB_REQ_CLEAR_TT_BUFFER;
+ psetup->wValue = (USHORT) ((pipe_content.endp_addr) | (pipe_content.dev_addr << 4) |
+ (pipe_content.trans_type << 10) | (pipe_content.trans_dir << 15));
+
+ if (hub_ext->multiple_tt)
+ {
+ psetup->wIndex = (USHORT) port_idx;
+ }
+ else
+ psetup->wIndex = 1;
+
+ psetup->wLength = 0;
+ unlock_dev(pdev, FALSE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ return FALSE;
+ }
+ return TRUE;
}
BOOL
-hub_event_clear_tt_buffer(
-PUSB_DEV pdev, //always null. we do not use this param
-ULONG event,
-ULONG context,
-ULONG param
-)
+hub_event_clear_tt_buffer(PUSB_DEV pdev, //always null. we do not use this param
+ ULONG event,
+ ULONG context,
+ ULONG param)
{
- hub_clear_tt_buffer( pdev, *( ( PURB_HS_PIPE_CONTENT )&context ), ( UCHAR )param );
- return TRUE;
+ hub_clear_tt_buffer(pdev, *((PURB_HS_PIPE_CONTENT) & context), (UCHAR) param);
+ return TRUE;
}
VOID
-hub_post_clear_tt_event(
-PUSB_DEV pdev,
-BYTE port_idx,
-ULONG pipe
-)
+hub_post_clear_tt_event(PUSB_DEV pdev, BYTE port_idx, ULONG pipe)
{
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_EVENT pevent;
- USE_IRQL;
-
- dev_mgr = dev_mgr_from_dev( pdev );
-
- KeAcquireSpinLock( &dev_mgr->event_list_lock, &old_irql );
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- return;
- }
- pevent = alloc_event( &dev_mgr->event_pool, 1 );
- if( pevent == NULL )
- {
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
- TRAP();
- return;
- }
-
- pevent->event = USB_EVENT_WAIT_RESET_PORT;
- pevent->pdev = pdev;
- pevent->context = pipe;
- pevent->param = port_idx;
- pevent->flags = USB_EVENT_FLAG_ACTIVE;
- pevent->process_queue = event_list_default_process_queue;
- pevent->process_event = hub_event_clear_tt_buffer;
- pevent->pnext = NULL;
- InsertTailList( &dev_mgr->event_list, &pevent->event_link );
-
- unlock_dev( pdev, TRUE );
- KeReleaseSpinLock( &dev_mgr->event_list_lock, old_irql );
-
- KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE );
- return;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_EVENT pevent;
+ USE_IRQL;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ return;
+ }
+ pevent = alloc_event(&dev_mgr->event_pool, 1);
+ if (pevent == NULL)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+ TRAP();
+ return;
+ }
+
+ pevent->event = USB_EVENT_WAIT_RESET_PORT;
+ pevent->pdev = pdev;
+ pevent->context = pipe;
+ pevent->param = port_idx;
+ pevent->flags = USB_EVENT_FLAG_ACTIVE;
+ pevent->process_queue = event_list_default_process_queue;
+ pevent->process_event = hub_event_clear_tt_buffer;
+ pevent->pnext = NULL;
+ InsertTailList(&dev_mgr->event_list, &pevent->event_link);
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
+
+ KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
+ return;
}
BOOL
-init_irp_list(
-PIRP_LIST irp_list
-)
+init_irp_list(PIRP_LIST irp_list)
{
- LONG i;
- KeInitializeSpinLock( &irp_list->irp_list_lock );
- InitializeListHead( &irp_list->irp_busy_list );
- InitializeListHead( &irp_list->irp_free_list );
- irp_list->irp_list_element_array = usb_alloc_mem( NonPagedPool, sizeof( IRP_LIST_ELEMENT ) * MAX_IRP_LIST_SIZE );
-
- if( irp_list->irp_list_element_array == NULL )
- return FALSE;
-
- RtlZeroMemory( irp_list->irp_list_element_array, sizeof( IRP_LIST_ELEMENT ) * MAX_IRP_LIST_SIZE );
- for( i = 0; i < MAX_IRP_LIST_SIZE; i++ )
- {
- InsertTailList( &irp_list->irp_free_list, &irp_list->irp_list_element_array[ i ].irp_link );
- }
- irp_list->irp_free_list_count = MAX_IRP_LIST_SIZE;
- return TRUE;
+ LONG i;
+ KeInitializeSpinLock(&irp_list->irp_list_lock);
+ InitializeListHead(&irp_list->irp_busy_list);
+ InitializeListHead(&irp_list->irp_free_list);
+ irp_list->irp_list_element_array =
+ usb_alloc_mem(NonPagedPool, sizeof(IRP_LIST_ELEMENT) * MAX_IRP_LIST_SIZE);
+
+ if (irp_list->irp_list_element_array == NULL)
+ return FALSE;
+
+ RtlZeroMemory(irp_list->irp_list_element_array, sizeof(IRP_LIST_ELEMENT) * MAX_IRP_LIST_SIZE);
+ for(i = 0; i < MAX_IRP_LIST_SIZE; i++)
+ {
+ InsertTailList(&irp_list->irp_free_list, &irp_list->irp_list_element_array[i].irp_link);
+ }
+ irp_list->irp_free_list_count = MAX_IRP_LIST_SIZE;
+ return TRUE;
}
VOID
-destroy_irp_list(
-PIRP_LIST irp_list
-)
+destroy_irp_list(PIRP_LIST irp_list)
{
- InitializeListHead( &irp_list->irp_busy_list );
- InitializeListHead( &irp_list->irp_free_list );
- usb_free_mem( irp_list->irp_list_element_array );
- irp_list->irp_list_element_array = NULL;
- irp_list->irp_free_list_count = 0;
- return;
+ InitializeListHead(&irp_list->irp_busy_list);
+ InitializeListHead(&irp_list->irp_free_list);
+ usb_free_mem(irp_list->irp_list_element_array);
+ irp_list->irp_list_element_array = NULL;
+ irp_list->irp_free_list_count = 0;
+ return;
}
BOOL
-add_irp_to_list(
-PIRP_LIST irp_list,
-PIRP pirp,
-PURB purb
-)
+add_irp_to_list(PIRP_LIST irp_list, PIRP pirp, PURB purb)
{
- KIRQL old_irql;
- PIRP_LIST_ELEMENT pile;
+ KIRQL old_irql;
+ PIRP_LIST_ELEMENT pile;
- if( irp_list == NULL || pirp == NULL || purb == NULL )
- return FALSE;
+ if (irp_list == NULL || pirp == NULL || purb == NULL)
+ return FALSE;
- IoAcquireCancelSpinLock( &old_irql );
- KeAcquireSpinLockAtDpcLevel( &irp_list->irp_list_lock );
+ IoAcquireCancelSpinLock(&old_irql);
+ KeAcquireSpinLockAtDpcLevel(&irp_list->irp_list_lock);
- if( irp_list->irp_free_list_count == 0 )
- {
- KeReleaseSpinLockFromDpcLevel( &irp_list->irp_list_lock );
- IoReleaseCancelSpinLock( old_irql );
- return FALSE;
- }
- pile = ( PIRP_LIST_ELEMENT )RemoveHeadList( &irp_list->irp_free_list );
+ if (irp_list->irp_free_list_count == 0)
+ {
+ KeReleaseSpinLockFromDpcLevel(&irp_list->irp_list_lock);
+ IoReleaseCancelSpinLock(old_irql);
+ return FALSE;
+ }
+ pile = (PIRP_LIST_ELEMENT) RemoveHeadList(&irp_list->irp_free_list);
- pile->pirp = pirp;
- pile->purb = purb;
+ pile->pirp = pirp;
+ pile->purb = purb;
- irp_list->irp_free_list_count--;
- InsertTailList( &irp_list->irp_busy_list, &pile->irp_link );
- IoSetCancelRoutine( pirp, dev_mgr_cancel_irp );
+ irp_list->irp_free_list_count--;
+ InsertTailList(&irp_list->irp_busy_list, &pile->irp_link);
+ IoSetCancelRoutine(pirp, dev_mgr_cancel_irp);
- KeReleaseSpinLockFromDpcLevel( &irp_list->irp_list_lock );
- IoReleaseCancelSpinLock( old_irql );
- return TRUE;
+ KeReleaseSpinLockFromDpcLevel(&irp_list->irp_list_lock);
+ IoReleaseCancelSpinLock(old_irql);
+ return TRUE;
}
PURB
-remove_irp_from_list(
-PIRP_LIST irp_list,
-PIRP pirp,
-PUSB_DEV_MANAGER dev_mgr //if dev_mgr is not NULL, the urb needs to be canceled
-)
+remove_irp_from_list(PIRP_LIST irp_list,
+ PIRP pirp,
+ PUSB_DEV_MANAGER dev_mgr //if dev_mgr is not NULL, the urb needs to be canceled
+ )
{
- PIRP_LIST_ELEMENT pile;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- DEV_HANDLE endp_handle;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- PHCD hcd;
-
- USE_IRQL;
-
- if( irp_list == NULL || pirp == NULL )
- return NULL;
-
- KeAcquireSpinLock( &irp_list->irp_list_lock, &old_irql );
-
- if( irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE )
- {
- KeReleaseSpinLock( &irp_list->irp_list_lock, old_irql );
- return NULL;
- }
-
- purb = NULL;
- ListFirst( &irp_list->irp_busy_list, pthis );
- while( pthis )
- {
- pile = struct_ptr( pthis, IRP_LIST_ELEMENT, irp_link );
- if( pile->pirp == pirp )
- {
- purb = pile->purb;
- pile->pirp = NULL;
- pile->purb = NULL;
- RemoveEntryList( pthis );
- InsertTailList( &irp_list->irp_free_list, pthis );
- irp_list->irp_free_list_count++;
- break;
- }
- ListNext( &irp_list->irp_busy_list, pthis, pnext );
- pthis = pnext;
- }
-
- if( purb == NULL )
- {
- // not found
- KeReleaseSpinLock( &irp_list->irp_list_lock, old_irql );
- return NULL;
- }
-
- endp_handle = purb->endp_handle;
- KeReleaseSpinLock( &irp_list->irp_list_lock, old_irql );
-
- if( dev_mgr )
- {
- // indicate we needs to cancel the urb, this condition happens only in cancel routine
- // we should notice that even the hcd_cancel_urb is called, the irp may not be canceled
- // if the urb does not exist in any queue of the host controller driver, indicating
- // it is being processed by dpc. Thus, the dpc will certainly prevent the irp in
- // completion from being canceled at the same time. On the other hand, if the
- // hcd_cancel_urb succeeds, it either directly complete the irp or queue the dpc for
- // irp completion. So, there won't be two simutaneous threads processing the same
- // irp.
-
- if( usb_query_and_lock_dev( dev_mgr, endp_handle, &pdev ) != STATUS_SUCCESS )
- return NULL;
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
- return NULL;
- }
-
- hcd = pdev->hcd;
- endp_from_handle( pdev, endp_handle, pendp );
- unlock_dev( pdev, TRUE );
- hcd->hcd_cancel_urb( hcd, pdev, pendp, purb );
- usb_unlock_dev( pdev );
- return NULL;
- }
- return purb;
+ PIRP_LIST_ELEMENT pile;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ DEV_HANDLE endp_handle;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ PHCD hcd;
+
+ USE_IRQL;
+
+ if (irp_list == NULL || pirp == NULL)
+ return NULL;
+
+ KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql);
+
+ if (irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE)
+ {
+ KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql);
+ return NULL;
+ }
+
+ purb = NULL;
+ ListFirst(&irp_list->irp_busy_list, pthis);
+ while (pthis)
+ {
+ pile = struct_ptr(pthis, IRP_LIST_ELEMENT, irp_link);
+ if (pile->pirp == pirp)
+ {
+ purb = pile->purb;
+ pile->pirp = NULL;
+ pile->purb = NULL;
+ RemoveEntryList(pthis);
+ InsertTailList(&irp_list->irp_free_list, pthis);
+ irp_list->irp_free_list_count++;
+ break;
+ }
+ ListNext(&irp_list->irp_busy_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ if (purb == NULL)
+ {
+ // not found
+ KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql);
+ return NULL;
+ }
+
+ endp_handle = purb->endp_handle;
+ KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql);
+
+ if (dev_mgr)
+ {
+ // indicate we needs to cancel the urb, this condition happens only in cancel routine
+ // we should notice that even the hcd_cancel_urb is called, the irp may not be canceled
+ // if the urb does not exist in any queue of the host controller driver, indicating
+ // it is being processed by dpc. Thus, the dpc will certainly prevent the irp in
+ // completion from being canceled at the same time. On the other hand, if the
+ // hcd_cancel_urb succeeds, it either directly complete the irp or queue the dpc for
+ // irp completion. So, there won't be two simutaneous threads processing the same
+ // irp.
+
+ if (usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev) != STATUS_SUCCESS)
+ return NULL;
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+ return NULL;
+ }
+
+ hcd = pdev->hcd;
+ endp_from_handle(pdev, endp_handle, pendp);
+ unlock_dev(pdev, TRUE);
+ hcd->hcd_cancel_urb(hcd, pdev, pendp, purb);
+ usb_unlock_dev(pdev);
+ return NULL;
+ }
+ return purb;
}
BOOL
-irp_list_empty(
-PIRP_LIST irp_list
-)
+irp_list_empty(PIRP_LIST irp_list)
{
- KIRQL old_irql;
- BOOL ret;
- KeAcquireSpinLock( &irp_list->irp_list_lock, &old_irql );
- ret = ( irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE );
- KeReleaseSpinLock( &irp_list->irp_list_lock, old_irql );
- return ret;
+ KIRQL old_irql;
+ BOOL ret;
+ KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql);
+ ret = (irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE);
+ KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql);
+ return ret;
}
BOOL
-irp_list_full(
-PIRP_LIST irp_list
-)
+irp_list_full(PIRP_LIST irp_list)
{
- KIRQL old_irql;
- BOOL ret;
- KeAcquireSpinLock( &irp_list->irp_list_lock, &old_irql );
- ret = ( irp_list->irp_free_list_count == 0 );
- KeReleaseSpinLock( &irp_list->irp_list_lock, old_irql );
- return ret;
+ KIRQL old_irql;
+ BOOL ret;
+ KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql);
+ ret = (irp_list->irp_free_list_count == 0);
+ KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql);
+ return ret;
}
-
-
-VOID
-zzz()
-{};
#define UHCI_MIN_TD_POOLS 4
-BOOL
-free_td_to_pool(
-PUHCI_TD_POOL ptd_pool,
-PUHCI_TD ptd
-); //add tds till pnext == NULL
+BOOL free_td_to_pool(PUHCI_TD_POOL ptd_pool, PUHCI_TD ptd); //add tds till pnext == NULL
-PUHCI_QH
-alloc_qh(
-PUHCI_QH_POOL pqh_pool
-); //null if failed
+PUHCI_QH alloc_qh(PUHCI_QH_POOL pqh_pool); //null if failed
BOOL
-init_td_pool(
-PUHCI_TD_POOL ptd_pool
-)
+init_td_pool(PUHCI_TD_POOL ptd_pool)
{
int i, pages;
- PTD_EXTENSION ptde;
- PHYSICAL_ADDRESS phys_addr;
-
+ PTD_EXTENSION ptde;
+ PHYSICAL_ADDRESS phys_addr;
+
if (ptd_pool == NULL)
return FALSE;
- if( ptd_pool->padapter == NULL)
- return FALSE;
-
- pages = sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE;
- RtlZeroMemory( ptd_pool->td_array, sizeof( ptd_pool->td_array ) );
- RtlZeroMemory( ptd_pool->logic_addr, sizeof( ptd_pool->logic_addr ) );
-
- for( i = 0; i < pages; i++ )
- {
- ptd_pool->td_array[ i ] =
- HalAllocateCommonBuffer(
- ptd_pool->padapter,
- PAGE_SIZE,
- &ptd_pool->logic_addr[ i ],
- FALSE);
- if( ptd_pool->td_array[ i ] == NULL )
- goto failed;
- }
-
- ptd_pool->tde_array = ( PTD_EXTENSION )usb_alloc_mem(
- NonPagedPool,
- sizeof( TD_EXTENSION ) * UHCI_MAX_POOL_TDS );
-
+ if (ptd_pool->padapter == NULL)
+ return FALSE;
+
+ pages = sizeof(UHCI_TD) * UHCI_MAX_POOL_TDS / PAGE_SIZE;
+ RtlZeroMemory(ptd_pool->td_array, sizeof(ptd_pool->td_array));
+ RtlZeroMemory(ptd_pool->logic_addr, sizeof(ptd_pool->logic_addr));
+
+ for(i = 0; i < pages; i++)
+ {
+ ptd_pool->td_array[i] =
+ HalAllocateCommonBuffer(ptd_pool->padapter, PAGE_SIZE, &ptd_pool->logic_addr[i], FALSE);
+ if (ptd_pool->td_array[i] == NULL)
+ goto failed;
+ }
+
+ ptd_pool->tde_array = (PTD_EXTENSION) usb_alloc_mem(NonPagedPool,
+ sizeof(TD_EXTENSION) * UHCI_MAX_POOL_TDS);
+
if (ptd_pool->tde_array == NULL)
goto failed;
- for( i = 0; i < pages; i++ )
- {
- RtlZeroMemory( ptd_pool->td_array[ i ], PAGE_SIZE );
- }
-
- RtlZeroMemory(
- ptd_pool->tde_array,
- sizeof( TD_EXTENSION ) * UHCI_MAX_POOL_TDS );
-
- ptde = ptd_pool->tde_array;
- ptd_pool->free_count = 0;
- ptd_pool->total_count = UHCI_MAX_POOL_TDS;
- InitializeListHead( &ptd_pool->free_que);
-
- for( i = 0; i < UHCI_MAX_POOL_TDS; i++ )
+ for(i = 0; i < pages; i++)
+ {
+ RtlZeroMemory(ptd_pool->td_array[i], PAGE_SIZE);
+ }
+
+ RtlZeroMemory(ptd_pool->tde_array, sizeof(TD_EXTENSION) * UHCI_MAX_POOL_TDS);
+
+ ptde = ptd_pool->tde_array;
+ ptd_pool->free_count = 0;
+ ptd_pool->total_count = UHCI_MAX_POOL_TDS;
+ InitializeListHead(&ptd_pool->free_que);
+
+ for(i = 0; i < UHCI_MAX_POOL_TDS; i++)
{
//link tde and the td one by one, fixed since this init
- ptd_pool->td_array[ i >> 7 ][ i & 0x7f ].ptde = &ptde[ i ];
- ptde[ i ].ptd = &ptd_pool->td_array[ i >> 7 ][ i & 0x7f ];
- ptde[ i ].flags = UHCI_ITEM_FLAG_TD;
- ptd_pool->td_array[ i >> 7 ][ i & 0x7f ].phy_addr = ptd_pool->logic_addr[ i >> 7 ].LowPart + ( i & 0x7f ) * sizeof( UHCI_TD );
- ptd_pool->td_array[ i >> 7 ][ i & 0x7f ].pool = ptd_pool;
- ptd_pool->td_array[ i >> 7 ][ i & 0x7f ].purb = NULL;
- free_td_to_pool( ptd_pool, &ptd_pool->td_array[ i >> 7 ][ i & 0x7f ]);
-
+ ptd_pool->td_array[i >> 7][i & 0x7f].ptde = &ptde[i];
+ ptde[i].ptd = &ptd_pool->td_array[i >> 7][i & 0x7f];
+ ptde[i].flags = UHCI_ITEM_FLAG_TD;
+ ptd_pool->td_array[i >> 7][i & 0x7f].phy_addr =
+ ptd_pool->logic_addr[i >> 7].LowPart + (i & 0x7f) * sizeof(UHCI_TD);
+ ptd_pool->td_array[i >> 7][i & 0x7f].pool = ptd_pool;
+ ptd_pool->td_array[i >> 7][i & 0x7f].purb = NULL;
+ free_td_to_pool(ptd_pool, &ptd_pool->td_array[i >> 7][i & 0x7f]);
+
}
- return TRUE;
-
- failed:
- for( i = 0; i < pages; i++ )
- {
- if( ptd_pool->td_array[ i ] )
- {
- HalFreeCommonBuffer( ptd_pool->padapter,
- PAGE_SIZE,
- ptd_pool->logic_addr[ i ],
- ptd_pool->td_array[ i ],
- FALSE);
- ptd_pool->td_array[ i ] = NULL;
- ptd_pool->logic_addr[ i ].QuadPart = 0;
- }
- }
-
- if( ptd_pool->tde_array )
- usb_free_mem( ptd_pool->tde_array);
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "init_td_pool(): failed to init the td pool\n" ) );
- TRAP();
-
+ return TRUE;
+
+failed:
+ for(i = 0; i < pages; i++)
+ {
+ if (ptd_pool->td_array[i])
+ {
+ HalFreeCommonBuffer(ptd_pool->padapter,
+ PAGE_SIZE, ptd_pool->logic_addr[i], ptd_pool->td_array[i], FALSE);
+ ptd_pool->td_array[i] = NULL;
+ ptd_pool->logic_addr[i].QuadPart = 0;
+ }
+ }
+
+ if (ptd_pool->tde_array)
+ usb_free_mem(ptd_pool->tde_array);
+
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("init_td_pool(): failed to init the td pool\n"));
+ TRAP();
+
ptd_pool->free_count = ptd_pool->total_count = 0;
- return FALSE;
+ return FALSE;
}
+//add tds till pnext == NULL
BOOL
-free_td_to_pool(
-PUHCI_TD_POOL ptd_pool,
-PUHCI_TD ptd
-) //add tds till pnext == NULL
+free_td_to_pool(PUHCI_TD_POOL ptd_pool, PUHCI_TD ptd)
{
- if( ptd_pool == NULL || ptd == NULL )
- {
- return FALSE;
- }
+ if (ptd_pool == NULL || ptd == NULL)
+ {
+ return FALSE;
+ }
+
+ ptd->link = ptd->status = ptd->info = ptd->buffer = 0;
+ ptd->purb = NULL;
+ ptd_pool->free_count++;
- ptd->link = ptd->status = ptd->info = ptd->buffer = 0;
- ptd->purb = NULL;
- ptd_pool->free_count++;
+ InsertTailList(&ptd_pool->free_que, &ptd->ptde->vert_link);
- InsertTailList( &ptd_pool->free_que, &ptd->ptde->vert_link);
+ return TRUE;
- return TRUE;
-
}
+
// qh routines
+
+//null if failed
PUHCI_TD
-alloc_td_from_pool(
-PUHCI_TD_POOL ptd_pool
-) //null if failed
+alloc_td_from_pool(PUHCI_TD_POOL ptd_pool)
{
- PTD_EXTENSION ptde;
- PLIST_ENTRY temp;
-
- if( ptd_pool == NULL )
- return FALSE;
-
- if( IsListEmpty( &ptd_pool->free_que ) )
- return FALSE;
-
- temp = RemoveHeadList( &ptd_pool->free_que );
+ PTD_EXTENSION ptde;
+ PLIST_ENTRY temp;
+
+ if (ptd_pool == NULL)
+ return FALSE;
+
+ if (IsListEmpty(&ptd_pool->free_que))
+ return FALSE;
- if( temp == NULL )
- return FALSE;
+ temp = RemoveHeadList(&ptd_pool->free_que);
- ptde = struct_ptr( temp, TD_EXTENSION, vert_link );
+ if (temp == NULL)
+ return FALSE;
+
+ ptde = struct_ptr(temp, TD_EXTENSION, vert_link);
- ptd_pool->free_count--;
-
- InitializeListHead( &ptde->vert_link );
- InitializeListHead( &ptde->hori_link );
+ ptd_pool->free_count--;
- return ptde->ptd;
+ InitializeListHead(&ptde->vert_link);
+ InitializeListHead(&ptde->hori_link);
+
+ return ptde->ptd;
}
+//test whether the pool is all free
BOOL
-is_pool_free(
-PUHCI_TD_POOL pool
-) //test whether the pool is all free
+is_pool_free(PUHCI_TD_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- if( pool->free_count == pool->total_count )
- return TRUE;
+ if (pool->free_count == pool->total_count)
+ return TRUE;
- return FALSE;
+ return FALSE;
}
BOOL
-is_pool_empty(
-PUHCI_TD_POOL pool
-)
+is_pool_empty(PUHCI_TD_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- return ( pool->free_count == 0 );
+ return (pool->free_count == 0);
}
BOOL
-destroy_td_pool(
-PUHCI_TD_POOL ptd_pool
-)
+destroy_td_pool(PUHCI_TD_POOL ptd_pool)
{
int i, pages;
- PADAPTER_OBJECT padapter; //we need this garbage for allocation
+ PADAPTER_OBJECT padapter; //we need this garbage for allocation
padapter = ptd_pool->padapter;
-
- pages = sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE;
- if( ptd_pool && ptd_pool->padapter )
+
+ pages = sizeof(UHCI_TD) * UHCI_MAX_POOL_TDS / PAGE_SIZE;
+ if (ptd_pool && ptd_pool->padapter)
{
- usb_free_mem( ptd_pool->tde_array );
- ptd_pool->tde_array = NULL;
- for( i = 0; i < pages; i++ )
- {
- if( ptd_pool->td_array[ i ] )
- {
- HalFreeCommonBuffer( ptd_pool->padapter,
- PAGE_SIZE,
- ptd_pool->logic_addr[ i ],
- ptd_pool->td_array[ i ],
- FALSE);
- ptd_pool->td_array[ i ] = NULL;
- ptd_pool->logic_addr[ i ].QuadPart = 0;
- }
- }
- RtlZeroMemory( ptd_pool, sizeof( UHCI_TD_POOL ) );
- ptd_pool->padapter = padapter;
- ptd_pool->free_count = ptd_pool->total_count = 0;
- }
- else
- return FALSE;
-
- return TRUE;
+ usb_free_mem(ptd_pool->tde_array);
+ ptd_pool->tde_array = NULL;
+ for(i = 0; i < pages; i++)
+ {
+ if (ptd_pool->td_array[i])
+ {
+ HalFreeCommonBuffer(ptd_pool->padapter,
+ PAGE_SIZE, ptd_pool->logic_addr[i], ptd_pool->td_array[i], FALSE);
+ ptd_pool->td_array[i] = NULL;
+ ptd_pool->logic_addr[i].QuadPart = 0;
+ }
+ }
+ RtlZeroMemory(ptd_pool, sizeof(UHCI_TD_POOL));
+ ptd_pool->padapter = padapter;
+ ptd_pool->free_count = ptd_pool->total_count = 0;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
}
BOOL
-init_td_pool_list(
-PUHCI_TD_POOL_LIST pool_list,
-PADAPTER_OBJECT padapter
-)
+init_td_pool_list(PUHCI_TD_POOL_LIST pool_list, PADAPTER_OBJECT padapter)
{
- int i;
- RtlZeroMemory( pool_list, sizeof( UHCI_TD_POOL_LIST));
- InitializeListHead( &pool_list->busy_pools );
- InitializeListHead( &pool_list->free_pools );
-
- pool_list->free_count = UHCI_MAX_TD_POOLS;
- pool_list->free_tds = 0;
-
- for( i = 0; i < UHCI_MAX_TD_POOLS; i++)
- {
- pool_list->pool_array[i].padapter = padapter;
- InsertTailList( &pool_list->free_pools, &pool_list->pool_array[i].pool_link);
- }
-
- KeInitializeSpinLock( &pool_list->pool_lock );
- return expand_pool_list( pool_list, UHCI_MIN_TD_POOLS );
+ int i;
+ RtlZeroMemory(pool_list, sizeof(UHCI_TD_POOL_LIST));
+ InitializeListHead(&pool_list->busy_pools);
+ InitializeListHead(&pool_list->free_pools);
+
+ pool_list->free_count = UHCI_MAX_TD_POOLS;
+ pool_list->free_tds = 0;
+
+ for(i = 0; i < UHCI_MAX_TD_POOLS; i++)
+ {
+ pool_list->pool_array[i].padapter = padapter;
+ InsertTailList(&pool_list->free_pools, &pool_list->pool_array[i].pool_link);
+ }
+
+ KeInitializeSpinLock(&pool_list->pool_lock);
+ return expand_pool_list(pool_list, UHCI_MIN_TD_POOLS);
}
BOOL
-destroy_td_pool_list(
-PUHCI_TD_POOL_LIST pool_list
-)
+destroy_td_pool_list(PUHCI_TD_POOL_LIST pool_list)
{
- PUHCI_TD_POOL pool;
- while( IsListEmpty( &pool_list->busy_pools) == FALSE )
- {
- pool = (PUHCI_TD_POOL) RemoveHeadList( &pool_list->busy_pools);
- destroy_td_pool( pool );
- }
-
- RtlZeroMemory( pool_list, sizeof( UHCI_TD_POOL_LIST ));
- return TRUE;
+ PUHCI_TD_POOL pool;
+ while (IsListEmpty(&pool_list->busy_pools) == FALSE)
+ {
+ pool = (PUHCI_TD_POOL) RemoveHeadList(&pool_list->busy_pools);
+ destroy_td_pool(pool);
+ }
+
+ RtlZeroMemory(pool_list, sizeof(UHCI_TD_POOL_LIST));
+ return TRUE;
}
BOOL
-expand_pool_list(
-PUHCI_TD_POOL_LIST pool_list,
-LONG pool_count
-) //private
+expand_pool_list(PUHCI_TD_POOL_LIST pool_list, LONG pool_count) //private
{
- PUHCI_TD_POOL pool;
- int i;
-
- if( IsListEmpty( &pool_list->free_pools) == TRUE )
- return FALSE;
-
- if( pool_list->free_count < pool_count )
- return FALSE;
-
- for( i = 0; i < pool_count; i++ )
- {
- pool = (PUHCI_TD_POOL) RemoveHeadList( &pool_list->free_pools);
-
- if( init_td_pool( pool ) == FALSE )
- {
- //reverse the allocation
- InsertHeadList( &pool_list->free_pools, &pool->pool_link );
- // collect_garbage( pool_list );
- return FALSE;
- }
-
- InsertTailList( &pool_list->busy_pools, &pool->pool_link );
- pool_list->free_tds += UHCI_MAX_POOL_TDS;
- pool_list->free_count--;
- }
- return TRUE;
+ PUHCI_TD_POOL pool;
+ int i;
+
+ if (IsListEmpty(&pool_list->free_pools) == TRUE)
+ return FALSE;
+
+ if (pool_list->free_count < pool_count)
+ return FALSE;
+
+ for(i = 0; i < pool_count; i++)
+ {
+ pool = (PUHCI_TD_POOL) RemoveHeadList(&pool_list->free_pools);
+
+ if (init_td_pool(pool) == FALSE)
+ {
+ //reverse the allocation
+ InsertHeadList(&pool_list->free_pools, &pool->pool_link);
+ // collect_garbage( pool_list );
+ return FALSE;
+ }
+
+ InsertTailList(&pool_list->busy_pools, &pool->pool_link);
+ pool_list->free_tds += UHCI_MAX_POOL_TDS;
+ pool_list->free_count--;
+ }
+ return TRUE;
}
BOOL
-collect_garbage(
-PUHCI_TD_POOL_LIST pool_list
-)
+collect_garbage(PUHCI_TD_POOL_LIST pool_list)
{
- PLIST_ENTRY prev, next;
-
- // no garbage
- if( pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS )
- return TRUE;
-
- ListFirstPrev( &pool_list->busy_pools, prev);
- ListNext( &pool_list->busy_pools, prev, next);
-
- while( next && next != &pool_list->busy_pools)
- {
- if( is_pool_free( (PUHCI_TD_POOL)next ) )
- {
- RemoveEntryList( next );
- destroy_td_pool( ( PUHCI_TD_POOL )next );
- InsertTailList( &pool_list->free_pools, next);
- pool_list->free_count++;
- pool_list->free_tds -= UHCI_MAX_POOL_TDS;
- ListNext( &pool_list->busy_pools, prev, next);
- if( pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS )
- break;
- }
- else
- {
- prev = next;
- ListNext( &pool_list->busy_pools, prev, next);
- }
- }
- return TRUE;
+ PLIST_ENTRY prev, next;
+
+ // no garbage
+ if (pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS)
+ return TRUE;
+
+ ListFirstPrev(&pool_list->busy_pools, prev);
+ ListNext(&pool_list->busy_pools, prev, next);
+
+ while (next && next != &pool_list->busy_pools)
+ {
+ if (is_pool_free((PUHCI_TD_POOL) next))
+ {
+ RemoveEntryList(next);
+ destroy_td_pool((PUHCI_TD_POOL) next);
+ InsertTailList(&pool_list->free_pools, next);
+ pool_list->free_count++;
+ pool_list->free_tds -= UHCI_MAX_POOL_TDS;
+ ListNext(&pool_list->busy_pools, prev, next);
+ if (pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS)
+ break;
+ }
+ else
+ {
+ prev = next;
+ ListNext(&pool_list->busy_pools, prev, next);
+ }
+ }
+ return TRUE;
}
//private
LONG
-get_num_free_tds(
-PUHCI_TD_POOL_LIST pool_list
-)
+get_num_free_tds(PUHCI_TD_POOL_LIST pool_list)
{
- return pool_list->free_tds;
+ return pool_list->free_tds;
}
-//private
+//private
LONG
-get_max_free_tds(
-PUHCI_TD_POOL_LIST pool_list
-)
+get_max_free_tds(PUHCI_TD_POOL_LIST pool_list)
{
- return pool_list->free_tds + pool_list->free_count * UHCI_MAX_POOL_TDS;
+ return pool_list->free_tds + pool_list->free_count * UHCI_MAX_POOL_TDS;
}
+//add tds till pnext == NULL
BOOL
-free_td(
-PUHCI_TD_POOL_LIST pool_list,
-PUHCI_TD ptd
-) //add tds till pnext == NULL
+free_td(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd)
{
- if( pool_list == NULL || ptd == NULL )
- return FALSE;
+ if (pool_list == NULL || ptd == NULL)
+ return FALSE;
- if( free_td_to_pool( ptd->pool, ptd ) == FALSE )
- return FALSE;
+ if (free_td_to_pool(ptd->pool, ptd) == FALSE)
+ return FALSE;
- pool_list->free_tds++;
+ pool_list->free_tds++;
- if( is_pool_free( ptd->pool ) )
- {
- collect_garbage( pool_list );
- }
- return TRUE;
+ if (is_pool_free(ptd->pool))
+ {
+ collect_garbage(pool_list);
+ }
+ return TRUE;
}
+//null if failed
PUHCI_TD
-alloc_td(
-PUHCI_TD_POOL_LIST pool_list
-) //null if failed
+alloc_td(PUHCI_TD_POOL_LIST pool_list)
{
- PLIST_ENTRY prev, next;
- PUHCI_TD new_td;
+ PLIST_ENTRY prev, next;
+ PUHCI_TD new_td;
- if( pool_list == NULL )
- return NULL;
+ if (pool_list == NULL)
+ return NULL;
- if( pool_list->free_tds == 0 )
- {
- if( expand_pool_list( pool_list, 1 ) == FALSE )
- return NULL;
- }
+ if (pool_list->free_tds == 0)
+ {
+ if (expand_pool_list(pool_list, 1) == FALSE)
+ return NULL;
+ }
- ListFirst( &pool_list->busy_pools, prev );
+ ListFirst(&pool_list->busy_pools, prev);
- while( prev && prev != &pool_list->busy_pools )
- {
- if( is_pool_empty( (PUHCI_TD_POOL) prev ) == FALSE )
- {
- new_td = alloc_td_from_pool( (PUHCI_TD_POOL) prev );
+ while (prev && prev != &pool_list->busy_pools)
+ {
+ if (is_pool_empty((PUHCI_TD_POOL) prev) == FALSE)
+ {
+ new_td = alloc_td_from_pool((PUHCI_TD_POOL) prev);
- if( new_td == NULL )
- TRAP();
+ if (new_td == NULL)
+ TRAP();
- pool_list->free_tds--;
+ pool_list->free_tds--;
- return new_td;
- }
+ return new_td;
+ }
- ListNext( &pool_list->busy_pools, prev, next);
+ ListNext(&pool_list->busy_pools, prev, next);
prev = next;
- }
+ }
- return NULL;
+ return NULL;
}
PUHCI_TD
-alloc_tds(
-PUHCI_TD_POOL_LIST pool_list,
-LONG count
-)
+alloc_tds(PUHCI_TD_POOL_LIST pool_list, LONG count)
{
//return value is a list of tds, vert_link chain.
- LONG i;
- PUHCI_TD ptd, pnext;
+ LONG i;
+ PUHCI_TD ptd, pnext;
+
+ if (pool_list == NULL || count <= 0)
+ return NULL;
- if( pool_list == NULL || count <= 0 )
- return NULL;
+ if (count >= get_max_free_tds(pool_list))
+ return NULL;
- if( count >= get_max_free_tds( pool_list ) )
- return NULL;
+ ptd = alloc_td(pool_list);
- ptd = alloc_td( pool_list );
+ for(i = 1; i < count; i++)
+ {
+ pnext = alloc_td(pool_list);
- for( i = 1; i < count; i ++ )
- {
- pnext = alloc_td( pool_list );
-
- if( pnext )
+ if (pnext)
{
- InsertTailList( &ptd->ptde->vert_link, &pnext->ptde->vert_link );
+ InsertTailList(&ptd->ptde->vert_link, &pnext->ptde->vert_link);
}
- else
- TRAP();
- }
+ else
+ TRAP();
+ }
- uhci_dbg_print( DBGLVL_MEDIUM, ("alloc_tds(): td pool-list free_tds=0x%x, free pools=0x%x\n", \
- pool_list->free_tds,
- pool_list->free_count ) );
-
- return ptd;
+ uhci_dbg_print(DBGLVL_MEDIUM, ("alloc_tds(): td pool-list free_tds=0x%x, free pools=0x%x\n",
+ pool_list->free_tds, pool_list->free_count));
+
+ return ptd;
}
VOID
-free_tds(
-PUHCI_TD_POOL_LIST pool_list,
-PUHCI_TD ptd
-)
+free_tds(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd)
{
- PUHCI_TD ptofree;
- PLIST_ENTRY pthis;
+ PUHCI_TD ptofree;
+ PLIST_ENTRY pthis;
- if( pool_list == NULL || ptd == NULL )
- return;
+ if (pool_list == NULL || ptd == NULL)
+ return;
- while( IsListEmpty( &ptd->ptde->vert_link ) == FALSE )
- {
- pthis = RemoveHeadList( &ptd->ptde->vert_link );
- ptofree = ( ( PTD_EXTENSION)pthis )->ptd;
- free_td( pool_list, ptofree );
- }
+ while (IsListEmpty(&ptd->ptde->vert_link) == FALSE)
+ {
+ pthis = RemoveHeadList(&ptd->ptde->vert_link);
+ ptofree = ((PTD_EXTENSION) pthis)->ptd;
+ free_td(pool_list, ptofree);
+ }
- free_td( pool_list, ptd );
- return;
+ free_td(pool_list, ptd);
+ return;
}
BOOL
-can_transfer(
-PUHCI_TD_POOL_LIST pool_list,
-LONG td_count
-)
+can_transfer(PUHCI_TD_POOL_LIST pool_list, LONG td_count)
{
- if( td_count > get_max_free_tds( pool_list ) )
- return FALSE;
+ if (td_count > get_max_free_tds(pool_list))
+ return FALSE;
- return TRUE;
+ return TRUE;
}
VOID
-lock_td_pool(
-PUHCI_TD_POOL_LIST pool_list,
-BOOL at_dpc
-)
+lock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOL at_dpc)
{
- //if( !at_dpc )
- // KeAcquireSpinLock( &pool_list->pool_lock );
- //else
- // KeAcquireSpinLockAtDpcLevel( &pool_list->pool_lock );
+ //if( !at_dpc )
+ // KeAcquireSpinLock( &pool_list->pool_lock );
+ //else
+ // KeAcquireSpinLockAtDpcLevel( &pool_list->pool_lock );
}
VOID
-unlock_td_pool(
-PUHCI_TD_POOL_LIST pool_list,
-BOOL at_dpc
-)
+unlock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOL at_dpc)
{
- //if( !at_dpc )
- // KeReleaseSpinLock( &pool_list->pool_lock );
- //else
- // KeReleaseSpinLockFromDpcLevel( &pool_list->pool_lock );
+ //if( !at_dpc )
+ // KeReleaseSpinLock( &pool_list->pool_lock );
+ //else
+ // KeReleaseSpinLockFromDpcLevel( &pool_list->pool_lock );
}
-BOOL
-init_qh_pool(
-PUHCI_QH_POOL pqh_pool,
-PADAPTER_OBJECT padapter
-)
+BOOL
+init_qh_pool(PUHCI_QH_POOL pqh_pool, PADAPTER_OBJECT padapter)
{
- PQH_EXTENSION pqhe;
- LONG i;
+ PQH_EXTENSION pqhe;
+ LONG i;
- if( pqh_pool == NULL || padapter == NULL )
- return FALSE;
+ if (pqh_pool == NULL || padapter == NULL)
+ return FALSE;
pqh_pool->padapter = padapter;
-
- pqh_pool->qhe_array = (PQH_EXTENSION)usb_alloc_mem(
- NonPagedPool,
- sizeof(QH_EXTENSION) * UHCI_MAX_POOL_QHS);
-
+
+ pqh_pool->qhe_array = (PQH_EXTENSION) usb_alloc_mem(NonPagedPool,
+ sizeof(QH_EXTENSION) * UHCI_MAX_POOL_QHS);
+
if (pqh_pool->qhe_array == NULL)
return FALSE;
- pqh_pool->qh_array = \
- (PUHCI_QH)HalAllocateCommonBuffer(
- padapter,
- sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS,
- &pqh_pool->logic_addr,
- FALSE);
-
- if( pqh_pool->qh_array == NULL )
- {
- usb_free_mem( pqh_pool->qhe_array );
- pqh_pool->qhe_array = NULL;
- return FALSE;
- }
-
- pqhe = pqh_pool->qhe_array;
-
- pqh_pool->free_count = 0;
- pqh_pool->total_count = UHCI_MAX_POOL_TDS;
-
- KeInitializeSpinLock( &pqh_pool->pool_lock);
- InitializeListHead( &pqh_pool->free_que);
-
+ pqh_pool->qh_array =
+ (PUHCI_QH) HalAllocateCommonBuffer(padapter,
+ sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS, &pqh_pool->logic_addr, FALSE);
+
+ if (pqh_pool->qh_array == NULL)
+ {
+ usb_free_mem(pqh_pool->qhe_array);
+ pqh_pool->qhe_array = NULL;
+ return FALSE;
+ }
+
+ pqhe = pqh_pool->qhe_array;
+
+ pqh_pool->free_count = 0;
+ pqh_pool->total_count = UHCI_MAX_POOL_TDS;
+
+ KeInitializeSpinLock(&pqh_pool->pool_lock);
+ InitializeListHead(&pqh_pool->free_que);
+
for(i = 0; i < UHCI_MAX_POOL_QHS; i++)
{
pqh_pool->qh_array[i].pqhe = &pqhe[i];
- pqhe[i].pqh = &pqh_pool->qh_array[i];
+ pqhe[i].pqh = &pqh_pool->qh_array[i];
+
+ pqh_pool->qh_array[i].phy_addr = (pqh_pool->logic_addr.LowPart + (sizeof(UHCI_QH) * i)) | UHCI_PTR_QH;
+ //pqh_pool->qh_array[i].reserved = 0;
- pqh_pool->qh_array[i].phy_addr = ( pqh_pool->logic_addr.LowPart + ( sizeof( UHCI_QH) * i ) ) | UHCI_PTR_QH;
- //pqh_pool->qh_array[i].reserved = 0;
+ //always breadth first
+ pqhe[i].flags = UHCI_ITEM_FLAG_QH;
- //always breadth first
- pqhe[i].flags = UHCI_ITEM_FLAG_QH;
+ free_qh(pqh_pool, &pqh_pool->qh_array[i]);
- free_qh( pqh_pool, &pqh_pool->qh_array[i] );
-
}
- return TRUE;
-
+ return TRUE;
+
}
+//add qhs till pnext == NULL
BOOL
-free_qh(
-PUHCI_QH_POOL pqh_pool,
-PUHCI_QH pqh
-) //add qhs till pnext == NULL
+free_qh(PUHCI_QH_POOL pqh_pool, PUHCI_QH pqh)
{
- if( pqh_pool == NULL || pqh == NULL)
- return FALSE;
-
+ if (pqh_pool == NULL || pqh == NULL)
+ return FALSE;
+
pqh->link = pqh->element = 0;
pqh->pqhe->purb = NULL;
- InsertTailList( &pqh_pool->free_que, &pqh->pqhe->vert_link);
- pqh_pool->free_count ++;
-
- return TRUE;
+ InsertTailList(&pqh_pool->free_que, &pqh->pqhe->vert_link);
+ pqh_pool->free_count++;
+
+ return TRUE;
}
+//null if failed
PUHCI_QH
-alloc_qh(
-PUHCI_QH_POOL pqh_pool
-) //null if failed
+alloc_qh(PUHCI_QH_POOL pqh_pool)
{
- PQH_EXTENSION pqhe;
-
- if( pqh_pool == NULL )
- return FALSE;
-
- if( IsListEmpty( &pqh_pool->free_que))
- return FALSE;
-
- pqhe = ( PQH_EXTENSION )RemoveHeadList( &pqh_pool->free_que );
-
- if( pqhe )
- {
- InitializeListHead( &pqhe->hori_link );
- InitializeListHead( &pqhe->vert_link );
- return pqhe->pqh;
- }
- return NULL;
-
+ PQH_EXTENSION pqhe;
+
+ if (pqh_pool == NULL)
+ return FALSE;
+
+ if (IsListEmpty(&pqh_pool->free_que))
+ return FALSE;
+
+ pqhe = (PQH_EXTENSION) RemoveHeadList(&pqh_pool->free_que);
+
+ if (pqhe)
+ {
+ InitializeListHead(&pqhe->hori_link);
+ InitializeListHead(&pqhe->vert_link);
+ return pqhe->pqh;
+ }
+ return NULL;
+
}
BOOL
-destroy_qh_pool(
-PUHCI_QH_POOL pqh_pool
-)
+destroy_qh_pool(PUHCI_QH_POOL pqh_pool)
{
int i;
- if(pqh_pool)
+ if (pqh_pool)
{
- usb_free_mem(pqh_pool->qhe_array);
+ usb_free_mem(pqh_pool->qhe_array);
- HalFreeCommonBuffer( pqh_pool->padapter,
- sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS,
- pqh_pool->logic_addr,
- pqh_pool->qh_array,
- FALSE);
+ HalFreeCommonBuffer(pqh_pool->padapter,
+ sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS,
+ pqh_pool->logic_addr, pqh_pool->qh_array, FALSE);
- RtlZeroMemory( pqh_pool, sizeof( UHCI_QH_POOL ) );
+ RtlZeroMemory(pqh_pool, sizeof(UHCI_QH_POOL));
- }
- else
- return FALSE;
+ }
+ else
+ return FALSE;
- return TRUE;
+ return TRUE;
}
VOID
-lock_qh_pool(
-PUHCI_QH_POOL pool,
-BOOL at_dpc
-)
+lock_qh_pool(PUHCI_QH_POOL pool, BOOL at_dpc)
{
- //if( !at_dpc )
- // KeAcquireSpinLock( &pool->pool_lock );
- //else
- // KeAcquireSpinLockAtDpcLevel( &pool->pool_lock );
+ //if( !at_dpc )
+ // KeAcquireSpinLock( &pool->pool_lock );
+ //else
+ // KeAcquireSpinLockAtDpcLevel( &pool->pool_lock );
}
VOID
-unlock_qh_pool(
-PUHCI_QH_POOL pool,
-BOOL at_dpc
-)
+unlock_qh_pool(PUHCI_QH_POOL pool, BOOL at_dpc)
{
- //if( !at_dpc )
- // KeReleaseSpinLock( &pool->pool_lock );
- //else
- // KeReleaseSpinLockFromDpcLevel( &pool->pool_lock );
+ //if( !at_dpc )
+ // KeReleaseSpinLock( &pool->pool_lock );
+ //else
+ // KeReleaseSpinLockFromDpcLevel( &pool->pool_lock );
}
-
#define rh_port1_status rh_port_status[ 1 ]
#define rh_port2_status rh_port_status[ 2 ]
-extern PDEVICE_OBJECT
-ehci_probe(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-PUSB_DEV_MANAGER dev_mgr
-);
+extern PDEVICE_OBJECT ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr);
#endif
//declarations
typedef struct
{
- PUHCI_DEV uhci;
- PVOID context;
- ULONG ret;
-
+ PUHCI_DEV uhci;
+ PVOID context;
+ ULONG ret;
} SYNC_PARAM, *PSYNC_PARAM;
PDEVICE_OBJECT
-uhci_alloc(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-ULONG bus_addr,
-PUSB_DEV_MANAGER dev_mgr
-);
+uhci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr);
-BOOL
-uhci_init_schedule(
-PUHCI_DEV uhci,
-PADAPTER_OBJECT padapter
-);
+BOOL uhci_init_schedule(PUHCI_DEV uhci, PADAPTER_OBJECT padapter);
-BOOL
-uhci_release(
-PDEVICE_OBJECT pdev
-);
+BOOL uhci_release(PDEVICE_OBJECT pdev);
-static VOID
-uhci_stop(
-PUHCI_DEV uhci
-);
+static VOID uhci_stop(PUHCI_DEV uhci);
-BOOL
-uhci_destroy_schedule(
-PUHCI_DEV uhci
-);
+BOOL uhci_destroy_schedule(PUHCI_DEV uhci);
-BOOLEAN
-uhci_sync_insert_urb_schedule(
-PVOID context
-);
+BOOLEAN uhci_sync_insert_urb_schedule(PVOID context);
-VOID
-uhci_init_hcd_interface(
-PUHCI_DEV uhci
-);
+VOID uhci_init_hcd_interface(PUHCI_DEV uhci);
-NTSTATUS
-uhci_rh_submit_urb(
-PUSB_DEV rh,
-PURB purb
-);
+NTSTATUS uhci_rh_submit_urb(PUSB_DEV rh, PURB purb);
-NTSTATUS
-uhci_dispatch_irp(
-IN PDEVICE_OBJECT DeviceObject,
-IN PIRP irp
-);
-
-extern VOID
-rh_timer_svc_reset_port_completion(
-PUSB_DEV dev,
-PVOID context
-);
-
-extern VOID
-rh_timer_svc_int_completion(
-PUSB_DEV dev,
-PVOID context
-);
-
-ULONG debug_level = DBGLVL_MAXIMUM;
-PDRIVER_OBJECT usb_driver_obj = NULL;
-extern USB_DEV_MANAGER g_dev_mgr;
+NTSTATUS uhci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp);
+
+extern VOID rh_timer_svc_reset_port_completion(PUSB_DEV dev, PVOID context);
+
+extern VOID rh_timer_svc_int_completion(PUSB_DEV dev, PVOID context);
+
+ULONG debug_level = DBGLVL_MAXIMUM;
+PDRIVER_OBJECT usb_driver_obj = NULL;
+extern USB_DEV_MANAGER g_dev_mgr;
//pending endpoint pool funcs
VOID
-uhci_wait_ms(
-PUHCI_DEV uhci,
-LONG ms
-)
+uhci_wait_ms(PUHCI_DEV uhci, LONG ms)
{
LARGE_INTEGER lms;
- if( ms <= 0 )
- return;
+ if (ms <= 0)
+ return;
lms.QuadPart = -10 * ms;
- KeSetTimer( &uhci->reset_timer, lms, NULL );
+ KeSetTimer(&uhci->reset_timer, lms, NULL);
- KeWaitForSingleObject(
- &uhci->reset_timer,
- Executive,
- KernelMode,
- FALSE,
- NULL );
+ KeWaitForSingleObject(&uhci->reset_timer, Executive, KernelMode, FALSE, NULL);
- return;
+ return;
}
BOOL
-init_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-)
+init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
{
- int i;
- if( pool == NULL )
- return FALSE;
+ int i;
+ if (pool == NULL)
+ return FALSE;
- pool->pending_endp_array = usb_alloc_mem( NonPagedPool, sizeof( UHCI_PENDING_ENDP ) * UHCI_MAX_PENDING_ENDPS );
- InitializeListHead( &pool->free_que );
- pool->free_count = 0;
- pool->total_count = UHCI_MAX_PENDING_ENDPS;
- KeInitializeSpinLock( &pool->pool_lock );
+ pool->pending_endp_array =
+ usb_alloc_mem(NonPagedPool, sizeof(UHCI_PENDING_ENDP) * UHCI_MAX_PENDING_ENDPS);
+ InitializeListHead(&pool->free_que);
+ pool->free_count = 0;
+ pool->total_count = UHCI_MAX_PENDING_ENDPS;
+ KeInitializeSpinLock(&pool->pool_lock);
- for( i = 0; i < MAX_TIMER_SVCS; i++ )
- {
- free_pending_endp( pool, &pool->pending_endp_array[i] );
- }
+ for(i = 0; i < MAX_TIMER_SVCS; i++)
+ {
+ free_pending_endp(pool, &pool->pending_endp_array[i]);
+ }
- return TRUE;
+ return TRUE;
}
BOOL
-free_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-PUHCI_PENDING_ENDP pending_endp
-)
+free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp)
{
- if( pool == NULL || pending_endp == NULL )
- {
- return FALSE;
- }
-
- RtlZeroMemory( pending_endp, sizeof( UHCI_PENDING_ENDP ) );
- InsertTailList( &pool->free_que, (PLIST_ENTRY) &pending_endp->endp_link );
- pool->free_count++;
-
- return TRUE;
+ if (pool == NULL || pending_endp == NULL)
+ {
+ return FALSE;
+ }
+
+ RtlZeroMemory(pending_endp, sizeof(UHCI_PENDING_ENDP));
+ InsertTailList(&pool->free_que, (PLIST_ENTRY) & pending_endp->endp_link);
+ pool->free_count++;
+
+ return TRUE;
}
PUHCI_PENDING_ENDP
-alloc_pending_endp(
-PUHCI_PENDING_ENDP_POOL pool,
-LONG count)
+alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count)
{
- PUHCI_PENDING_ENDP new;
- if( pool == NULL || count != 1 )
- return NULL;
+ PUHCI_PENDING_ENDP new;
+ if (pool == NULL || count != 1)
+ return NULL;
- if( pool->free_count <= 0 )
- return NULL;
+ if (pool->free_count <= 0)
+ return NULL;
- new = ( PUHCI_PENDING_ENDP )RemoveHeadList( &pool->free_que );
- pool->free_count --;
- return new;
+ new = (PUHCI_PENDING_ENDP) RemoveHeadList(&pool->free_que);
+ pool->free_count--;
+ return new;
}
BOOL
-destroy_pending_endp_pool(
-PUHCI_PENDING_ENDP_POOL pool
-)
+destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
{
- if( pool == NULL )
- return FALSE;
+ if (pool == NULL)
+ return FALSE;
- InitializeListHead( &pool->free_que );
- pool->free_count = pool->total_count = 0;
- usb_free_mem( pool->pending_endp_array );
- pool->pending_endp_array = NULL;
+ InitializeListHead(&pool->free_que);
+ pool->free_count = pool->total_count = 0;
+ usb_free_mem(pool->pending_endp_array);
+ pool->pending_endp_array = NULL;
- return TRUE;
+ return TRUE;
}
//end of pending endpoint pool funcs
static void
-uhci_fill_td(
-PUHCI_TD td,
-ULONG status,
-ULONG info,
-ULONG buffer)
+uhci_fill_td(PUHCI_TD td, ULONG status, ULONG info, ULONG buffer)
{
- td->status = status;
- td->info = info;
- td->buffer = buffer;
+ td->status = status;
+ td->info = info;
+ td->buffer = buffer;
}
BOOL
-uhci_insert_td_fl(
-PUHCI_TD prev_td,
-PUHCI_TD ptd
-)
+uhci_insert_td_fl(PUHCI_TD prev_td, PUHCI_TD ptd)
{
- ULONG temp;
- PLIST_ENTRY temp_entry;
+ ULONG temp;
+ PLIST_ENTRY temp_entry;
- if( prev_td == NULL || ptd == NULL )
- return FALSE;
+ if (prev_td == NULL || ptd == NULL)
+ return FALSE;
- temp_entry = &prev_td->ptde->hori_link;
+ temp_entry = &prev_td->ptde->hori_link;
- ptd->link = ( struct_ptr( temp_entry, TD_EXTENSION, hori_link ) )->ptd->phy_addr;
- prev_td->link = ptd->phy_addr;
+ ptd->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr;
+ prev_td->link = ptd->phy_addr;
- InsertHeadList( &prev_td->ptde->hori_link, &ptd->ptde->hori_link );
- return TRUE;
+ InsertHeadList(&prev_td->ptde->hori_link, &ptd->ptde->hori_link);
+ return TRUE;
}
BOOL
-uhci_remove_td_fl(
-PUHCI_TD ptd
-)
+uhci_remove_td_fl(PUHCI_TD ptd)
{
- PUHCI_TD prev_td;
+ PUHCI_TD prev_td;
- if( ptd == NULL )
- return FALSE;
+ if (ptd == NULL)
+ return FALSE;
- prev_td = ( struct_ptr( ptd->ptde->hori_link.Blink, TD_EXTENSION, hori_link ) )->ptd;
- prev_td->link = ptd->link;
- ptd->link = UHCI_PTR_TERM;
+ prev_td = (struct_ptr(ptd->ptde->hori_link.Blink, TD_EXTENSION, hori_link))->ptd;
+ prev_td->link = ptd->link;
+ ptd->link = UHCI_PTR_TERM;
- RemoveEntryList( &ptd->ptde->hori_link );
+ RemoveEntryList(&ptd->ptde->hori_link);
- return FALSE;
+ return FALSE;
}
BOOL
-uhci_insert_qh_fl(
-PVOID prev_item,
-PUHCI_QH pqh
-)
+uhci_insert_qh_fl(PVOID prev_item, PUHCI_QH pqh)
{
- //only horizontal link allowed
- PUHCI_QH pprev_qh;
- PUHCI_TD pprev_td;
- ULONG temp;
- PLIST_ENTRY temp_entry;
-
- if( prev_item == NULL || pqh == NULL )
- return FALSE;
-
- if( ( ( (PUHCI_TD)prev_item )->ptde->flags & UHCI_ITEM_FLAG_TYPE )
- == UHCI_ITEM_FLAG_QH )
- {
- pprev_qh = (PUHCI_QH)prev_item;
- temp_entry = pprev_qh->pqhe->hori_link.Flink;
- pqh->link = ( struct_ptr( temp_entry, TD_EXTENSION, hori_link ) )->ptd->phy_addr;
- pprev_qh->link = pqh->phy_addr;
-
- InsertHeadList( &pprev_qh->pqhe->hori_link, &pqh->pqhe->hori_link );
- }
- else
- {
- pprev_td = ( (PUHCI_TD)prev_item );
-
- temp_entry = pprev_td->ptde->hori_link.Flink;
- pprev_td->link = pqh->phy_addr;
- pqh->link = ( struct_ptr( temp_entry, TD_EXTENSION, hori_link ) )->ptd->phy_addr;
-
- InsertHeadList( &pprev_td->ptde->hori_link, &pqh->pqhe->hori_link );
- }
-
- return FALSE;
+ //only horizontal link allowed
+ PUHCI_QH pprev_qh;
+ PUHCI_TD pprev_td;
+ ULONG temp;
+ PLIST_ENTRY temp_entry;
+
+ if (prev_item == NULL || pqh == NULL)
+ return FALSE;
+
+ if ((((PUHCI_TD) prev_item)->ptde->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH)
+ {
+ pprev_qh = (PUHCI_QH) prev_item;
+ temp_entry = pprev_qh->pqhe->hori_link.Flink;
+ pqh->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr;
+ pprev_qh->link = pqh->phy_addr;
+
+ InsertHeadList(&pprev_qh->pqhe->hori_link, &pqh->pqhe->hori_link);
+ }
+ else
+ {
+ pprev_td = ((PUHCI_TD) prev_item);
+
+ temp_entry = pprev_td->ptde->hori_link.Flink;
+ pprev_td->link = pqh->phy_addr;
+ pqh->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr;
+
+ InsertHeadList(&pprev_td->ptde->hori_link, &pqh->pqhe->hori_link);
+ }
+
+ return FALSE;
}
BOOL
-uhci_remove_qh_fl(
-PUHCI_QH pqh
-)
+uhci_remove_qh_fl(PUHCI_QH pqh)
{
- PVOID prev_item;
- PUHCI_QH pprevqh;
- PUHCI_TD pprevtd;
+ PVOID prev_item;
+ PUHCI_QH pprevqh;
+ PUHCI_TD pprevtd;
- if( pqh == NULL )
- return FALSE;
+ if (pqh == NULL)
+ return FALSE;
- prev_item = ( struct_ptr( pqh->pqhe->hori_link.Blink, TD_EXTENSION, hori_link ) )->ptd;
+ prev_item = (struct_ptr(pqh->pqhe->hori_link.Blink, TD_EXTENSION, hori_link))->ptd;
- if( ( ( ( PUHCI_TD )prev_item )->ptde->flags & UHCI_ITEM_FLAG_TYPE )
- == UHCI_ITEM_FLAG_QH )
- {
- pprevqh = (PUHCI_QH)prev_item;
- pprevqh->link = pqh->link;
- }
- else
- {
- pprevtd = ( (PUHCI_TD)prev_item );
- pprevtd->link = pqh->link;
- }
+ if ((((PUHCI_TD) prev_item)->ptde->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH)
+ {
+ pprevqh = (PUHCI_QH) prev_item;
+ pprevqh->link = pqh->link;
+ }
+ else
+ {
+ pprevtd = ((PUHCI_TD) prev_item);
+ pprevtd->link = pqh->link;
+ }
- RemoveEntryList( &pqh->pqhe->hori_link );
+ RemoveEntryList(&pqh->pqhe->hori_link);
- pqh->link = UHCI_PTR_TERM;
- pqh->pqhe->hori_link.Flink = pqh->pqhe->hori_link.Blink = NULL;
+ pqh->link = UHCI_PTR_TERM;
+ pqh->pqhe->hori_link.Flink = pqh->pqhe->hori_link.Blink = NULL;
- return TRUE;
+ return TRUE;
}
BOOL
-uhci_init_frame_list(
-PUHCI_DEV uhci,
-PADAPTER_OBJECT padapter
-)
+uhci_init_frame_list(PUHCI_DEV uhci, PADAPTER_OBJECT padapter)
{
- int i;
- if( uhci == NULL || padapter == NULL )
- return FALSE;
+ int i;
+ if (uhci == NULL || padapter == NULL)
+ return FALSE;
//note: frame_list_lock will be connected to interrupt
- KeInitializeSpinLock( &uhci->frame_list_lock );
-
- uhci->io_buf = \
- HalAllocateCommonBuffer(
- padapter,
- 4096,
- &uhci->io_buf_logic_addr,
- FALSE);
-
- if( uhci->io_buf == NULL )
- return FALSE;
-
- uhci->frame_list = \
- HalAllocateCommonBuffer(
- padapter,
- sizeof(ULONG) * UHCI_MAX_FRAMES,
- &uhci->frame_list_logic_addr,
- FALSE);
-
- if( uhci->frame_list == NULL )
- return FALSE;
-
- RtlZeroMemory( uhci->frame_list,
- sizeof( ULONG ) * UHCI_MAX_FRAMES );
-
- uhci->frame_list_cpu = usb_alloc_mem(
- NonPagedPool,
- sizeof( FRAME_LIST_CPU_ENTRY ) * UHCI_MAX_FRAMES );
-
- if( uhci->frame_list_cpu == NULL )
- return FALSE;
-
- for( i = 0; i < UHCI_MAX_FRAMES; i++ )
- InitializeListHead( &uhci->frame_list_cpu[ i ].td_link );
-
- uhci->frame_bw = usb_alloc_mem( NonPagedPool,
- sizeof( LONG ) * UHCI_MAX_FRAMES );
-
- if( uhci->frame_bw == NULL )
- return FALSE;
-
- for( i = 0; i < UHCI_MAX_FRAMES; i++ )
- {
- uhci->frame_bw[ i ] = FRAME_TIME_MAX_USECS_ALLOC;
- }
- uhci->fsbr_cnt = 0;
-
- return TRUE;
+ KeInitializeSpinLock(&uhci->frame_list_lock);
+
+ uhci->io_buf = HalAllocateCommonBuffer(padapter, 4096, &uhci->io_buf_logic_addr, FALSE);
+
+ if (uhci->io_buf == NULL)
+ return FALSE;
+
+ uhci->frame_list =
+ HalAllocateCommonBuffer(padapter,
+ sizeof(ULONG) * UHCI_MAX_FRAMES, &uhci->frame_list_logic_addr, FALSE);
+
+ if (uhci->frame_list == NULL)
+ return FALSE;
+
+ RtlZeroMemory(uhci->frame_list, sizeof(ULONG) * UHCI_MAX_FRAMES);
+
+ uhci->frame_list_cpu = usb_alloc_mem(NonPagedPool, sizeof(FRAME_LIST_CPU_ENTRY) * UHCI_MAX_FRAMES);
+
+ if (uhci->frame_list_cpu == NULL)
+ return FALSE;
+
+ for(i = 0; i < UHCI_MAX_FRAMES; i++)
+ InitializeListHead(&uhci->frame_list_cpu[i].td_link);
+
+ uhci->frame_bw = usb_alloc_mem(NonPagedPool, sizeof(LONG) * UHCI_MAX_FRAMES);
+
+ if (uhci->frame_bw == NULL)
+ return FALSE;
+
+ for(i = 0; i < UHCI_MAX_FRAMES; i++)
+ {
+ uhci->frame_bw[i] = FRAME_TIME_MAX_USECS_ALLOC;
+ }
+ uhci->fsbr_cnt = 0;
+
+ return TRUE;
}
BOOL
-uhci_destroy_frame_list(
-PUHCI_DEV uhci
-)
+uhci_destroy_frame_list(PUHCI_DEV uhci)
{
+ if (uhci == NULL)
+ return FALSE;
- if( uhci == NULL )
- return FALSE;
+ if (uhci->frame_list)
+ HalFreeCommonBuffer(uhci->pdev_ext->padapter,
+ sizeof(ULONG) * UHCI_MAX_FRAMES,
+ uhci->frame_list_logic_addr, uhci->frame_list, FALSE);
- if( uhci->frame_list )
- HalFreeCommonBuffer(
- uhci->pdev_ext->padapter,
- sizeof(ULONG) * UHCI_MAX_FRAMES,
- uhci->frame_list_logic_addr,
- uhci->frame_list,
- FALSE );
-
- uhci->frame_list = NULL;
- uhci->frame_list_logic_addr.LowPart = 0;
+ uhci->frame_list = NULL;
+ uhci->frame_list_logic_addr.LowPart = 0;
uhci->frame_list_logic_addr.HighPart = 0;
- if( uhci->frame_list_cpu )
- usb_free_mem( uhci->frame_list_cpu );
+ if (uhci->frame_list_cpu)
+ usb_free_mem(uhci->frame_list_cpu);
- uhci->frame_list_cpu = NULL;
+ uhci->frame_list_cpu = NULL;
- if( uhci->frame_bw )
- usb_free_mem( uhci->frame_bw );
+ if (uhci->frame_bw)
+ usb_free_mem(uhci->frame_bw);
- uhci->frame_bw = NULL;
+ uhci->frame_bw = NULL;
- return TRUE;
+ return TRUE;
}
PDEVICE_OBJECT
-uhci_create_device(
-PDRIVER_OBJECT drvr_obj,
-PUSB_DEV_MANAGER dev_mgr
-)
+uhci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr)
{
- NTSTATUS status;
- PDEVICE_OBJECT pdev;
- PDEVICE_EXTENSION pdev_ext;
-
- UNICODE_STRING dev_name;
- UNICODE_STRING symb_name;
-
- STRING string, another_string;
- CHAR str_dev_name[ 64 ], str_symb_name[ 64 ];
- UCHAR hcd_id;
-
- if( drvr_obj == NULL )
- return NULL;
-
- ASSERT( dev_mgr != NULL );
-
- //note: hcd count wont increment till the hcd is registered in dev_mgr
- sprintf( str_dev_name, "%s%d", UHCI_DEVICE_NAME, dev_mgr->hcd_count );
- sprintf( str_symb_name, "%s%d", DOS_DEVICE_NAME, dev_mgr->hcd_count );
-
- RtlInitString( &string, str_dev_name );
- RtlAnsiStringToUnicodeString( &dev_name, &string, TRUE );
-
- pdev = NULL;
- status = IoCreateDevice(
- drvr_obj,
- sizeof( DEVICE_EXTENSION ) + sizeof( UHCI_DEV ),
- &dev_name,
- FILE_UHCI_DEV_TYPE,
- 0,
- FALSE,
- &pdev);
-
- if( status != STATUS_SUCCESS || pdev == NULL )
- {
- RtlFreeUnicodeString( &dev_name );
- return NULL;
- }
-
- pdev_ext = pdev->DeviceExtension;
- RtlZeroMemory( pdev_ext,
- sizeof( DEVICE_EXTENSION )
- + sizeof( UHCI_DEV) );
-
- pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD;
- pdev_ext->dev_ext_hdr.dispatch = uhci_dispatch_irp;
- pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio
- pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
-
- pdev_ext->pdev_obj = pdev;
- pdev_ext->pdrvr_obj = drvr_obj;
-
- pdev_ext->uhci = ( PUHCI_DEV ) &( pdev_ext[ 1 ] );
-
- RtlInitString( &another_string, str_symb_name );
- RtlAnsiStringToUnicodeString( &symb_name, &another_string, TRUE );
-
- IoCreateSymbolicLink( &symb_name, &dev_name );
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, uhci=0x%x, dev_mgr=0x%x\n", \
- pdev,\
- pdev_ext,\
- pdev_ext->uhci, \
- dev_mgr ) );
-
- RtlFreeUnicodeString( &dev_name );
- RtlFreeUnicodeString( &symb_name );
-
- //register with dev_mgr though it is not initilized
- uhci_init_hcd_interface( pdev_ext->uhci );
- hcd_id = dev_mgr_register_hcd( dev_mgr, &pdev_ext->uhci->hcd_interf );
-
- pdev_ext->uhci->hcd_interf.hcd_set_id( &pdev_ext->uhci->hcd_interf, hcd_id );
- pdev_ext->uhci->hcd_interf.hcd_set_dev_mgr( &pdev_ext->uhci->hcd_interf, dev_mgr );
- return pdev;
+ NTSTATUS status;
+ PDEVICE_OBJECT pdev;
+ PDEVICE_EXTENSION pdev_ext;
+
+ UNICODE_STRING dev_name;
+ UNICODE_STRING symb_name;
+
+ STRING string, another_string;
+ CHAR str_dev_name[64], str_symb_name[64];
+ UCHAR hcd_id;
+
+ if (drvr_obj == NULL)
+ return NULL;
+
+ ASSERT(dev_mgr != NULL);
+
+ //note: hcd count wont increment till the hcd is registered in dev_mgr
+ sprintf(str_dev_name, "%s%d", UHCI_DEVICE_NAME, dev_mgr->hcd_count);
+ sprintf(str_symb_name, "%s%d", DOS_DEVICE_NAME, dev_mgr->hcd_count);
+
+ RtlInitString(&string, str_dev_name);
+ RtlAnsiStringToUnicodeString(&dev_name, &string, TRUE);
+
+ pdev = NULL;
+ status = IoCreateDevice(drvr_obj,
+ sizeof(DEVICE_EXTENSION) + sizeof(UHCI_DEV),
+ &dev_name, FILE_UHCI_DEV_TYPE, 0, FALSE, &pdev);
+
+ if (status != STATUS_SUCCESS || pdev == NULL)
+ {
+ RtlFreeUnicodeString(&dev_name);
+ return NULL;
+ }
+
+ pdev_ext = pdev->DeviceExtension;
+ RtlZeroMemory(pdev_ext, sizeof(DEVICE_EXTENSION) + sizeof(UHCI_DEV));
+
+ pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD;
+ pdev_ext->dev_ext_hdr.dispatch = uhci_dispatch_irp;
+ pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio
+ pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
+
+ pdev_ext->pdev_obj = pdev;
+ pdev_ext->pdrvr_obj = drvr_obj;
+
+ pdev_ext->uhci = (PUHCI_DEV) & (pdev_ext[1]);
+
+ RtlInitString(&another_string, str_symb_name);
+ RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE);
+
+ IoCreateSymbolicLink(&symb_name, &dev_name);
+
+ uhci_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, uhci=0x%x, dev_mgr=0x%x\n", pdev,
+ pdev_ext, pdev_ext->uhci, dev_mgr));
+
+ RtlFreeUnicodeString(&dev_name);
+ RtlFreeUnicodeString(&symb_name);
+
+ //register with dev_mgr though it is not initilized
+ uhci_init_hcd_interface(pdev_ext->uhci);
+ hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->uhci->hcd_interf);
+
+ pdev_ext->uhci->hcd_interf.hcd_set_id(&pdev_ext->uhci->hcd_interf, hcd_id);
+ pdev_ext->uhci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->uhci->hcd_interf, dev_mgr);
+ return pdev;
}
BOOL
-uhci_delete_device(
-PDEVICE_OBJECT pdev
-)
+uhci_delete_device(PDEVICE_OBJECT pdev)
{
- STRING string;
- UNICODE_STRING symb_name;
- PDEVICE_EXTENSION pdev_ext;
- CHAR str_symb_name[ 64 ];
-
-
- if( pdev == NULL )
- return FALSE;
-
- pdev_ext = pdev->DeviceExtension;
-
- sprintf( str_symb_name,
- "%s%d",
- DOS_DEVICE_NAME,
- pdev_ext->uhci->hcd_interf.hcd_get_id( &pdev_ext->uhci->hcd_interf ) );
- RtlInitString( &string, str_symb_name );
- RtlAnsiStringToUnicodeString( &symb_name, &string, TRUE );
- IoDeleteSymbolicLink( &symb_name );
- RtlFreeUnicodeString( &symb_name );
-
- if( pdev_ext->res_list )
- ExFreePool( pdev_ext->res_list ); // not allocated by usb_alloc_mem
-
- IoDeleteDevice( pdev );
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_delete_device(): device deleted\n" ) );
- return TRUE;
+ STRING string;
+ UNICODE_STRING symb_name;
+ PDEVICE_EXTENSION pdev_ext;
+ CHAR str_symb_name[64];
+
+
+ if (pdev == NULL)
+ return FALSE;
+
+ pdev_ext = pdev->DeviceExtension;
+
+ sprintf(str_symb_name,
+ "%s%d", DOS_DEVICE_NAME, pdev_ext->uhci->hcd_interf.hcd_get_id(&pdev_ext->uhci->hcd_interf));
+ RtlInitString(&string, str_symb_name);
+ RtlAnsiStringToUnicodeString(&symb_name, &string, TRUE);
+ IoDeleteSymbolicLink(&symb_name);
+ RtlFreeUnicodeString(&symb_name);
+
+ if (pdev_ext->res_list)
+ ExFreePool(pdev_ext->res_list); // not allocated by usb_alloc_mem
+
+ IoDeleteDevice(pdev);
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_delete_device(): device deleted\n"));
+ return TRUE;
}
+// we can not use endp here for it is within the dev scope, and
+// we can not acquire the dev-lock, fortunately we saved some
+// info in urb->pipe in uhci_internal_submit_XXX.
BOOLEAN
-uhci_isr(
-PKINTERRUPT interrupt,
-PVOID context
-)
- // we can not use endp here for it is within the dev scope, and
- // we can not acquire the dev-lock, fortunately we saved some
- // info in urb->pipe in uhci_internal_submit_XXX.
+uhci_isr(PKINTERRUPT interrupt, PVOID context)
+{
+ PUHCI_DEV uhci;
+ USHORT status;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+
+ /*
+ * Read the interrupt status, and write it back to clear the
+ * interrupt cause
+ */
+ uhci = (PUHCI_DEV) context;
+ if (uhci == NULL)
+ return FALSE;
+
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS));
+ if (!status) /* shared interrupt, not mine */
+ return FALSE;
+
+ if (status != 1)
+ {
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): current uhci status=0x%x\n", status));
+ }
+ else
+ {
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): congratulations, no error occurs\n"));
+ }
-{
+ /* clear it */
+ WRITE_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS), status);
+
+ if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD))
+ {
+ if (status & USBSTS_HSE)
+ {
+ DbgPrint("uhci_isr(): host system error, PCI problems?\n");
+ //for( ; ; );
+ }
+ if (status & USBSTS_HCPE)
+ {
+ DbgPrint("uhci_isr(): host controller process error. something bad happened\n");
+ //for( ; ; );
+ //for( ; ; );
+ }
+ if ((status & USBSTS_HCH)) //&& !uhci->is_suspended
+ {
+ DbgPrint("uhci_isr(): host controller halted. very bad\n");
+ /* FIXME: Reset the controller, fix the offending TD */
+ }
+ }
+
+ // don't no how to handle it yet
+ //if (status & USBSTS_RD)
+ //{
+ //uhci_wakeup(uhci);
+ //}*/
- PUHCI_DEV uhci;
- USHORT status;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
-
-
- /*
- * Read the interrupt status, and write it back to clear the
- * interrupt cause
- */
- uhci = ( PUHCI_DEV )context;
- if( uhci == NULL )
- return FALSE;
-
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBSTS ) );
- if (!status) /* shared interrupt, not mine */
- return FALSE;
-
- if( status != 1 )
- {
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_isr(): current uhci status=0x%x\n", status ) );
- }
- else
- {
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_isr(): congratulations, no error occurs\n" ) );
- }
-
- /* clear it*/
- WRITE_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBSTS ), status );
-
- if ( status & ~( USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD ) )
- {
- if ( status & USBSTS_HSE )
- {
- DbgPrint( "uhci_isr(): host system error, PCI problems?\n");
- //for( ; ; );
- }
- if ( status & USBSTS_HCPE )
- {
- DbgPrint( "uhci_isr(): host controller process error. something bad happened\n");
- //for( ; ; );
- //for( ; ; );
- }
- if ( ( status & USBSTS_HCH ) ) //&& !uhci->is_suspended
- {
- DbgPrint( "uhci_isr(): host controller halted. very bad\n");
- /* FIXME: Reset the controller, fix the offending TD */
- }
- }
-
- // don't no how to handle it yet
- //if (status & USBSTS_RD)
- //{
- //uhci_wakeup(uhci);
- //}*/
-
- //let's remove those force-cancel urbs from the schedule first
- ListFirst( &uhci->urb_list, pthis );
- while( pthis )
- {
- purb = ( PURB )pthis;
- if( purb->flags & URB_FLAG_FORCE_CANCEL )
- {
- uhci_remove_urb_from_schedule( uhci, purb );
- }
- ListNext( &uhci->urb_list, pthis, pnext );
- pthis = pnext;
- }
-
- //clear the interrupt if the urb is force canceled
- uhci->skel_term_td->status &= ~TD_CTRL_IOC;
-
- //next we need to find if anything fininshed
- ListFirst( &uhci->urb_list, pthis );
- while( pthis )
- {
- purb = ( PURB )pthis;
- if( purb->flags & URB_FLAG_IN_SCHEDULE )
- {
- if( uhci_is_xfer_finished( purb ) )
- uhci_remove_urb_from_schedule( uhci, purb );
- }
- ListNext( &uhci->urb_list, pthis, pnext );
- pthis = pnext;
- }
-
- KeInsertQueueDpc( &uhci->pdev_ext->uhci_dpc, uhci, 0 );
- return TRUE;
+ //let's remove those force-cancel urbs from the schedule first
+ ListFirst(&uhci->urb_list, pthis);
+ while (pthis)
+ {
+ purb = (PURB) pthis;
+ if (purb->flags & URB_FLAG_FORCE_CANCEL)
+ {
+ uhci_remove_urb_from_schedule(uhci, purb);
+ }
+ ListNext(&uhci->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ //clear the interrupt if the urb is force canceled
+ uhci->skel_term_td->status &= ~TD_CTRL_IOC;
+
+ //next we need to find if anything fininshed
+ ListFirst(&uhci->urb_list, pthis);
+ while (pthis)
+ {
+ purb = (PURB) pthis;
+ if (purb->flags & URB_FLAG_IN_SCHEDULE)
+ {
+ if (uhci_is_xfer_finished(purb))
+ uhci_remove_urb_from_schedule(uhci, purb);
+ }
+ ListNext(&uhci->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ KeInsertQueueDpc(&uhci->pdev_ext->uhci_dpc, uhci, 0);
+ return TRUE;
}
BOOLEAN
-uhci_cal_cpu_freq(
-PVOID context
-)
+uhci_cal_cpu_freq(PVOID context)
{
- usb_cal_cpu_freq();
- return TRUE;
+ usb_cal_cpu_freq();
+ return TRUE;
}
PDEVICE_OBJECT
-uhci_probe(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-PUSB_DEV_MANAGER dev_mgr
-)
-{
- LONG bus, i, j, ret;
- PCI_SLOT_NUMBER slot_num;
- PPCI_COMMON_CONFIG pci_config;
- PDEVICE_OBJECT pdev;
- BYTE buffer[ sizeof( PCI_COMMON_CONFIG ) ];
- LONG count;
- PDEVICE_EXTENSION pdev_ext;
-
- slot_num.u.AsULONG = 0;
- pci_config = ( PPCI_COMMON_CONFIG ) buffer;
- count = 0;
- pdev = NULL;
-
- //scan the bus to find uhci controller
- for( bus = 0; bus < 2; bus++ ) /*enum only bus0 and bus1*/
- {
- for( i = 0; i < PCI_MAX_DEVICES; i++ )
- {
- slot_num.u.bits.DeviceNumber = i;
- for( j = 0; j < PCI_MAX_FUNCTIONS; j++ )
- {
- slot_num.u.bits.FunctionNumber = j;
-
- ret = HalGetBusData(
- PCIConfiguration,
- bus,
- slot_num.u.AsULONG,
- pci_config,
- PCI_COMMON_HDR_LENGTH );
-
- if( ret == 0 ) /*no this bus*/
- break;
-
- if( ret == 2 ) /*no device on the slot*/
- break;
-
- if( pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03 )
- {
- // well, we find our usb host controller, create device
+uhci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr)
+{
+ LONG bus, i, j, ret;
+ PCI_SLOT_NUMBER slot_num;
+ PPCI_COMMON_CONFIG pci_config;
+ PDEVICE_OBJECT pdev;
+ BYTE buffer[sizeof(PCI_COMMON_CONFIG)];
+ LONG count;
+ PDEVICE_EXTENSION pdev_ext;
+
+ slot_num.u.AsULONG = 0;
+ pci_config = (PPCI_COMMON_CONFIG) buffer;
+ count = 0;
+ pdev = NULL;
+
+ //scan the bus to find uhci controller
+ for(bus = 0; bus < 2; bus++) /*enum only bus0 and bus1 */
+ {
+ for(i = 0; i < PCI_MAX_DEVICES; i++)
+ {
+ slot_num.u.bits.DeviceNumber = i;
+ for(j = 0; j < PCI_MAX_FUNCTIONS; j++)
+ {
+ slot_num.u.bits.FunctionNumber = j;
+
+ ret = HalGetBusData(PCIConfiguration,
+ bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH);
+
+ if (ret == 0) /*no this bus */
+ break;
+
+ if (ret == 2) /*no device on the slot */
+ break;
+
+ if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03)
+ {
+ // well, we find our usb host controller, create device
#ifdef _MULTI_UHCI
- {
- pdev = uhci_alloc( drvr_obj, reg_path, ( ( bus << 8 ) | ( i << 3 ) | j ), dev_mgr );
- count++;
- if( !pdev )
- return NULL;
- }
+ {
+ pdev = uhci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr);
+ count++;
+ if (!pdev)
+ return NULL;
+ }
#else
- pdev = uhci_alloc( drvr_obj, reg_path, ( ( bus << 8 ) | ( i << 3 ) | j ), dev_mgr );
- if( pdev )
- goto LBL_LOOPOUT;
+ pdev = uhci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr);
+ if (pdev)
+ goto LBL_LOOPOUT;
#endif
- }
- }
- if( ret == 0 )
- break;
- }
- }
+ }
+ }
+ if (ret == 0)
+ break;
+ }
+ }
+
LBL_LOOPOUT:
- if( pdev )
- {
- pdev_ext = pdev->DeviceExtension;
- if( pdev_ext )
- {
- // acquire higher irql to eliminate pre-empty
- KeSynchronizeExecution( pdev_ext->uhci_int, uhci_cal_cpu_freq, NULL );
- }
- }
- return NULL;
+ if (pdev)
+ {
+ pdev_ext = pdev->DeviceExtension;
+ if (pdev_ext)
+ {
+ // acquire higher irql to eliminate pre-empty
+ KeSynchronizeExecution(pdev_ext->uhci_int, uhci_cal_cpu_freq, NULL);
+ }
+ }
+ return NULL;
}
PDEVICE_OBJECT
-uhci_alloc(
-PDRIVER_OBJECT drvr_obj,
-PUNICODE_STRING reg_path,
-ULONG bus_addr,
-PUSB_DEV_MANAGER dev_mgr
-)
+uhci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr)
{
+ LONG frd_num, prd_num;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PDEVICE_OBJECT pdev;
+ PDEVICE_EXTENSION pdev_ext;
+ ULONG vector, addr_space;
+ LONG bus;
+ KIRQL irql;
+ KAFFINITY affinity;
+ UCHAR hcd_id;
+
+ DEVICE_DESCRIPTION dev_desc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd;
+ PCI_SLOT_NUMBER slot_num;
+ NTSTATUS status;
+
+
+ pdev = uhci_create_device(drvr_obj, dev_mgr);
+ pdev_ext = pdev->DeviceExtension;
+
+ pdev_ext->pci_addr = bus_addr;
+ bus = (bus_addr >> 8);
+
+ slot_num.u.AsULONG = 0;
+ slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3);
+ slot_num.u.bits.FunctionNumber = (bus_addr & 0x07);
+
+ if (pdev == NULL)
+ return pdev;
+
+ //now create adapter object
+ RtlZeroMemory(&dev_desc, sizeof(dev_desc));
+
+ dev_desc.Version = DEVICE_DESCRIPTION_VERSION;
+ dev_desc.Master = TRUE;
+ dev_desc.ScatterGather = TRUE;
+ dev_desc.Dma32BitAddresses = TRUE;
+ dev_desc.BusNumber = bus;
+ dev_desc.InterfaceType = PCIBus;
+ dev_desc.MaximumLength =
+ UHCI_MAX_POOL_TDS * sizeof(UHCI_TD) * UHCI_MAX_TD_POOLS
+ + sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS + sizeof(ULONG) * UHCI_MAX_FRAMES;
+
+ pdev_ext->map_regs = 2; // UHCI_MAX_TD_POOLS +
+ //+ BYTES_TO_PAGES( ( UHCI_MAX_POOL_TDS * 64 ) * UHCI_MAX_TD_POOLS ) ;
+
+ pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs);
- LONG frd_num, prd_num;
- UCHAR buffer[ PCI_COMMON_HDR_LENGTH ];
- PDEVICE_OBJECT pdev;
- PDEVICE_EXTENSION pdev_ext;
- ULONG vector, addr_space;
- LONG bus;
- KIRQL irql;
- KAFFINITY affinity;
- UCHAR hcd_id;
-
- DEVICE_DESCRIPTION dev_desc;
- CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd;
- PCI_SLOT_NUMBER slot_num;
- NTSTATUS status;
-
-
- pdev = uhci_create_device( drvr_obj, dev_mgr );
- pdev_ext = pdev->DeviceExtension;
-
- pdev_ext->pci_addr = bus_addr;
- bus = ( bus_addr >> 8 );
-
- slot_num.u.AsULONG = 0;
- slot_num.u.bits.DeviceNumber = ( ( bus_addr & 0xff ) >> 3 );
- slot_num.u.bits.FunctionNumber = ( bus_addr & 0x07 );
-
- if( pdev == NULL )
- return pdev;
-
- //now create adapter object
- RtlZeroMemory( &dev_desc, sizeof( dev_desc ) );
-
- dev_desc.Version = DEVICE_DESCRIPTION_VERSION;
- dev_desc.Master = TRUE;
- dev_desc.ScatterGather = TRUE;
- dev_desc.Dma32BitAddresses = TRUE;
- dev_desc.BusNumber = bus;
- dev_desc.InterfaceType = PCIBus;
- dev_desc.MaximumLength = \
- UHCI_MAX_POOL_TDS * sizeof( UHCI_TD ) * UHCI_MAX_TD_POOLS \
- + sizeof( UHCI_QH ) * UHCI_MAX_POOL_QHS \
- + sizeof( ULONG ) * UHCI_MAX_FRAMES;
-
- pdev_ext->map_regs = 2; // UHCI_MAX_TD_POOLS +
- //+ BYTES_TO_PAGES( ( UHCI_MAX_POOL_TDS * 64 ) * UHCI_MAX_TD_POOLS ) ;
-
- pdev_ext->padapter = HalGetAdapter( &dev_desc, &pdev_ext->map_regs);
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_alloc(): padapter=0x%x\n", pdev_ext->padapter ) );
- if( pdev_ext->padapter == NULL )
- {
- //fatal error
- uhci_delete_device( pdev );
- return NULL;
- }
-
- DbgPrint("uhci_alloc(): reg_path=0x%x, \n \
- uhci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
- uhci_alloc(): slot_num=0x%x, &res_list=0x%x \n", \
- ( DWORD )reg_path, \
- ( DWORD )PCIBus, \
- ( DWORD )bus, \
- ( DWORD )bus_addr,\
- ( DWORD )slot_num.u.AsULONG, \
- ( DWORD )&pdev_ext->res_list );
-
- //let's allocate resources for this device
- DbgPrint( "uhci_alloc(): about to assign slot res\n" );
- if( ( status = HalAssignSlotResources(
- reg_path,
- NULL, //no class name yet
- drvr_obj,
- NULL, //no support of another uhci controller
- PCIBus,
- bus,
- slot_num.u.AsULONG,
- &pdev_ext->res_list ) )
- != STATUS_SUCCESS )
- {
- DbgPrint( "uhci_alloc(): error assign slot res, 0x%x\n", status );
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- uhci_delete_device( pdev );
- return NULL;
- }
-
- //parse the resource list
- for( frd_num = 0; frd_num < ( LONG )pdev_ext->res_list->Count; frd_num ++ )
- {
- for( prd_num = 0; prd_num < ( LONG )pdev_ext->res_list->List[ frd_num ].PartialResourceList.Count; prd_num ++ )
- {
- pprd = &pdev_ext->res_list->List[ frd_num ].PartialResourceList.PartialDescriptors[ prd_num ];
- if( pprd->Type == CmResourceTypePort )
- {
- RtlCopyMemory( &pdev_ext->res_port, &pprd->u.Port, sizeof( pprd->u.Port ) );
-
- }
- else if( pprd->Type == CmResourceTypeInterrupt )
- {
- RtlCopyMemory( &pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof( pprd->u.Interrupt ) );
- }
- }
- }
-
- //for port, translate them to system address
- addr_space = 1;
- if( HalTranslateBusAddress(
- PCIBus,
- bus,
- pdev_ext->res_port.Start,
- &addr_space, //io space
- &pdev_ext->uhci->uhci_reg_base
- )
- != ( BOOLEAN )TRUE )
- {
- DbgPrint( "uhci_alloc(): error, can not translate bus address\n" );
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- uhci_delete_device( pdev );
- return NULL;
- }
-
- DbgPrint( "uhci_alloc(): address space=0x%x\n, reg_base=0x%x\n", \
- addr_space, pdev_ext->uhci->uhci_reg_base.u.LowPart );
-
- if( addr_space == 0 )
- {
- //port has been mapped to memory space
- pdev_ext->uhci->port_mapped = TRUE;
- pdev_ext->uhci->port_base = ( PBYTE )MmMapIoSpace(
- pdev_ext->uhci->uhci_reg_base,
- pdev_ext->res_port.Length,
- FALSE );
-
- //fatal error can not map the registers
- if( pdev_ext->uhci->port_base == NULL )
- {
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- uhci_delete_device( pdev );
- return NULL;
- }
- }
- else
- {
- //io space
- pdev_ext->uhci->port_mapped = FALSE;
- pdev_ext->uhci->port_base = ( PBYTE )pdev_ext->uhci->uhci_reg_base.LowPart;
- }
-
- //before we connect the interrupt, we have to init uhci
- pdev_ext->uhci->fsbr_cnt = 0;
- pdev_ext->uhci->pdev_ext = pdev_ext;
-
- if( uhci_init_schedule( pdev_ext->uhci, pdev_ext->padapter ) == FALSE )
- {
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
- uhci_delete_device( pdev );
- return NULL;
- }
-
- InitializeListHead( &pdev_ext->uhci->urb_list );
- KeInitializeSpinLock( &pdev_ext->uhci->pending_endp_list_lock );
- InitializeListHead( &pdev_ext->uhci->pending_endp_list );
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_alloc(): pending_endp_list=0x%x\n", \
- &pdev_ext->uhci->pending_endp_list ) );
-
- init_pending_endp_pool( &pdev_ext->uhci->pending_endp_pool );
- KeInitializeTimer( &pdev_ext->uhci->reset_timer );
-
- vector = HalGetInterruptVector(
- PCIBus,
- bus,
- pdev_ext->res_interrupt.level,
- pdev_ext->res_interrupt.vector,
- &irql,
- &affinity);
-
- //connect the interrupt
- DbgPrint( "uhci_alloc(): the int=0x%x\n", vector );
- if( IoConnectInterrupt(
- &pdev_ext->uhci_int,
- uhci_isr,
- pdev_ext->uhci,
- NULL, //&pdev_ext->uhci->frame_list_lock,
- vector,
- irql,
- irql,
- LevelSensitive,
- TRUE, //share the vector
- affinity,
- FALSE ) //No float save
- != STATUS_SUCCESS )
- {
- uhci_release( pdev );
- return NULL;
- }
-
- KeInitializeDpc( &pdev_ext->uhci_dpc,
- uhci_dpc_callback,
- ( PVOID )pdev_ext->uhci );
-
- return pdev;
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): padapter=0x%x\n", pdev_ext->padapter));
+ if (pdev_ext->padapter == NULL)
+ {
+ //fatal error
+ uhci_delete_device(pdev);
+ return NULL;
+ }
+
+ DbgPrint("uhci_alloc(): reg_path=0x%x, \n \
+ uhci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
+ uhci_alloc(): slot_num=0x%x, &res_list=0x%x \n", (DWORD) reg_path, (DWORD) PCIBus, (DWORD) bus,
+ (DWORD) bus_addr, (DWORD) slot_num.u.AsULONG, (DWORD) & pdev_ext->res_list);
+
+ //let's allocate resources for this device
+ DbgPrint("uhci_alloc(): about to assign slot res\n");
+ if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet
+ drvr_obj, NULL, //no support of another uhci controller
+ PCIBus,
+ bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS)
+ {
+ DbgPrint("uhci_alloc(): error assign slot res, 0x%x\n", status);
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ uhci_delete_device(pdev);
+ return NULL;
+ }
+
+ //parse the resource list
+ for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++)
+ {
+ for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count;
+ prd_num++)
+ {
+ pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num];
+ if (pprd->Type == CmResourceTypePort)
+ {
+ RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port));
+ }
+ else if (pprd->Type == CmResourceTypeInterrupt)
+ {
+ RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt));
+ }
+ }
+ }
+
+ //for port, translate them to system address
+ addr_space = 1;
+ if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space
+ &pdev_ext->uhci->uhci_reg_base) != (BOOLEAN) TRUE)
+ {
+ DbgPrint("uhci_alloc(): error, can not translate bus address\n");
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ uhci_delete_device(pdev);
+ return NULL;
+ }
+
+ DbgPrint("uhci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
+ addr_space, pdev_ext->uhci->uhci_reg_base.u.LowPart);
+
+ if (addr_space == 0)
+ {
+ //port has been mapped to memory space
+ pdev_ext->uhci->port_mapped = TRUE;
+ pdev_ext->uhci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->uhci->uhci_reg_base,
+ pdev_ext->res_port.Length, FALSE);
+
+ //fatal error can not map the registers
+ if (pdev_ext->uhci->port_base == NULL)
+ {
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ uhci_delete_device(pdev);
+ return NULL;
+ }
+ }
+ else
+ {
+ //io space
+ pdev_ext->uhci->port_mapped = FALSE;
+ pdev_ext->uhci->port_base = (PBYTE) pdev_ext->uhci->uhci_reg_base.LowPart;
+ }
+
+ //before we connect the interrupt, we have to init uhci
+ pdev_ext->uhci->fsbr_cnt = 0;
+ pdev_ext->uhci->pdev_ext = pdev_ext;
+
+ if (uhci_init_schedule(pdev_ext->uhci, pdev_ext->padapter) == FALSE)
+ {
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
+ uhci_delete_device(pdev);
+ return NULL;
+ }
+
+ InitializeListHead(&pdev_ext->uhci->urb_list);
+ KeInitializeSpinLock(&pdev_ext->uhci->pending_endp_list_lock);
+ InitializeListHead(&pdev_ext->uhci->pending_endp_list);
+
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): pending_endp_list=0x%x\n",
+ &pdev_ext->uhci->pending_endp_list));
+
+ init_pending_endp_pool(&pdev_ext->uhci->pending_endp_pool);
+ KeInitializeTimer(&pdev_ext->uhci->reset_timer);
+
+ vector = HalGetInterruptVector(PCIBus,
+ bus,
+ pdev_ext->res_interrupt.level,
+ pdev_ext->res_interrupt.vector,
+ &irql,
+ &affinity);
+
+ //connect the interrupt
+ DbgPrint("uhci_alloc(): the int=0x%x\n", vector);
+ if (IoConnectInterrupt(&pdev_ext->uhci_int,
+ uhci_isr,
+ pdev_ext->uhci,
+ NULL, //&pdev_ext->uhci->frame_list_lock,
+ vector,
+ irql,
+ irql,
+ LevelSensitive,
+ TRUE, //share the vector
+ affinity,
+ FALSE) //No float save
+ != STATUS_SUCCESS)
+ {
+ uhci_release(pdev);
+ return NULL;
+ }
+
+ KeInitializeDpc(&pdev_ext->uhci_dpc, uhci_dpc_callback, (PVOID) pdev_ext->uhci);
+
+ return pdev;
}
BOOL
-uhci_release(
-PDEVICE_OBJECT pdev
-)
+uhci_release(PDEVICE_OBJECT pdev)
{
- PDEVICE_EXTENSION pdev_ext;
- PUHCI_DEV uhci;
- KIRQL disp_level;
- KIRQL old_level;
+ PDEVICE_EXTENSION pdev_ext;
+ PUHCI_DEV uhci;
+ KIRQL disp_level;
+ KIRQL old_level;
- if( pdev == NULL )
- return FALSE;
+ if (pdev == NULL)
+ return FALSE;
- pdev_ext = pdev->DeviceExtension;
+ pdev_ext = pdev->DeviceExtension;
- if( pdev_ext == NULL )
- return FALSE;
+ if (pdev_ext == NULL)
+ return FALSE;
- uhci = pdev_ext->uhci;
- if( uhci == NULL )
- return FALSE;
+ uhci = pdev_ext->uhci;
+ if (uhci == NULL)
+ return FALSE;
- uhci_stop( uhci );
- //pdev_ext->uhci->conn_count = 0;
- pdev_ext->uhci->fsbr_cnt = 0;
+ uhci_stop(uhci);
+ //pdev_ext->uhci->conn_count = 0;
+ pdev_ext->uhci->fsbr_cnt = 0;
- if( pdev_ext->uhci_int )
+ if (pdev_ext->uhci_int)
{
- IoDisconnectInterrupt( pdev_ext->uhci_int );
- pdev_ext->uhci_int = NULL;
+ IoDisconnectInterrupt(pdev_ext->uhci_int);
+ pdev_ext->uhci_int = NULL;
}
- else
- TRAP();
- destroy_pending_endp_pool( &pdev_ext->uhci->pending_endp_pool );
- //pdev_ext->uhci->pending_endp_pool = NULL;
+ else
+ TRAP();
+ destroy_pending_endp_pool(&pdev_ext->uhci->pending_endp_pool);
+ //pdev_ext->uhci->pending_endp_pool = NULL;
- uhci_destroy_schedule( uhci );
+ uhci_destroy_schedule(uhci);
- release_adapter( pdev_ext->padapter );
- pdev_ext->padapter = NULL;
+ release_adapter(pdev_ext->padapter);
+ pdev_ext->padapter = NULL;
- uhci_delete_device( pdev );
+ uhci_delete_device(pdev);
- return FALSE;
+ return FALSE;
}
-BOOL
-uhci_start(
-PHCD hcd
-)
-{
// send cmds to start the uhc
// shamelessly copied from linux's uhci.c
- PUHCI_DEV uhci;
- PBYTE io_addr;
- int timeout = 10000;
-
- uhci = uhci_from_hcd( hcd );
- io_addr = uhci->port_base;
-
- /*
- * Reset the HC - this will force us to get a
- * new notification of any already connected
- * ports due to the virtual disconnect that it
- * implies.
- */
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), USBCMD_HCRESET );
- while ( READ_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ) ) & USBCMD_HCRESET )
- {
- if (!--timeout)
- {
- break;
- }
- }
-
- /* Turn on all interrupts */
- WRITE_PORT_USHORT(
- ( PUSHORT )( io_addr + USBINTR ),
- USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP
- );
-
- /* Start at frame 0 */
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBFRNUM ), 0 );
- WRITE_PORT_ULONG( ( PULONG )( io_addr + USBFLBASEADD ), uhci->frame_list_logic_addr.LowPart );
-
- /* Run and mark it configured with a 64-byte max packet */
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), USBCMD_RS | USBCMD_CF | USBCMD_MAXP );
-
- DbgPrint( "uhci_start(): current uhci status=0x%x\n", uhci_status( uhci ) );
-
- return TRUE;
+BOOL
+uhci_start(PHCD hcd)
+{
+ PUHCI_DEV uhci;
+ PBYTE io_addr;
+ int timeout = 10000;
+
+ uhci = uhci_from_hcd(hcd);
+ io_addr = uhci->port_base;
+
+ /*
+ * Reset the HC - this will force us to get a
+ * new notification of any already connected
+ * ports due to the virtual disconnect that it
+ * implies.
+ */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_HCRESET);
+ while (READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD)) & USBCMD_HCRESET)
+ {
+ if (!--timeout)
+ {
+ break;
+ }
+ }
+
+ /* Turn on all interrupts */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBINTR),
+ USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
+
+ /* Start at frame 0 */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBFRNUM), 0);
+ WRITE_PORT_ULONG((PULONG) (io_addr + USBFLBASEADD), uhci->frame_list_logic_addr.LowPart);
+
+ /* Run and mark it configured with a 64-byte max packet */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
+
+ DbgPrint("uhci_start(): current uhci status=0x%x\n", uhci_status(uhci));
+
+ return TRUE;
}
VOID
-uhci_stop(
-PUHCI_DEV uhci
-)
+uhci_stop(PUHCI_DEV uhci)
{
- PBYTE io_addr = uhci->port_base;
- // turn off all the interrupt
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBINTR ), 0 );
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), 0 );
+ PBYTE io_addr = uhci->port_base;
+ // turn off all the interrupt
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBINTR), 0);
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0);
}
static VOID
-uhci_reset(
-PUHCI_DEV uhci
-)
+uhci_reset(PUHCI_DEV uhci)
{
- PUSB_DEV_MANAGER dev_mgr;
- PLIST_ENTRY pthis, pnext;
- PBYTE io_addr = uhci->port_base;
-
- uhci_stop( uhci );
- /* Global reset for 50ms */
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), USBCMD_GRESET );
- //uhci_wait_ms( uhci, 50 );
- usb_wait_ms_dpc( 50 );
-
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), 0 );
- //uhci_wait_ms( uhci, 10 );
- usb_wait_ms_dpc( 10 );
+ PUSB_DEV_MANAGER dev_mgr;
+ PLIST_ENTRY pthis, pnext;
+ PBYTE io_addr = uhci->port_base;
+
+ uhci_stop(uhci);
+ /* Global reset for 50ms */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_GRESET);
+ //uhci_wait_ms( uhci, 50 );
+ usb_wait_ms_dpc(50);
+
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0);
+ //uhci_wait_ms( uhci, 10 );
+ usb_wait_ms_dpc(10);
}
static VOID
-uhci_suspend(
-PUHCI_DEV uhci
-)
+uhci_suspend(PUHCI_DEV uhci)
{
- PBYTE io_addr = uhci->port_base;
+ PBYTE io_addr = uhci->port_base;
- //uhci->is_suspended = 1;
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), USBCMD_EGSM );
+ //uhci->is_suspended = 1;
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_EGSM);
}
static VOID
-uhci_wakeup(
-PUHCI_DEV uhci
-)
+uhci_wakeup(PUHCI_DEV uhci)
{
- PBYTE io_addr;
- unsigned int status;
+ PBYTE io_addr;
+ unsigned int status;
+
+ io_addr = uhci->port_base;
- io_addr = uhci->port_base;
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0);
- WRITE_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ), 0 );
-
- /* wait for EOP to be sent */
- status = READ_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ) );
- while (status & USBCMD_FGR)
- status = READ_PORT_USHORT( ( PUSHORT )( io_addr + USBCMD ) );
+ /* wait for EOP to be sent */
+ status = READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD));
+ while (status & USBCMD_FGR)
+ status = READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD));
- //uhci->is_suspended = 0;
+ //uhci->is_suspended = 0;
- /* Run and mark it configured with a 64-byte max packet */
- WRITE_PORT_USHORT(
- ( PUSHORT )( io_addr + USBCMD ),
- USBCMD_RS | USBCMD_CF | USBCMD_MAXP
- );
+ /* Run and mark it configured with a 64-byte max packet */
+ WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
}
BOOL
-uhci_init_schedule(
-PUHCI_DEV uhci,
-PADAPTER_OBJECT padapter
-)
+uhci_init_schedule(PUHCI_DEV uhci, PADAPTER_OBJECT padapter)
{
- int i, irq;
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_init_schedule(): entering..., uhci=0x%x\n", uhci ) );
- if( uhci == NULL || padapter == NULL )
- return FALSE;
-
- if( init_td_pool_list( &uhci->td_pool, padapter ) == FALSE )
- {
- return FALSE;
- }
- if( init_qh_pool( &uhci->qh_pool, padapter ) == FALSE )
- {
- return FALSE;
- }
-
- //since uhci is not started we can freely access all resources.
- for( i = 0; i < UHCI_MAX_SKELTDS; i++ )
- {
- uhci->skel_td[ i ] = alloc_td( &uhci->td_pool );
- uhci_fill_td(uhci->skel_td[ i ],
- 0,
- ( UHCI_NULL_DATA_SIZE << 21 )
- | ( 0x7f << 8 ) | USB_PID_IN,
- 0 );
-
- if( i > 0 )
- {
- uhci->skel_td[ i ]->link = uhci->skel_td[ i - 1 ]->phy_addr;
- }
- }
-
- /*for( i = UHCI_MAX_SKELTDS - 3; i >= 0; i-- )
- {
- InsertTailList( &uhci->skel_int256_td->ptde->hori_link,
- &uhci->skel_td[ i ]->ptde->hori_link );
- }*/
-
- for( i = 0; i < UHCI_MAX_SKELQHS; i++ )
- {
- uhci->skel_qh[ i ] = alloc_qh( &uhci->qh_pool );
- if( i > 0 )
- {
- uhci->skel_qh[ i - 1 ]->link = uhci->skel_qh[ i ]->phy_addr;
- }
-
- uhci->skel_qh[ i ]->element = UHCI_PTR_TERM;
- }
-
- uhci->skel_int1_td->link = uhci->skel_ls_control_qh->phy_addr;
-
- uhci_fill_td( uhci->skel_term_td, 0, ( UHCI_NULL_DATA_SIZE << 21 ) | ( 0x7f << 8 ) | USB_PID_IN, 0 );
- uhci->skel_term_td->link = uhci->skel_term_td->phy_addr;
-
- uhci->skel_term_qh->link = UHCI_PTR_TERM;
- uhci->skel_term_qh->element = uhci->skel_term_td->phy_addr;
-
- InsertTailList( &uhci->skel_term_qh->pqhe->vert_link, &uhci->skel_term_td->ptde->vert_link );
-
- /*for( i = 0; i < UHCI_MAX_SKELQHS; i++ )
- {
- InsertTailList( &uhci->skel_int256_td->ptde->hori_link,
- &uhci->skel_qh[ i ]->pqhe->hori_link );
- }*/
-
- if( uhci_init_frame_list( uhci, uhci->pdev_ext->padapter ) == FALSE )
- uhci_destroy_frame_list( uhci );
-
- //well all have been chained, now scatter the int tds to frame-list
+ int i, irq;
+
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_init_schedule(): entering..., uhci=0x%x\n", uhci));
+ if (uhci == NULL || padapter == NULL)
+ return FALSE;
+
+ if (init_td_pool_list(&uhci->td_pool, padapter) == FALSE)
+ {
+ return FALSE;
+ }
+ if (init_qh_pool(&uhci->qh_pool, padapter) == FALSE)
+ {
+ return FALSE;
+ }
+
+ //since uhci is not started we can freely access all resources.
+ for(i = 0; i < UHCI_MAX_SKELTDS; i++)
+ {
+ uhci->skel_td[i] = alloc_td(&uhci->td_pool);
+ uhci_fill_td(uhci->skel_td[i], 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+
+ if (i > 0)
+ {
+ uhci->skel_td[i]->link = uhci->skel_td[i - 1]->phy_addr;
+ }
+ }
+
+ /*for( i = UHCI_MAX_SKELTDS - 3; i >= 0; i-- )
+ {
+ InsertTailList( &uhci->skel_int256_td->ptde->hori_link,
+ &uhci->skel_td[ i ]->ptde->hori_link );
+ } */
+
+ for(i = 0; i < UHCI_MAX_SKELQHS; i++)
+ {
+ uhci->skel_qh[i] = alloc_qh(&uhci->qh_pool);
+ if (i > 0)
+ {
+ uhci->skel_qh[i - 1]->link = uhci->skel_qh[i]->phy_addr;
+ }
+
+ uhci->skel_qh[i]->element = UHCI_PTR_TERM;
+ }
+
+ uhci->skel_int1_td->link = uhci->skel_ls_control_qh->phy_addr;
+
+ uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+ uhci->skel_term_td->link = uhci->skel_term_td->phy_addr;
+
+ uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ uhci->skel_term_qh->element = uhci->skel_term_td->phy_addr;
+
+ InsertTailList(&uhci->skel_term_qh->pqhe->vert_link, &uhci->skel_term_td->ptde->vert_link);
+
+ /*for( i = 0; i < UHCI_MAX_SKELQHS; i++ )
+ {
+ InsertTailList( &uhci->skel_int256_td->ptde->hori_link,
+ &uhci->skel_qh[ i ]->pqhe->hori_link );
+ } */
+
+ if (uhci_init_frame_list(uhci, uhci->pdev_ext->padapter) == FALSE)
+ uhci_destroy_frame_list(uhci);
+
+ //well all have been chained, now scatter the int tds to frame-list
//shamelessly pasted from linux's uhci.c :-)
- for( i = 0; i < UHCI_MAX_FRAMES; i++ )
- {
- irq = 0;
- if (i & 1)
- {
- irq++;
- if (i & 2)
- {
- irq++;
- if (i & 4)
- {
- irq++;
- if (i & 8)
- {
- irq++;
- if (i & 16)
- {
- irq++;
- if (i & 32)
- {
- irq++;
- if (i & 64)
- irq++;
- }
- }
- }
- }
- }
- }
-
- /* Only place we don't use the frame list routines */
- uhci->frame_list[ i ] = uhci->skel_td[ irq ]->phy_addr;
- }
- return TRUE;
+ for(i = 0; i < UHCI_MAX_FRAMES; i++)
+ {
+ irq = 0;
+ if (i & 1)
+ {
+ irq++;
+ if (i & 2)
+ {
+ irq++;
+ if (i & 4)
+ {
+ irq++;
+ if (i & 8)
+ {
+ irq++;
+ if (i & 16)
+ {
+ irq++;
+ if (i & 32)
+ {
+ irq++;
+ if (i & 64)
+ irq++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Only place we don't use the frame list routines */
+ uhci->frame_list[i] = uhci->skel_td[irq]->phy_addr;
+ }
+ return TRUE;
}
BOOL
-uhci_destroy_schedule(
-PUHCI_DEV uhci
-)
+uhci_destroy_schedule(PUHCI_DEV uhci)
{
- BOOL ret;
+ BOOL ret;
- ret = uhci_destroy_frame_list( uhci );
- ret = destroy_qh_pool( &uhci->qh_pool );
- ret = destroy_td_pool_list( &uhci->td_pool );
+ ret = uhci_destroy_frame_list(uhci);
+ ret = destroy_qh_pool(&uhci->qh_pool);
+ ret = destroy_td_pool_list(&uhci->td_pool);
- return ret;
+ return ret;
}
static VOID
-uhci_cancel_pending_endp_urb(
-IN PVOID Parameter
-)
+uhci_cancel_pending_endp_urb(IN PVOID Parameter)
{
- PLIST_ENTRY abort_list;
- PUSB_DEV pdev;
- PURB purb;
- USE_IRQL;
-
- abort_list = ( PLIST_ENTRY )Parameter;
-
- if( abort_list == NULL )
- return;
-
- while( IsListEmpty( abort_list ) == FALSE )
- {
- //these devs are protected by urb's ref-count
- purb = ( PURB )RemoveHeadList( abort_list );
- pdev = purb->pdev;
- // purb->status is set when they are added to abort_list
-
- uhci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, FALSE );
- pdev->ref_count--;
- unlock_dev( pdev, FALSE );
- }
- usb_free_mem( abort_list );
- return;
+ PLIST_ENTRY abort_list;
+ PUSB_DEV pdev;
+ PURB purb;
+ USE_IRQL;
+
+ abort_list = (PLIST_ENTRY) Parameter;
+
+ if (abort_list == NULL)
+ return;
+
+ while (IsListEmpty(abort_list) == FALSE)
+ {
+ //these devs are protected by urb's ref-count
+ purb = (PURB) RemoveHeadList(abort_list);
+ pdev = purb->pdev;
+ // purb->status is set when they are added to abort_list
+
+ uhci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, FALSE);
+ pdev->ref_count--;
+ unlock_dev(pdev, FALSE);
+ }
+ usb_free_mem(abort_list);
+ return;
}
static BOOL
-uhci_process_pending_endp(
-PUHCI_DEV uhci
-)
+uhci_process_pending_endp(PUHCI_DEV uhci)
{
- PUSB_DEV pdev;
- LIST_ENTRY temp_list, abort_list;
- PLIST_ENTRY pthis;
- PURB purb;
- PUSB_ENDPOINT pendp;
- BOOL can_submit;
- PWORK_QUEUE_ITEM pwork_item;
- PLIST_ENTRY cancel_list;
- USE_IRQL;
-
- if( uhci == NULL )
- return FALSE;
-
- InitializeListHead( &temp_list );
- InitializeListHead( &abort_list );
-
- purb = NULL;
- uhci_dbg_print( DBGLVL_MEDIUM, ("uhci_process_pending_endp(): entering..., uhci=0x%x\n", uhci ) );
-
- lock_pending_endp_list( &uhci->pending_endp_list_lock );
- while( IsListEmpty( &uhci->pending_endp_list ) == FALSE )
- {
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_process_pending_endp(): pending_endp_list=0x%x\n", \
- &uhci->pending_endp_list ) );
-
- pthis = RemoveHeadList( &uhci->pending_endp_list );
- pendp = ( ( PUHCI_PENDING_ENDP )pthis )->pendp;
- pdev = dev_from_endp( pendp );
-
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- free_pending_endp( &uhci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- //delegate to uhci_remove_device for remiving the urb queue on the endpoint
- continue;
- }
-
- if( endp_state( pendp ) == USB_ENDP_FLAG_STALL )
- {
- while( IsListEmpty( &pendp->urb_list ) == FALSE )
- {
- purb = ( PURB )RemoveHeadList( &pendp->urb_list );
- purb->status = USB_STATUS_ENDPOINT_HALTED;
- InsertTailList( &abort_list, ( LIST_ENTRY* )purb );
- }
- InitializeListHead( &pendp->urb_list );
- unlock_dev( pdev, TRUE );
- free_pending_endp( &uhci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- continue;
- }
-
-
- if( IsListEmpty( &pendp->urb_list ) == FALSE )
- {
- purb = ( PURB )RemoveHeadList( &pendp->urb_list );
- ASSERT( purb );
- }
- else
- {
- InitializeListHead( &pendp->urb_list );
- unlock_dev( pdev, TRUE );
- free_pending_endp( &uhci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- continue;
- }
-
- // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
- switch( endp_type( pendp ) )
- {
- case USB_ENDPOINT_XFER_BULK:
- {
+ PUSB_DEV pdev;
+ LIST_ENTRY temp_list, abort_list;
+ PLIST_ENTRY pthis;
+ PURB purb;
+ PUSB_ENDPOINT pendp;
+ BOOL can_submit;
+ PWORK_QUEUE_ITEM pwork_item;
+ PLIST_ENTRY cancel_list;
+ USE_IRQL;
+
+ if (uhci == NULL)
+ return FALSE;
+
+ InitializeListHead(&temp_list);
+ InitializeListHead(&abort_list);
+
+ purb = NULL;
+ uhci_dbg_print(DBGLVL_MEDIUM, ("uhci_process_pending_endp(): entering..., uhci=0x%x\n", uhci));
+
+ lock_pending_endp_list(&uhci->pending_endp_list_lock);
+ while (IsListEmpty(&uhci->pending_endp_list) == FALSE)
+ {
+
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_process_pending_endp(): pending_endp_list=0x%x\n",
+ &uhci->pending_endp_list));
+
+ pthis = RemoveHeadList(&uhci->pending_endp_list);
+ pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp;
+ pdev = dev_from_endp(pendp);
+
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ //delegate to uhci_remove_device for remiving the urb queue on the endpoint
+ continue;
+ }
+
+ if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
+ {
+ while (IsListEmpty(&pendp->urb_list) == FALSE)
+ {
+ purb = (PURB) RemoveHeadList(&pendp->urb_list);
+ purb->status = USB_STATUS_ENDPOINT_HALTED;
+ InsertTailList(&abort_list, (LIST_ENTRY *) purb);
+ }
+ InitializeListHead(&pendp->urb_list);
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ continue;
+ }
+
+
+ if (IsListEmpty(&pendp->urb_list) == FALSE)
+ {
+ purb = (PURB) RemoveHeadList(&pendp->urb_list);
+ ASSERT(purb);
+ }
+ else
+ {
+ InitializeListHead(&pendp->urb_list);
+ unlock_dev(pdev, TRUE);
+ free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ continue;
+ }
+
+ // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
+ switch (endp_type(pendp))
+ {
+ case USB_ENDPOINT_XFER_BULK:
+ {
#ifdef DEMO
- can_submit = STATUS_UNSUCCESSFUL;
+ can_submit = STATUS_UNSUCCESSFUL;
#else
- can_submit = uhci_internal_submit_bulk( uhci, purb );
+ can_submit = uhci_internal_submit_bulk(uhci, purb);
#endif
- break;
- }
- case USB_ENDPOINT_XFER_CONTROL:
- {
- can_submit = uhci_internal_submit_ctrl( uhci, purb );
- break;
- }
- case USB_ENDPOINT_XFER_INT:
- {
- can_submit = uhci_internal_submit_int( uhci, purb );
- break;
- }
- case USB_ENDPOINT_XFER_ISOC:
- {
- can_submit = uhci_internal_submit_iso( uhci, purb );
- break;
- }
- }
-
- if( can_submit == STATUS_NO_MORE_ENTRIES )
- {
- //no enough bandwidth or tds
- InsertHeadList( &pendp->urb_list, ( PLIST_ENTRY )purb );
- InsertTailList( &temp_list, pthis );
- }
- else
- {
- // other error or success
- free_pending_endp(
- &uhci->pending_endp_pool,
- struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
-
- if( can_submit != STATUS_SUCCESS )
- {
- //abort these URBs
- InsertTailList( &abort_list, ( LIST_ENTRY* )purb );
- purb->status = can_submit;
- }
-
- }
- unlock_dev( pdev, TRUE );
- }
-
- if( IsListEmpty( &temp_list ) == FALSE )
- {
- //re-append them to the pending_endp_list
- ListFirst( &temp_list, pthis );
- RemoveEntryList( &temp_list );
- MergeList( &uhci->pending_endp_list, pthis );
- }
- unlock_pending_endp_list( &uhci->pending_endp_list_lock );
-
- if( IsListEmpty( &abort_list ) == FALSE )
- {
- PLIST_ENTRY pthis;
- cancel_list = ( PLIST_ENTRY )usb_alloc_mem( NonPagedPool, sizeof( WORK_QUEUE_ITEM ) + sizeof( LIST_ENTRY ) );
- ASSERT( cancel_list );
-
- ListFirst( &abort_list, pthis );
- RemoveEntryList( &abort_list );
- InsertTailList( pthis, cancel_list );
-
- pwork_item = ( PWORK_QUEUE_ITEM )&cancel_list[ 1 ];
-
- // we do not need to worry the uhci_cancel_pending_endp_urb running when the
- // driver is unloading since it will prevent the dev_mgr to quit till all the
- // reference count to the dev drop to zero.
- ExInitializeWorkItem( pwork_item, uhci_cancel_pending_endp_urb, ( PVOID )cancel_list );
- ExQueueWorkItem( pwork_item, DelayedWorkQueue );
- }
- return TRUE;
+ break;
+ }
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ can_submit = uhci_internal_submit_ctrl(uhci, purb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
+ can_submit = uhci_internal_submit_int(uhci, purb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_ISOC:
+ {
+ can_submit = uhci_internal_submit_iso(uhci, purb);
+ break;
+ }
+ }
+
+ if (can_submit == STATUS_NO_MORE_ENTRIES)
+ {
+ //no enough bandwidth or tds
+ InsertHeadList(&pendp->urb_list, (PLIST_ENTRY) purb);
+ InsertTailList(&temp_list, pthis);
+ }
+ else
+ {
+ // other error or success
+ free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+
+ if (can_submit != STATUS_SUCCESS)
+ {
+ //abort these URBs
+ InsertTailList(&abort_list, (LIST_ENTRY *) purb);
+ purb->status = can_submit;
+ }
+
+ }
+ unlock_dev(pdev, TRUE);
+ }
+
+ if (IsListEmpty(&temp_list) == FALSE)
+ {
+ //re-append them to the pending_endp_list
+ ListFirst(&temp_list, pthis);
+ RemoveEntryList(&temp_list);
+ MergeList(&uhci->pending_endp_list, pthis);
+ }
+ unlock_pending_endp_list(&uhci->pending_endp_list_lock);
+
+ if (IsListEmpty(&abort_list) == FALSE)
+ {
+ PLIST_ENTRY pthis;
+ cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY));
+ ASSERT(cancel_list);
+
+ ListFirst(&abort_list, pthis);
+ RemoveEntryList(&abort_list);
+ InsertTailList(pthis, cancel_list);
+
+ pwork_item = (PWORK_QUEUE_ITEM) & cancel_list[1];
+
+ // we do not need to worry the uhci_cancel_pending_endp_urb running when the
+ // driver is unloading since it will prevent the dev_mgr to quit till all the
+ // reference count to the dev drop to zero.
+ ExInitializeWorkItem(pwork_item, uhci_cancel_pending_endp_urb, (PVOID) cancel_list);
+ ExQueueWorkItem(pwork_item, DelayedWorkQueue);
+ }
+ return TRUE;
}
BOOL
-uhci_submit_urb(
-PUHCI_DEV uhci,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
+uhci_submit_urb(PUHCI_DEV uhci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- int i;
- PLIST_ENTRY pthis, pnext;
- PUHCI_PENDING_ENDP pending_endp;
- NTSTATUS status;
- USE_IRQL;
-
- if( uhci == NULL || pdev == NULL || pendp == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- lock_pending_endp_list( &uhci->pending_endp_list_lock );
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- goto LBL_OUT;
- }
-
- if( dev_class( pdev ) == USB_DEV_CLASS_ROOT_HUB )
- {
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &uhci->pending_endp_list_lock );
- status = uhci_rh_submit_urb( pdev, purb );
- return status;
- }
-
- if( pendp )
- purb->pendp = pendp;
- else
- purb->pendp = &pdev->default_endp;
-
- if( dev_from_endp( purb->pendp ) != pdev )
- {
- status = purb->status = STATUS_INVALID_PARAMETER;
- goto LBL_OUT;
- }
-
- if( endp_state( purb->pendp ) == USB_ENDP_FLAG_STALL )
- {
- status = purb->status = USB_STATUS_ENDPOINT_HALTED;
- goto LBL_OUT;
- }
-
- purb->pdev = pdev;
- purb->rest_bytes = purb->data_length;
-
- if( endp_type( purb->pendp ) == USB_ENDPOINT_XFER_BULK )
- purb->bytes_to_transfer =
- ( purb->data_length
- > purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER
- ? purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER
- : purb->data_length ); //multiple transfer for large data block
- else
- purb->bytes_to_transfer = purb->data_length;
-
- uhci_dbg_print( DBGLVL_MEDIUM, ( "uhci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer ) );
-
- purb->bytes_transfered = 0;
- InitializeListHead( &purb->trasac_list );
- purb->last_finished_td = &purb->trasac_list;
- purb->flags &= ~( URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL );
- purb->flags |= URB_FLAG_STATE_PENDING;
-
-
- i = IsListEmpty( &pendp->urb_list );
- InsertTailList( &pendp->urb_list, &purb->urb_link );
-
- pdev->ref_count ++; //for urb reference
-
- if( i == FALSE )
- {
- //there is urb pending, simply queue it and return
- status = purb->status = STATUS_PENDING;
- goto LBL_OUT;
- }
- else if( usb_endp_busy_count( purb->pendp )
- && endp_type( purb->pendp) != USB_ENDPOINT_XFER_ISOC )
- {
+ int i;
+ PLIST_ENTRY pthis, pnext;
+ PUHCI_PENDING_ENDP pending_endp;
+ NTSTATUS status;
+ USE_IRQL;
+
+ if (uhci == NULL || pdev == NULL || pendp == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_pending_endp_list(&uhci->pending_endp_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ goto LBL_OUT;
+ }
+
+ if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB)
+ {
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&uhci->pending_endp_list_lock);
+ status = uhci_rh_submit_urb(pdev, purb);
+ return status;
+ }
+
+ if (pendp)
+ purb->pendp = pendp;
+ else
+ purb->pendp = &pdev->default_endp;
+
+ if (dev_from_endp(purb->pendp) != pdev)
+ {
+ status = purb->status = STATUS_INVALID_PARAMETER;
+ goto LBL_OUT;
+ }
+
+ if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL)
+ {
+ status = purb->status = USB_STATUS_ENDPOINT_HALTED;
+ goto LBL_OUT;
+ }
+
+ purb->pdev = pdev;
+ purb->rest_bytes = purb->data_length;
+
+ if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK)
+ purb->bytes_to_transfer = (purb->data_length > purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER ? purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER : purb->data_length); //multiple transfer for large data block
+ else
+ purb->bytes_to_transfer = purb->data_length;
+
+ uhci_dbg_print(DBGLVL_MEDIUM, ("uhci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer));
+
+ purb->bytes_transfered = 0;
+ InitializeListHead(&purb->trasac_list);
+ purb->last_finished_td = &purb->trasac_list;
+ purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL);
+ purb->flags |= URB_FLAG_STATE_PENDING;
+
+
+ i = IsListEmpty(&pendp->urb_list);
+ InsertTailList(&pendp->urb_list, &purb->urb_link);
+
+ pdev->ref_count++; //for urb reference
+
+ if (i == FALSE)
+ {
+ //there is urb pending, simply queue it and return
+ status = purb->status = STATUS_PENDING;
+ goto LBL_OUT;
+ }
+ else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC)
+ {
+ //
+ //No urb waiting but urb overlap not allowed,
+ //so leave it in queue and return, will be scheduled
+ //later
//
- //No urb waiting but urb overlap not allowed,
- //so leave it in queue and return, will be scheduled
- //later
- //
- status = purb->status = STATUS_PENDING;
- goto LBL_OUT;
- }
-
- pending_endp = alloc_pending_endp( &uhci->pending_endp_pool, 1 );
- if( pending_endp == NULL )
- {
- //panic
- status = purb->status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT2;
- }
-
- pending_endp->pendp = purb->pendp;
- InsertTailList( &uhci->pending_endp_list, ( PLIST_ENTRY )pending_endp );
-
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &uhci->pending_endp_list_lock );
-
- uhci_process_pending_endp( uhci );
- return STATUS_PENDING;
+ status = purb->status = STATUS_PENDING;
+ goto LBL_OUT;
+ }
+
+ pending_endp = alloc_pending_endp(&uhci->pending_endp_pool, 1);
+ if (pending_endp == NULL)
+ {
+ //panic
+ status = purb->status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT2;
+ }
+
+ pending_endp->pendp = purb->pendp;
+ InsertTailList(&uhci->pending_endp_list, (PLIST_ENTRY) pending_endp);
+
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&uhci->pending_endp_list_lock);
+
+ uhci_process_pending_endp(uhci);
+ return STATUS_PENDING;
LBL_OUT2:
- pdev->ref_count --;
- RemoveEntryList( ( PLIST_ENTRY )purb );
+ pdev->ref_count--;
+ RemoveEntryList((PLIST_ENTRY) purb);
LBL_OUT:
- unlock_dev( pdev, TRUE );
- unlock_pending_endp_list( &uhci->pending_endp_list_lock );
- return status;
+ unlock_dev(pdev, TRUE);
+ unlock_pending_endp_list(&uhci->pending_endp_list_lock);
+ return status;
}
static NTSTATUS
-uhci_set_error_code(
-PURB urb,
-ULONG raw_status
-)
+uhci_set_error_code(PURB urb, ULONG raw_status)
{
-
- if( ( raw_status & TD_CTRL_ANY_ERROR ) == 0 )
- {
- //test if the urb is canceled
- if( urb->flags & URB_FLAG_FORCE_CANCEL )
- urb->status = STATUS_CANCELLED;
- else
- urb->status = STATUS_SUCCESS;
- }
-
- else if( raw_status & TD_CTRL_BABBLE )
- urb->status = USB_STATUS_DATA_OVERRUN;
-
- else if( raw_status & TD_CTRL_STALLED )
- urb->status = USB_STATUS_STALL_PID;
-
- else if( raw_status & TD_CTRL_DBUFERR )
- urb->status = USB_STATUS_BUFFER_OVERRUN;
-
- else if( raw_status & TD_CTRL_CRCTIMEO )
- urb->status = USB_STATUS_CRC;
-
- else if( raw_status & TD_CTRL_BITSTUFF )
- urb->status = USB_STATUS_BTSTUFF;
-
- else
- urb->status = STATUS_UNSUCCESSFUL;
-
- return urb->status;
+ if ((raw_status & TD_CTRL_ANY_ERROR) == 0)
+ {
+ //test if the urb is canceled
+ if (urb->flags & URB_FLAG_FORCE_CANCEL)
+ urb->status = STATUS_CANCELLED;
+ else
+ urb->status = STATUS_SUCCESS;
+ }
+
+ else if (raw_status & TD_CTRL_BABBLE)
+ urb->status = USB_STATUS_DATA_OVERRUN;
+
+ else if (raw_status & TD_CTRL_STALLED)
+ urb->status = USB_STATUS_STALL_PID;
+
+ else if (raw_status & TD_CTRL_DBUFERR)
+ urb->status = USB_STATUS_BUFFER_OVERRUN;
+
+ else if (raw_status & TD_CTRL_CRCTIMEO)
+ urb->status = USB_STATUS_CRC;
+
+ else if (raw_status & TD_CTRL_BITSTUFF)
+ urb->status = USB_STATUS_BTSTUFF;
+
+ else
+ urb->status = STATUS_UNSUCCESSFUL;
+
+ return urb->status;
}
BOOLEAN
-uhci_sync_remove_urb_finished(
-PVOID context
-)
+uhci_sync_remove_urb_finished(PVOID context)
{
- PUHCI_DEV uhci;
- PLIST_ENTRY pthis, pnext, ptemp;
- PURB purb;
- PSYNC_PARAM pparam;
-
- pparam = ( PSYNC_PARAM )context;
- uhci = pparam->uhci;
- ptemp = ( PLIST_ENTRY )pparam->context;
-
- if( uhci == NULL )
- {
- return ( UCHAR )pparam->ret = FALSE;
- }
-
- ListFirst( &uhci->urb_list, pthis );
- while( pthis )
- {
+ PUHCI_DEV uhci;
+ PLIST_ENTRY pthis, pnext, ptemp;
+ PURB purb;
+ PSYNC_PARAM pparam;
+
+ pparam = (PSYNC_PARAM) context;
+ uhci = pparam->uhci;
+ ptemp = (PLIST_ENTRY) pparam->context;
+
+ if (uhci == NULL)
+ {
+ return (UCHAR) pparam->ret = FALSE;
+ }
+
+ ListFirst(&uhci->urb_list, pthis);
+ while (pthis)
+ {
//remove urbs not in the schedule
- ListNext( &uhci->urb_list, pthis, pnext );
- purb = ( PURB )pthis;
+ ListNext(&uhci->urb_list, pthis, pnext);
+ purb = (PURB) pthis;
+
+ if ((purb->flags & URB_FLAG_IN_SCHEDULE) == 0)
+ {
+ //finished or canceled( not apply for split bulk ).
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_FINISHED;
+ RemoveEntryList(pthis);
+ InsertTailList(ptemp, pthis);
+ }
+ pthis = pnext;
+ }
+ pparam->ret = TRUE;
+ return (UCHAR) TRUE;
+}
+
+BOOLEAN
+uhci_drop_fsbr(PUHCI_DEV uhci)
+{
+ if (uhci == NULL)
+ return (UCHAR) FALSE;
+
+ uhci->fsbr_cnt--;
+
+ if (uhci->fsbr_cnt <= 0)
+ {
+ uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ uhci->fsbr_cnt = 0;
+ }
+
+ return (UCHAR) TRUE;
+}
+
+VOID
+uhci_dpc_callback(PKDPC dpc, PVOID context, PVOID sysarg1, PVOID sysarg2)
+{
+ PUHCI_DEV uhci;
+
+ LIST_HEAD temp_list;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ PQH_EXTENSION pqhe;
+ PTD_EXTENSION ptde;
+ PUHCI_PENDING_ENDP pending_endp;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+
+ BOOL finished;
+ LONG i, j;
+ ULONG uhci_status, urb_status, toggle = 0;
+
+ SYNC_PARAM sync_param;
+ USE_IRQL;
+
+ uhci = (PUHCI_DEV) context;
+ if (uhci == NULL)
+ return;
+
+ uhci_status = (ULONG) sysarg1;
+
+ InitializeListHead(&temp_list);
+
+ sync_param.uhci = uhci;
+ sync_param.context = (PVOID) & temp_list;
+
+ uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_dpc_callback(): entering..., uhci=0x%x\n", uhci));
+ //remove finished urb from uhci's urb-list
+ KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_remove_urb_finished, &sync_param);
+
+ //release resources( tds, and qhs ) the urb occupied
+ while (IsListEmpty(&temp_list) == FALSE)
+ {
+ //not in any public queue, if do not access into dev, no race
+ //condition will occur
+ purb = (PURB) RemoveHeadList(&temp_list);
+ urb_status = purb->status;
+
+ //the only place we do not use this lock on non-pending-endp-list data ops
+ KeAcquireSpinLockAtDpcLevel(&uhci->pending_endp_list_lock);
+ while (IsListEmpty(&purb->trasac_list) == FALSE)
+ {
+ pthis = RemoveHeadList(&purb->trasac_list);
+
+ if ((((PTD_EXTENSION) pthis)->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH)
+ {
+ pqhe = (PQH_EXTENSION) pthis;
+ lock_qh_pool(&uhci->qh_pool, TRUE);
+ free_qh(&uhci->qh_pool, pqhe->pqh);
+ unlock_qh_pool(&uhci->qh_pool, TRUE);
+ }
+ else
+ {
+ //must be a td chain
+ InsertHeadList(&purb->trasac_list, pthis);
+ for(i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++)
+ {
+ PUHCI_TD ptd;
+ // accumulate data transfered in tds
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ if ((ptd->status & TD_CTRL_ACTIVE) == 0 && (ptd->status & TD_CTRL_ANY_ERROR) == 0)
+ {
+ j = ptd->status & 0x7ff;
+ purb->bytes_transfered += ((j == 0x7ff) ? 0 : (j + 1));
+
+ }
+ ListNext(&purb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ if (urb_status & TD_CTRL_ANY_ERROR)
+ {
+ if (purb->last_finished_td != NULL && purb->last_finished_td != &purb->trasac_list)
+ toggle = (((PTD_EXTENSION) purb->last_finished_td)->ptd->info & (1 << 19));
+ }
+ //trick, remove trasac_list
+ ListFirst(&purb->trasac_list, pthis);
+ RemoveEntryList(&purb->trasac_list);
+ lock_td_pool(&uhci->td_pool, TRUE);
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ //termination condition
+ InitializeListHead(&purb->trasac_list);
+ purb->last_finished_td = NULL;
+ }
+ }
+
+ if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_ISOC
+ || endp_type(purb->pendp) == USB_ENDPOINT_XFER_INT)
+ uhci_claim_bandwidth(uhci, purb, FALSE); //release band-width
+
+ KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock);
+
+ uhci_set_error_code(purb, urb_status);
+
+ finished = TRUE;
+
+ //since the ref_count for the urb is not released, we can safely have one
+ //pointer to dev
+ pdev = dev_from_endp(purb->pendp);
+ pendp = purb->pendp;
+
+ if (purb->status == USB_STATUS_BABBLE_DETECTED)
+ {
+ usb_dbg_print(DBGLVL_MEDIUM,
+ ("uhci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n"));
+ uhci_reset(uhci);
+ uhci_start(&uhci->hcd_interf);
+ }
+
+ //this will let the new request in uhci_generic_urb_completion to this endp
+ //be processed rather than queued in the pending_endp_list
+ lock_dev(pdev, TRUE);
+ usb_endp_busy_count_dec(pendp);
+ unlock_dev(pdev, TRUE);
+
+ if (usb_success(purb->status) == FALSE)
+ {
+ // set error code and complete the urb and purb is invalid from this point
+ uhci_generic_urb_completion(purb, purb->context);
+ }
+ else
+ {
+ if ((purb->pipe & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+ {
+ purb->rest_bytes -= purb->bytes_transfered;
+ if (purb->rest_bytes)
+ {
+ finished = FALSE;
+ }
+ else
+ {
+ uhci_generic_urb_completion(purb, purb->context);
+ }
+ }
+ else
+ {
+ uhci_generic_urb_completion(purb, purb->context);
+ //purb is now invalid
+ }
+ }
+
+ KeAcquireSpinLockAtDpcLevel(&uhci->pending_endp_list_lock);
+ lock_dev(pdev, TRUE);
+
+ if (finished)
+ pdev->ref_count--;
+
+ if (urb_status & TD_CTRL_ANY_ERROR && endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
+ {
+ pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
+ pendp->flags |= USB_ENDP_FLAG_STALL;
+ }
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock);
+ if (finished == FALSE)
+ {
+
+ purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ uhci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, TRUE);
+ pdev->ref_count--;
+ unlock_dev(pdev, TRUE);
+ }
+ continue;
+ }
+
+ if (finished && IsListEmpty(&pendp->urb_list) == TRUE)
+ {
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock);
+ continue;
+ }
+ else if (finished == TRUE)
+ {
+ //has urb in the endp's urb-list
+ if (usb_endp_busy_count(pendp) > 0)
+ {
+ //the urbs still have chance to be sheduled but not this time
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock);
+ continue;
+ }
+ }
+
+ if (finished == FALSE)
+ {
+ //a split bulk transfer
+ purb->bytes_transfered = 0;
+ purb->bytes_to_transfer =
+ UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize
+ > purb->rest_bytes
+ ? purb->rest_bytes : UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize;
+
+ //the urb is not finished
+ purb->flags &= ~URB_FLAG_STATE_MASK;
+ purb->flags |= URB_FLAG_STATE_PENDING;
+
+ InsertHeadList(&pendp->urb_list, (PLIST_ENTRY) purb);
+ }
+
+ pending_endp = alloc_pending_endp(&uhci->pending_endp_pool, 1);
+ pending_endp->pendp = pendp;
+ InsertTailList(&uhci->pending_endp_list, &pending_endp->endp_link);
+
+ unlock_dev(pdev, TRUE);
+ KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock);
+ }
+
+ //ah...exhausted, let's find some in the pending_endp_list to rock
+ uhci_process_pending_endp(uhci);
+ return;
+}
+
+BOOL
+uhci_add_device(PUHCI_DEV uhci, PUSB_DEV dev)
+{
+ if (dev == NULL || uhci == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN
+uhci_sync_cancel_urbs_dev(PVOID context)
+{
+ //cancel all the urbs on one dev
+ PUHCI_DEV uhci;
+ PUSB_DEV pdev, dest_dev;
+ PSYNC_PARAM sync_param;
+ PLIST_ENTRY pthis, pnext;
+ LONG count;
+
+ sync_param = (PSYNC_PARAM) context;
+ dest_dev = (PUSB_DEV) sync_param->context;
+ uhci = sync_param->uhci;
+
+ if (uhci == NULL || dest_dev == NULL)
+ {
+ return (UCHAR) sync_param->ret = FALSE;
+ }
+ count = 0;
+ ListFirst(&uhci->urb_list, pthis);
+ while (pthis)
+ {
+ pdev = dev_from_endp(((PURB) pthis)->pendp);
+ if (pdev == dest_dev)
+ {
+ ((PURB) pthis)->flags |= URB_FLAG_FORCE_CANCEL;
+ }
+ ListNext(&uhci->urb_list, pthis, pnext);
+ pthis = pnext;
+ count++;
+ }
+ if (count)
+ uhci->skel_term_td->status |= TD_CTRL_IOC;
+
+ return (UCHAR) sync_param->ret = TRUE;
+}
+
+BOOL
+uhci_remove_device(PUHCI_DEV uhci, PUSB_DEV dev)
+{
+ PUHCI_PENDING_ENDP ppending_endp;
+ PLIST_ENTRY pthis, pnext;
+ PURB purb;
+ LIST_HEAD temp_list;
+ int i, j, k;
+ SYNC_PARAM sync_param;
+
+ USE_IRQL;
+
+ if (uhci == NULL || dev == NULL)
+ return FALSE;
+
+ InitializeListHead(&temp_list);
+
+ //free pending endp that has urb queued from pending endp list
+ lock_pending_endp_list(&uhci->pending_endp_list_lock);
+
+ ListFirst(&uhci->pending_endp_list, pthis);
+
+ while (pthis)
+ {
+ ppending_endp = (PUHCI_PENDING_ENDP) pthis;
+ ListNext(&uhci->pending_endp_list, pthis, pnext);
+ if (dev_from_endp(ppending_endp->pendp) == dev)
+ {
+ RemoveEntryList(pthis);
+ free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
+ }
+ pthis = pnext;
+ }
+ unlock_pending_endp_list(&uhci->pending_endp_list_lock);
+
+ //cancel all the urbs in the urb-list
+ sync_param.uhci = uhci;
+ sync_param.context = (PVOID) dev;
+
+ KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_cancel_urbs_dev, &sync_param);
+
+ //cancel all the urb in the endp's urb-list
+ k = 0;
+ lock_dev(dev, FALSE);
+ if (dev->usb_config)
+ {
+ //only for configed dev
+ for(i = 0; i < dev->usb_config->if_count; i++)
+ {
+ for(j = 0; j < dev->usb_config->interf[i].endp_count; j++)
+ {
+ ListFirst(&dev->usb_config->interf[i].endp[j].urb_list, pthis);
+ while (pthis)
+ {
+ ListNext(&dev->usb_config->interf[i].endp[j].urb_list, pthis, pnext);
+
+ RemoveEntryList(pthis);
+ InsertHeadList(&temp_list, pthis);
+ pthis = pnext;
+ k++;
+ }
+
+ }
+ }
+ }
+ ListFirst(&dev->default_endp.urb_list, pthis);
+
+ while (pthis)
+ {
+ ListNext(&dev->default_endp.urb_list, pthis, pnext);
+
+ RemoveEntryList(pthis);
+ InsertHeadList(&temp_list, pthis);
+ pthis = pnext;
+ k++;
+ }
+ unlock_dev(dev, FALSE);
+
+ if (IsListEmpty(&temp_list) == FALSE)
+ {
+ for(i = 0; i < k; i++)
+ {
+ //complete those urbs with error
+ pthis = RemoveHeadList(&temp_list);
+ purb = (PURB) pthis;
+ purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
+ {
+ uhci_generic_urb_completion(purb, purb->context);
+ }
+ }
+ }
+
+ lock_dev(dev, FALSE) dev->ref_count -= k;
+ unlock_dev(dev, FALSE);
+
+ return TRUE;
+}
+
+
+//
+// assume that the urb has its rest_bytes and bytes_to_transfer set
+// and bytes_transfered is zeroed.
+// dev_lock must be acquired outside
+// urb comes from dev's endpoint urb-list. it is already removed from
+// the endpoint urb-list.
+//
+static NTSTATUS
+uhci_internal_submit_bulk(PUHCI_DEV uhci, PURB urb)
+{
+
+ LONG max_packet_size, td_count, offset, bytes_to_transfer, data_load;
+ PBYTE start_addr;
+ PUHCI_TD ptd;
+ PUHCI_QH pqh;
+ LIST_ENTRY td_list, *pthis, *pnext;
+ BOOL old_toggle, toggle, ret;
+ UCHAR pid;
+
+ if (uhci == NULL || urb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ max_packet_size = endp_max_packet_size(urb->pendp);
+ if (urb->bytes_to_transfer == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ td_count = (urb->bytes_to_transfer + max_packet_size - 1) / max_packet_size;
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ if (can_transfer(&uhci->td_pool, td_count) == FALSE)
+ {
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ ptd = alloc_tds(&uhci->td_pool, td_count);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ if (ptd == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ InitializeListHead(&td_list);
+ InsertTailList(&ptd->ptde->vert_link, &td_list);
+
+ ListFirst(&td_list, pthis);
+ ListNext(&td_list, pthis, pnext);
+
+ start_addr = &urb->data_buffer[urb->data_length - urb->rest_bytes];
+ offset = 0;
+
+ old_toggle = toggle = urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ? TRUE : FALSE;
+ bytes_to_transfer = urb->bytes_to_transfer;
+
+ urb->pipe = ((max_packet_size - 1) << 21)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (dev_from_endp(urb->pendp)->dev_addr << 8)
+ | ((ULONG) endp_dir(urb->pendp)) | USB_ENDPOINT_XFER_BULK;
+
+ pid = (((ULONG) urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT);
+ while (pthis)
+ {
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+
+ data_load = max_packet_size < bytes_to_transfer ? max_packet_size : bytes_to_transfer;
+ ptd->purb = urb;
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT)
+ | (TD_CTRL_ACTIVE),
+ ((data_load - 1) << 21)
+ | (toggle << 19)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (dev_from_endp(urb->pendp)->dev_addr << 8)
+ | pid, MmGetPhysicalAddress(start_addr + offset).LowPart);
+
+ bytes_to_transfer -= data_load;
+ offset += data_load;
+
+ if (pnext)
+ {
+ ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr;
+ }
+ else
+ {
+ //Last one, enable ioc and short packet detect if necessary
+ ptd->link = UHCI_PTR_TERM;
+ ptd->status |= TD_CTRL_IOC;
+ if (bytes_to_transfer < max_packet_size && (pid == USB_PID_IN))
+ {
+ //ptd->status |= TD_CTRL_SPD;
+ }
+ }
+
+ pthis = pnext;
+ toggle ^= 1;
+ if (pthis)
+ ListNext(&td_list, pthis, pnext);
+
+ }
+
+ ListFirst(&td_list, pthis);
+ RemoveEntryList(&td_list);
+
+ lock_qh_pool(&uhci->qh_pool, TRUE);
+ pqh = alloc_qh(&uhci->qh_pool);
+ unlock_qh_pool(&uhci->qh_pool, TRUE);
+
+ if (pqh == NULL)
+ {
+ lock_td_pool(&uhci->td_pool, TRUE);
+
+ if (pthis)
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
+
+ }
+
+ urb->td_count = td_count;
+
+ uhci_insert_tds_qh(pqh, ((PTD_EXTENSION) pthis)->ptd);
+ uhci_insert_qh_urb(urb, pqh);
+ urb->pendp->flags =
+ (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
+ usb_endp_busy_count_inc(urb->pendp);
+ uhci_insert_urb_to_schedule(uhci, urb, ret);
+
+ if (ret == FALSE)
+ {
+ // undo all we have done
+ RemoveEntryList(&pqh->pqhe->vert_link); //remove qh from td_chain
+ RemoveEntryList(&urb->trasac_list);
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ if (pthis)
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ lock_qh_pool(&uhci->qh_pool, TRUE);
+ if (pqh)
+ free_qh(&uhci->qh_pool, pqh);
+ unlock_qh_pool(&uhci->qh_pool, TRUE);
+
+ InitializeListHead(&urb->trasac_list);
+ usb_endp_busy_count_dec(urb->pendp);
+ urb->pendp->flags =
+ (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+uhci_internal_submit_ctrl(PUHCI_DEV uhci, PURB urb)
+{
+ LIST_ENTRY td_list, *pthis, *pnext;
+ LONG i, td_count;
+ LONG toggle;
+ LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx;
+ PUHCI_TD ptd;
+ PUHCI_QH pqh;
+ ULONG dev_addr;
+ PUSB_DEV pdev;
+ BOOL ret;
+
+ if (uhci == NULL || urb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ toggle = 0;
+ bytes_rest = urb->rest_bytes;
+ bytes_to_transfer = urb->bytes_to_transfer;
+ max_packet_size = endp_max_packet_size(urb->pendp);
+ start_idx = urb->data_length - urb->rest_bytes;
+ td_count = 2 + (urb->bytes_to_transfer + max_packet_size - 1) / max_packet_size;
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+
+ if (can_transfer(&uhci->td_pool, td_count) == FALSE)
+ {
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ ptd = alloc_tds(&uhci->td_pool, td_count);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ if (ptd == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ InsertTailList(&ptd->ptde->vert_link, &td_list);
+
+ ListFirst(&td_list, pthis);
+ ListNext(&td_list, pthis, pnext);
+
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+
+ pdev = dev_from_endp(urb->pendp);
+ dev_addr = pdev->dev_addr;
+
+ if (dev_state(pdev) <= USB_DEV_STATE_RESET)
+ dev_addr = 0;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("uhci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr));
+
+ RtlCopyMemory(uhci->io_buf, urb->setup_packet, 8);
+
+ if ((urb->setup_packet[0] & USB_DIR_IN) == 0) //out
+ RtlCopyMemory(&uhci->io_buf[8], urb->data_buffer, bytes_to_transfer);
+ else
+ RtlZeroMemory(&uhci->io_buf[8], bytes_to_transfer);
+
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT) | (TD_CTRL_ACTIVE),
+ (7 << 21) | (((ULONG) endp_num(urb->pendp)) << 15) | (dev_addr << 8) | (USB_PID_SETUP),
+ //uhci->io_buf_logic_addr.LowPart);
+ MmGetPhysicalAddress(urb->setup_packet).LowPart);
+
+ ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr;
+ pthis = pnext;
+ ListNext(&td_list, pthis, pnext);
+
+ urb->pipe = ((max_packet_size - 1) << 21)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (dev_addr << 8) | (pdev->flags & USB_DEV_FLAG_LOW_SPEED) | USB_ENDPOINT_XFER_CONTROL;
+
+ for(i = 0, toggle = 1; ((i < td_count - 2) && pthis); i++, toggle ^= 1)
+ {
+ //construct tds for DATA packets of data stage.
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT)
+ | (TD_CTRL_ACTIVE),
+ ((bytes_to_transfer >
+ max_packet_size ? max_packet_size - 1 : bytes_to_transfer -
+ 1) << 21) | (toggle << 19) | (((ULONG) endp_num(urb->
+ pendp)) << 15) | (dev_addr << 8) |
+ ((urb->setup_packet[0] & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT),
+ //uhci->io_buf_logic_addr.LowPart + 8 + i * max_packet_size );
+ MmGetPhysicalAddress(&urb->data_buffer[start_idx + i * max_packet_size]).LowPart);
+
+ if (pnext)
+ ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr;
+
+ if (i < td_count - 3)
+ {
+ bytes_to_transfer -= max_packet_size;
+ }
+ else
+ {
+ if (bytes_to_transfer > 0)
+ {
+ if (bytes_to_transfer < max_packet_size && (urb->setup_packet[0] & USB_DIR_IN))
+ ptd->status |= TD_CTRL_SPD;
+ }
+ }
+ pthis = pnext;
+
+ if (pthis)
+ ListNext(&td_list, pthis, pnext);
+ }
+
+ if (pnext)
+ ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr;
+
+ ListFirstPrev(&td_list, pthis);
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+
+ //the last is an IN transaction
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT)
+ | (TD_CTRL_ACTIVE | TD_CTRL_IOC),
+ (UHCI_NULL_DATA_SIZE << 21)
+ | (1 << 19)
+ | (((ULONG) endp_num(urb->pendp)) << 15)
+ | (dev_addr << 8)
+ | ((td_count > 2)
+ ? ((urb->setup_packet[0] & USB_DIR_IN) ? USB_PID_OUT : USB_PID_IN) : USB_PID_IN), 0);
+
+ ptd->link = UHCI_PTR_TERM;
+
+ ListFirst(&td_list, pthis);
+ RemoveEntryList(&td_list);
+
+ lock_qh_pool(&uhci->qh_pool, TRUE);
+ pqh = alloc_qh(&uhci->qh_pool);
+ unlock_qh_pool(&uhci->qh_pool, TRUE);
+
+ if (pqh == NULL)
+ {
+ lock_td_pool(&uhci->td_pool, TRUE);
+ if (pthis)
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ urb->td_count = td_count;
+
+ uhci_insert_tds_qh(pqh, ((PTD_EXTENSION) pthis)->ptd);
+ uhci_insert_qh_urb(urb, pqh);
+
+ usb_endp_busy_count_inc(urb->pendp);
+ uhci_insert_urb_to_schedule(uhci, urb, ret);
+ if (ret == FALSE)
+ {
+ RemoveEntryList(&pqh->pqhe->vert_link);
+ RemoveEntryList(&urb->trasac_list);
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ if (pthis)
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ lock_qh_pool(&uhci->qh_pool, TRUE);
+ if (pqh)
+ free_qh(&uhci->qh_pool, pqh);
+ unlock_qh_pool(&uhci->qh_pool, TRUE);
+
+ InitializeListHead(&urb->trasac_list);
+ usb_endp_busy_count_dec(urb->pendp);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+uhci_internal_submit_int(PUHCI_DEV uhci, PURB urb)
+{
+ LIST_ENTRY td_list, *pthis, *pnext;
+ LONG i;
+ LONG toggle = 0;
+ LONG max_packet_size;
+ PUHCI_TD ptd;
+ BOOL ret;
+
+ if (uhci == NULL || urb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ toggle = (urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE;
+ max_packet_size = endp_max_packet_size(urb->pendp);
+
+ if (max_packet_size < urb->data_length || max_packet_size == 0 || max_packet_size > 64)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ ptd = alloc_td(&uhci->td_pool);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ if (ptd == NULL)
+ return STATUS_NO_MORE_ENTRIES;
+
+ for(i = 1; i <= 7; i++)
+ {
+ if (((ULONG) max_packet_size) >> i)
+ continue;
+ else
+ break;
+ }
+
+ i--;
+ i &= 7;
+
+ urb->pipe = (((ULONG) urb->pendp->pusb_endp_desc->bInterval) << 24)
+ | (i << 21)
+ | (toggle << 19)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8)
+ | USB_DIR_IN | (dev_from_endp(urb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) | USB_ENDPOINT_XFER_INT;
+
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT)
+ | (TD_CTRL_ACTIVE)
+ | ((urb->data_length < max_packet_size ? TD_CTRL_SPD : 0))
+ | (TD_CTRL_IOC),
+ (((ULONG) max_packet_size - 1) << 21)
+ | (toggle << 19)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (((ULONG) dev_from_endp(urb->pendp)->dev_addr & 0x7f) << 8)
+ | USB_PID_IN, MmGetPhysicalAddress(urb->data_buffer).LowPart);
+
+ toggle ^= 1;
+ urb->td_count = 1;
+
+ InitializeListHead(&urb->trasac_list);
+ InsertTailList(&urb->trasac_list, &ptd->ptde->vert_link);
+
+ //indirectly guarded by pending_endp_list_lock
+ if (uhci_claim_bandwidth(uhci, urb, TRUE) == FALSE)
+ {
+ InitializeListHead(&urb->trasac_list);
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ free_td(&uhci->td_pool, ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ return STATUS_NO_MORE_ENTRIES;
+ }
- if( ( purb->flags & URB_FLAG_IN_SCHEDULE ) == 0 )
- {
- //finished or canceled( not apply for split bulk ).
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_FINISHED;
- RemoveEntryList( pthis );
- InsertTailList( ptemp, pthis );
- }
- pthis = pnext;
- }
- pparam->ret = TRUE;
- return ( UCHAR )TRUE;
-}
+ urb->pendp->flags = (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle << 31);
+ usb_endp_busy_count_inc(urb->pendp);
-BOOLEAN
-uhci_drop_fsbr(
-PUHCI_DEV uhci
-)
-{
+ uhci_insert_urb_to_schedule(uhci, urb, ret);
- if( uhci == NULL )
- return ( UCHAR )FALSE;
-
- uhci->fsbr_cnt--;
-
- if( uhci->fsbr_cnt <= 0 )
- {
- uhci->skel_term_qh->link = UHCI_PTR_TERM;
- uhci->fsbr_cnt = 0;
- }
-
- return ( UCHAR )TRUE;
-}
-VOID
-uhci_dpc_callback(
-PKDPC dpc,
-PVOID context,
-PVOID sysarg1,
-PVOID sysarg2
-)
-{
- PUHCI_DEV uhci;
-
- LIST_HEAD temp_list;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- PQH_EXTENSION pqhe;
- PTD_EXTENSION ptde;
- PUHCI_PENDING_ENDP pending_endp;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
-
- BOOL finished;
- LONG i, j;
- ULONG uhci_status, urb_status, toggle = 0;
-
- SYNC_PARAM sync_param;
- USE_IRQL;
-
- uhci = ( PUHCI_DEV ) context;
- if( uhci == NULL )
- return;
-
- uhci_status = ( ULONG )sysarg1;
-
- InitializeListHead( &temp_list );
-
- sync_param.uhci = uhci;
- sync_param.context = ( PVOID )&temp_list;
-
- uhci_dbg_print( DBGLVL_MAXIMUM, ( "uhci_dpc_callback(): entering..., uhci=0x%x\n", uhci ) );
- //remove finished urb from uhci's urb-list
- KeSynchronizeExecution( uhci->pdev_ext->uhci_int, uhci_sync_remove_urb_finished, &sync_param );
+ if (ret == FALSE)
+ {
+ lock_td_pool(&uhci->td_pool, TRUE);
+ if (ptd)
+ free_td(&uhci->td_pool, ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+
+ InitializeListHead(&urb->trasac_list);
+ usb_endp_busy_count_dec(urb->pendp);
+ urb->pendp->flags = (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | ((toggle ^ 1) << 31);
+ uhci_claim_bandwidth(uhci, urb, FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
- //release resources( tds, and qhs ) the urb occupied
- while( IsListEmpty( &temp_list ) == FALSE )
- {
- //not in any public queue, if do not access into dev, no race
- //condition will occur
- purb = ( PURB ) RemoveHeadList( &temp_list );
- urb_status = purb->status;
-
- //the only place we do not use this lock on non-pending-endp-list data ops
- KeAcquireSpinLockAtDpcLevel( &uhci->pending_endp_list_lock );
- while( IsListEmpty( &purb->trasac_list ) == FALSE )
- {
- pthis = RemoveHeadList( &purb->trasac_list );
-
- if( ( ( ( PTD_EXTENSION )pthis )->flags & UHCI_ITEM_FLAG_TYPE )
- == UHCI_ITEM_FLAG_QH )
- {
- pqhe = ( PQH_EXTENSION ) pthis;
- lock_qh_pool( &uhci->qh_pool, TRUE );
- free_qh( &uhci->qh_pool, pqhe->pqh );
- unlock_qh_pool( &uhci->qh_pool, TRUE );
- }
- else
- {
- //must be a td chain
- InsertHeadList( &purb->trasac_list, pthis );
- for( i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++ )
- {
- PUHCI_TD ptd;
- // accumulate data transfered in tds
- ptd = ( ( PTD_EXTENSION )pthis )->ptd;
- if( ( ptd->status & TD_CTRL_ACTIVE ) == 0 && ( ptd->status & TD_CTRL_ANY_ERROR ) == 0 )
- {
- j = ptd->status & 0x7ff;
- purb->bytes_transfered += ( ( j == 0x7ff ) ? 0 : ( j + 1 ) );
-
- }
- ListNext( &purb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
-
- if( urb_status & TD_CTRL_ANY_ERROR )
- {
- if( purb->last_finished_td != NULL && purb->last_finished_td != &purb->trasac_list )
- toggle = ( ( ( PTD_EXTENSION )purb->last_finished_td )->ptd->info & ( 1 << 19 ) );
- }
- //trick, remove trasac_list
- ListFirst( &purb->trasac_list, pthis );
- RemoveEntryList( &purb->trasac_list );
- lock_td_pool( &uhci->td_pool, TRUE );
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
- //termination condition
- InitializeListHead( &purb->trasac_list );
- purb->last_finished_td = NULL;
- }
- }
-
- if( endp_type( purb->pendp ) == USB_ENDPOINT_XFER_ISOC
- || endp_type( purb->pendp ) == USB_ENDPOINT_XFER_INT )
- uhci_claim_bandwidth( uhci, purb, FALSE); //release band-width
-
- KeReleaseSpinLockFromDpcLevel( &uhci->pending_endp_list_lock );
-
- uhci_set_error_code( purb, urb_status );
-
- finished = TRUE;
-
- //since the ref_count for the urb is not released, we can safely have one
- //pointer to dev
- pdev = dev_from_endp( purb->pendp );
- pendp = purb->pendp;
-
- if( purb->status == USB_STATUS_BABBLE_DETECTED )
- {
- usb_dbg_print( DBGLVL_MEDIUM, ( "uhci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n" ) );
- uhci_reset( uhci );
- uhci_start( &uhci->hcd_interf );
- }
-
- //this will let the new request in uhci_generic_urb_completion to this endp
- //be processed rather than queued in the pending_endp_list
- lock_dev( pdev, TRUE );
- usb_endp_busy_count_dec( pendp );
- unlock_dev( pdev, TRUE );
-
- if( usb_success( purb->status ) == FALSE )
- {
- // set error code and complete the urb and purb is invalid from this point
- uhci_generic_urb_completion( purb, purb->context );
- }
- else
- {
- if( ( purb->pipe & USB_ENDPOINT_XFERTYPE_MASK )
- == USB_ENDPOINT_XFER_BULK )
- {
- purb->rest_bytes -= purb->bytes_transfered;
- if( purb->rest_bytes )
- {
- finished = FALSE;
- }
- else
- {
- uhci_generic_urb_completion( purb, purb->context );
- }
- }
- else
- {
- uhci_generic_urb_completion( purb, purb->context );
- //purb is now invalid
- }
- }
-
- KeAcquireSpinLockAtDpcLevel( &uhci->pending_endp_list_lock );
- lock_dev( pdev, TRUE );
-
- if( finished )
- pdev->ref_count--;
-
- if( urb_status & TD_CTRL_ANY_ERROR
- && endp_type( pendp ) != USB_ENDPOINT_XFER_CONTROL )
- {
- pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
- pendp->flags |= USB_ENDP_FLAG_STALL;
- }
-
- if( dev_state( pdev )== USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &uhci->pending_endp_list_lock );
- if( finished == FALSE )
- {
-
- purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- uhci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, TRUE );
- pdev->ref_count--;
- unlock_dev( pdev, TRUE);
- }
- continue;
- }
-
- if( finished && IsListEmpty( &pendp->urb_list ) == TRUE )
- {
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &uhci->pending_endp_list_lock );
- continue;
- }
- else if( finished == TRUE )
- {
- //has urb in the endp's urb-list
- if( usb_endp_busy_count( pendp ) > 0 )
- {
- //the urbs still have chance to be sheduled but not this time
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &uhci->pending_endp_list_lock );
- continue;
- }
- }
-
- if( finished == FALSE )
- {
- //a split bulk transfer
- purb->bytes_transfered = 0;
- purb->bytes_to_transfer =
- UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize
- > purb->rest_bytes
- ? purb->rest_bytes
- : UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize;
-
- //the urb is not finished
- purb->flags &= ~URB_FLAG_STATE_MASK;
- purb->flags |= URB_FLAG_STATE_PENDING;
-
- InsertHeadList( &pendp->urb_list, ( PLIST_ENTRY )purb );
- }
-
- pending_endp = alloc_pending_endp( &uhci->pending_endp_pool, 1 );
- pending_endp->pendp = pendp;
- InsertTailList( &uhci->pending_endp_list, &pending_endp->endp_link );
-
- unlock_dev( pdev, TRUE);
- KeReleaseSpinLockFromDpcLevel( &uhci->pending_endp_list_lock );
- }
-
- //ah...exhausted, let's find some in the pending_endp_list to rock
- uhci_process_pending_endp( uhci );
- return;
+ return STATUS_SUCCESS;
}
-BOOL
-uhci_add_device(
-PUHCI_DEV uhci,
-PUSB_DEV dev
-)
+
+static NTSTATUS
+uhci_internal_submit_iso(PUHCI_DEV uhci, PURB urb)
{
- if( dev == NULL || uhci == NULL )
- return FALSE;
+ PUHCI_TD ptd;
+ LIST_ENTRY td_list, *pthis, *pnext;
+ int i;
+ BOOL toggle, ret;
+ KIRQL old_irql;
- return TRUE;
+ if (uhci == NULL || urb == NULL)
+ return STATUS_INVALID_PARAMETER;
-}
+ if (urb->iso_frame_count == 0)
+ return STATUS_INVALID_PARAMETER;
-BOOLEAN
-uhci_sync_cancel_urbs_dev(
-PVOID context
-)
-{
- //cancel all the urbs on one dev
- PUHCI_DEV uhci;
- PUSB_DEV pdev, dest_dev;
- PSYNC_PARAM sync_param;
- PLIST_ENTRY pthis, pnext;
- LONG count;
-
- sync_param = ( PSYNC_PARAM )context;
- dest_dev = ( PUSB_DEV )sync_param->context;
- uhci = sync_param->uhci;
-
- if( uhci == NULL || dest_dev == NULL )
- {
- return ( UCHAR )sync_param->ret = FALSE;
- }
- count = 0;
- ListFirst( &uhci->urb_list, pthis );
- while( pthis )
- {
- pdev = dev_from_endp( ( ( PURB ) pthis )->pendp );
- if( pdev == dest_dev )
- {
- ( ( PURB ) pthis )->flags |= URB_FLAG_FORCE_CANCEL;
- }
- ListNext( &uhci->urb_list, pthis, pnext );
- pthis = pnext;
- count ++;
- }
- if( count )
- uhci->skel_term_td->status |= TD_CTRL_IOC;
-
- return ( UCHAR )sync_param->ret = TRUE;
-}
+ lock_td_pool(&uhci->td_pool, TRUE);
-BOOL
-uhci_remove_device(
-PUHCI_DEV uhci,
-PUSB_DEV dev
-)
-{
- PUHCI_PENDING_ENDP ppending_endp;
- PLIST_ENTRY pthis, pnext;
- PURB purb;
- LIST_HEAD temp_list;
- int i, j, k;
- SYNC_PARAM sync_param;
-
- USE_IRQL;
-
- if( uhci == NULL || dev == NULL )
- return FALSE;
-
- InitializeListHead( &temp_list );
-
- //free pending endp that has urb queued from pending endp list
- lock_pending_endp_list( &uhci->pending_endp_list_lock );
-
- ListFirst( &uhci->pending_endp_list, pthis );
-
- while( pthis )
- {
- ppending_endp = ( PUHCI_PENDING_ENDP ) pthis;
- ListNext( &uhci->pending_endp_list, pthis, pnext );
- if( dev_from_endp( ppending_endp->pendp ) == dev )
- {
- RemoveEntryList( pthis );
- free_pending_endp( &uhci->pending_endp_pool, struct_ptr( pthis, UHCI_PENDING_ENDP, endp_link ) );
- }
- pthis = pnext;
- }
- unlock_pending_endp_list( &uhci->pending_endp_list_lock );
-
- //cancel all the urbs in the urb-list
- sync_param.uhci = uhci;
- sync_param.context = ( PVOID )dev;
-
- KeSynchronizeExecution( uhci->pdev_ext->uhci_int, uhci_sync_cancel_urbs_dev, &sync_param );
-
- //cancel all the urb in the endp's urb-list
- k = 0;
- lock_dev( dev, FALSE );
- if( dev->usb_config )
- {
- //only for configed dev
- for( i = 0; i < dev->usb_config->if_count; i++ )
- {
- for( j = 0; j < dev->usb_config->interf[ i ].endp_count; j++ )
- {
- ListFirst( &dev->usb_config->interf[ i ].endp[ j ].urb_list, pthis );
- while( pthis )
- {
- ListNext( &dev->usb_config->interf[ i ].endp[ j ].urb_list,
- pthis,
- pnext );
-
- RemoveEntryList( pthis );
- InsertHeadList( &temp_list, pthis );
- pthis = pnext;
- k++;
- }
-
- }
- }
- }
- ListFirst( &dev->default_endp.urb_list, pthis );
-
- while( pthis )
- {
- ListNext( &dev->default_endp.urb_list,
- pthis,
- pnext );
-
- RemoveEntryList( pthis );
- InsertHeadList( &temp_list, pthis );
- pthis = pnext;
- k++;
- }
- unlock_dev( dev, FALSE );
-
- if( IsListEmpty( &temp_list ) == FALSE )
- {
- for( i = 0; i < k ; i++ )
- {
- //complete those urbs with error
- pthis = RemoveHeadList( &temp_list );
- purb = ( PURB ) pthis;
- purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
- {
- uhci_generic_urb_completion( purb, purb->context );
- }
- }
- }
-
- lock_dev( dev, FALSE )
- dev->ref_count -= k;
- unlock_dev( dev, FALSE );
-
- return TRUE;
-}
+ if (can_transfer(&uhci->td_pool, urb->iso_frame_count) == FALSE)
+ {
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ ptd = alloc_tds(&uhci->td_pool, urb->iso_frame_count);
+ unlock_td_pool(&uhci->td_pool, TRUE);
-static NTSTATUS
-uhci_internal_submit_bulk(
-PUHCI_DEV uhci,
-PURB urb
-)
-//
-// assume that the urb has its rest_bytes and bytes_to_transfer set
-// and bytes_transfered is zeroed.
-// dev_lock must be acquired outside
-// urb comes from dev's endpoint urb-list. it is already removed from
-// the endpoint urb-list.
-//
-{
+ if (ptd == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
- LONG max_packet_size, td_count, offset, bytes_to_transfer, data_load;
- PBYTE start_addr;
- PUHCI_TD ptd;
- PUHCI_QH pqh;
- LIST_ENTRY td_list, *pthis, *pnext;
- BOOL old_toggle, toggle, ret;
- UCHAR pid;
+ InsertTailList(&ptd->ptde->vert_link, &td_list);
+ ListFirst(&td_list, pthis);
- if( uhci == NULL || urb == NULL )
- return STATUS_INVALID_PARAMETER;
+ urb->td_count = urb->iso_frame_count;
- max_packet_size = endp_max_packet_size( urb->pendp );
- if( urb->bytes_to_transfer == 0 )
- {
- return STATUS_INVALID_PARAMETER;
- }
+ urb->pipe = (((ULONG) urb->iso_packet_desc[0].length) << 21)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8)
+ | ((ULONG) endp_dir(urb->pendp)) | USB_ENDPOINT_XFER_ISOC;
- td_count = ( urb->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;
-
- lock_td_pool( &uhci->td_pool, TRUE );
- if( can_transfer( &uhci->td_pool, td_count ) == FALSE )
- {
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
- }
- ptd = alloc_tds( &uhci->td_pool, td_count );
- unlock_td_pool( &uhci->td_pool, TRUE );
+ for(i = 0; i < urb->iso_frame_count && pthis; i++)
+ {
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ uhci_fill_td(ptd,
+ (3 << TD_CTRL_C_ERR_SHIFT)
+ | (TD_CTRL_ACTIVE)
+ | (TD_CTRL_IOS),
+ (((ULONG) urb->iso_packet_desc[i].length - 1) << 21)
+ | (0 << 19)
+ | ((ULONG) endp_num(urb->pendp) << 15)
+ | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8)
+ | ((urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN)
+ ? USB_PID_OUT : USB_PID_IN),
+ MmGetPhysicalAddress(&urb->data_buffer[urb->iso_packet_desc[i].offset]).LowPart);
+
+ toggle ^= 1;
+ ListNext(&td_list, pthis, pnext);
+ pthis = pnext;
+ }
- if( ptd == NULL )
- {
- return STATUS_UNSUCCESSFUL;
- }
+ ptd->status |= TD_CTRL_IOC; //need interrupt
- InitializeListHead( &td_list );
- InsertTailList( &ptd->ptde->vert_link, &td_list );
+ ListFirst(&td_list, pthis);
+ RemoveEntryList(&td_list);
- ListFirst( &td_list, pthis );
- ListNext( &td_list, pthis, pnext );
+ InsertTailList(pthis, &urb->trasac_list);
- start_addr = &urb->data_buffer[ urb->data_length - urb->rest_bytes ];
- offset = 0;
+ //indirectly guarded by pending_endp_list_lock
+ if (uhci_claim_bandwidth(uhci, urb, TRUE) == FALSE)
+ {
+ //bad news: we can not allocate the enough bandwidth for the urb
+ RemoveEntryList(&urb->trasac_list);
+ InitializeListHead(&urb->trasac_list);
- old_toggle = toggle = urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ? TRUE : FALSE;
- bytes_to_transfer = urb->bytes_to_transfer;
+ lock_td_pool(&uhci->td_pool, TRUE);
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ return STATUS_NO_MORE_ENTRIES;
- urb->pipe = ( ( max_packet_size - 1 ) << 21 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( dev_from_endp( urb->pendp )->dev_addr << 8 )
- | ( ( ULONG )endp_dir( urb->pendp ) )
- | USB_ENDPOINT_XFER_BULK;
+ }
- pid = ( ( ( ULONG )urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? USB_PID_IN : USB_PID_OUT );
- while( pthis )
+ usb_endp_busy_count_inc(urb->pendp);
+ uhci_insert_urb_to_schedule(uhci, urb, ret);
+ if (ret == FALSE)
{
- ptd = ( ( PTD_EXTENSION )pthis )->ptd;
-
- data_load = max_packet_size < bytes_to_transfer ? max_packet_size : bytes_to_transfer;
- ptd->purb = urb;
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT )
- | ( TD_CTRL_ACTIVE ),
- ( ( data_load - 1 ) << 21 )
- | ( toggle << 19 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( dev_from_endp( urb->pendp )->dev_addr << 8 )
- | pid,
- MmGetPhysicalAddress( start_addr + offset ).LowPart );
-
- bytes_to_transfer -= data_load;
- offset += data_load;
-
- if( pnext )
- {
- ptd->link = ( ( PTD_EXTENSION ) pnext )->ptd->phy_addr;
- }
- else
- {
- //Last one, enable ioc and short packet detect if necessary
- ptd->link = UHCI_PTR_TERM;
- ptd->status |= TD_CTRL_IOC;
- if( bytes_to_transfer < max_packet_size && ( pid == USB_PID_IN ) )
- {
- //ptd->status |= TD_CTRL_SPD;
- }
- }
-
- pthis = pnext;
- toggle ^= 1;
- if( pthis )
- ListNext( &td_list, pthis, pnext );
-
- }
-
- ListFirst( &td_list, pthis );
- RemoveEntryList( &td_list );
-
- lock_qh_pool( &uhci->qh_pool, TRUE );
- pqh = alloc_qh( &uhci->qh_pool );
- unlock_qh_pool( &uhci->qh_pool, TRUE);
-
- if( pqh == NULL )
- {
- lock_td_pool( &uhci->td_pool, TRUE );
-
- if( pthis )
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
-
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
-
- urb->td_count = td_count;
-
- uhci_insert_tds_qh( pqh, ( ( PTD_EXTENSION )pthis )->ptd );
- uhci_insert_qh_urb( urb, pqh );
- urb->pendp->flags = ( urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( toggle ? USB_ENDP_FLAG_DATATOGGLE : 0 ) ;
- usb_endp_busy_count_inc( urb->pendp );
- uhci_insert_urb_to_schedule( uhci, urb, ret );
-
- if( ret == FALSE )
- {
- // undo all we have done
- RemoveEntryList( &pqh->pqhe->vert_link ); //remove qh from td_chain
- RemoveEntryList( &urb->trasac_list );
-
- lock_td_pool( &uhci->td_pool, TRUE );
- if( pthis )
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- lock_qh_pool( &uhci->qh_pool, TRUE );
- if( pqh )
- free_qh( &uhci->qh_pool, pqh );
- unlock_qh_pool( &uhci->qh_pool, TRUE );
-
- InitializeListHead( &urb->trasac_list );
- usb_endp_busy_count_dec( urb->pendp );
- urb->pendp->flags = ( urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0 ) ;
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
+ usb_endp_busy_count_dec(urb->pendp);
+ RemoveEntryList(&urb->trasac_list);
+
+ lock_td_pool(&uhci->td_pool, TRUE);
+ free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd);
+ unlock_td_pool(&uhci->td_pool, TRUE);
+ uhci_claim_bandwidth(uhci, urb, FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
}
-static NTSTATUS
-uhci_internal_submit_ctrl(
-PUHCI_DEV uhci,
-PURB urb
-)
+// runs in uhci_isr
+static BOOL
+uhci_is_xfer_finished(PURB urb)
{
+ PLIST_ENTRY pthis, pnext;
+ PUHCI_TD ptd;
+ PUHCI_QH pqh;
+ BOOL ret;
+ PTD_EXTENSION ptde;
- LIST_ENTRY td_list, *pthis, *pnext;
- LONG i, td_count;
- LONG toggle;
- LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx;
- PUHCI_TD ptd;
- PUHCI_QH pqh;
- ULONG dev_addr;
- PUSB_DEV pdev;
- BOOL ret;
-
- if( uhci == NULL || urb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- toggle = 0;
- bytes_rest = urb->rest_bytes;
- bytes_to_transfer = urb->bytes_to_transfer;
- max_packet_size = endp_max_packet_size( urb->pendp );
- start_idx = urb->data_length - urb->rest_bytes;
- td_count = 2 + ( urb->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;
-
- lock_td_pool( &uhci->td_pool, TRUE );
-
- if( can_transfer( &uhci->td_pool, td_count ) == FALSE )
- {
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
- }
-
- ptd = alloc_tds( &uhci->td_pool, td_count );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- if( ptd == NULL )
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- InsertTailList( &ptd->ptde->vert_link, &td_list );
-
- ListFirst( &td_list, pthis );
- ListNext( &td_list, pthis, pnext );
-
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
-
- pdev = dev_from_endp( urb->pendp );
- dev_addr = pdev->dev_addr;
-
- if( dev_state( pdev ) <= USB_DEV_STATE_RESET )
- dev_addr = 0;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_internal_submit_ctrl(): dev_addr =0x%x\n", \
- dev_addr ) );
-
- RtlCopyMemory( uhci->io_buf, urb->setup_packet, 8 );
-
- if( ( urb->setup_packet[ 0 ] & USB_DIR_IN ) == 0 ) //out
- RtlCopyMemory( &uhci->io_buf[ 8 ], urb->data_buffer, bytes_to_transfer );
- else
- RtlZeroMemory( &uhci->io_buf[ 8 ], bytes_to_transfer );
-
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT ) | ( TD_CTRL_ACTIVE ),
- ( 7 << 21 )
- | ( ( ( ULONG )endp_num( urb->pendp ) ) << 15 )
- | ( dev_addr << 8 )
- | ( USB_PID_SETUP ),
- //uhci->io_buf_logic_addr.LowPart );
- MmGetPhysicalAddress( urb->setup_packet ).LowPart );
-
- ptd->link = ( ( PTD_EXTENSION ) pnext )->ptd->phy_addr;
- pthis = pnext;
- ListNext( &td_list, pthis, pnext );
-
- urb->pipe = ( ( max_packet_size - 1 ) << 21 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( dev_addr << 8 )
- | ( pdev->flags & USB_DEV_FLAG_LOW_SPEED )
- | USB_ENDPOINT_XFER_CONTROL;
-
- for( i = 0, toggle = 1; ( ( i < td_count - 2 ) && pthis ); i++, toggle ^= 1 )
- {
- //construct tds for DATA packets of data stage.
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT )
- | ( TD_CTRL_ACTIVE ),
- ( ( bytes_to_transfer > max_packet_size ? max_packet_size - 1 : bytes_to_transfer - 1 ) << 21 )
- | ( toggle << 19 )
- | ( ( ( ULONG )endp_num( urb->pendp ) ) << 15 )
- | ( dev_addr << 8 )
- | ( ( urb->setup_packet[ 0 ] & USB_DIR_IN ) ? USB_PID_IN : USB_PID_OUT ),
- //uhci->io_buf_logic_addr.LowPart + 8 + i * max_packet_size );
- MmGetPhysicalAddress( &urb->data_buffer[ start_idx + i * max_packet_size ] ).LowPart );
-
- if( pnext )
- ptd->link = ( ( PTD_EXTENSION ) pnext )->ptd->phy_addr;
-
- if( i < td_count - 3 )
- {
- bytes_to_transfer -= max_packet_size;
- }
- else
- {
- if( bytes_to_transfer > 0 )
- {
- if( bytes_to_transfer < max_packet_size && ( urb->setup_packet[ 0 ] & USB_DIR_IN ) )
- ptd->status |= TD_CTRL_SPD;
- }
- }
- pthis = pnext;
-
- if( pthis )
- ListNext( &td_list, pthis, pnext );
- }
-
- if( pnext )
- ptd->link = ( ( PTD_EXTENSION ) pnext )->ptd->phy_addr;
-
- ListFirstPrev( &td_list, pthis );
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
+ if (urb->last_finished_td == NULL)
+ {
+ urb->last_finished_td = &urb->trasac_list;
+ }
- //the last is an IN transaction
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT )
- | ( TD_CTRL_ACTIVE | TD_CTRL_IOC ),
- ( UHCI_NULL_DATA_SIZE << 21 )
- | ( 1 << 19 )
- | ( ( ( ULONG )endp_num( urb->pendp ) ) << 15 )
- | ( dev_addr << 8 )
- | ( ( td_count > 2 )
- ? ( ( urb->setup_packet[ 0 ] & USB_DIR_IN )
- ? USB_PID_OUT : USB_PID_IN )
- : USB_PID_IN ),
- 0 );
-
- ptd->link = UHCI_PTR_TERM;
-
- ListFirst( &td_list, pthis );
- RemoveEntryList( &td_list );
-
- lock_qh_pool( &uhci->qh_pool, TRUE );
- pqh = alloc_qh( &uhci->qh_pool );
- unlock_qh_pool( &uhci->qh_pool, TRUE);
-
- if( pqh == NULL )
- {
- lock_td_pool( &uhci->td_pool, TRUE );
- if( pthis )
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
-
- urb->td_count = td_count;
-
- uhci_insert_tds_qh( pqh, ( ( PTD_EXTENSION )pthis )->ptd );
- uhci_insert_qh_urb( urb, pqh );
-
- usb_endp_busy_count_inc( urb->pendp );
- uhci_insert_urb_to_schedule( uhci, urb, ret );
- if( ret == FALSE )
- {
- RemoveEntryList( &pqh->pqhe->vert_link );
- RemoveEntryList( &urb->trasac_list );
-
- lock_td_pool( &uhci->td_pool, TRUE );
- if( pthis )
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- lock_qh_pool( &uhci->qh_pool, TRUE );
- if( pqh )
- free_qh( &uhci->qh_pool, pqh );
- unlock_qh_pool( &uhci->qh_pool, TRUE );
-
- InitializeListHead( &urb->trasac_list );
- usb_endp_busy_count_dec( urb->pendp );
- return STATUS_UNSUCCESSFUL;
- }
- return STATUS_SUCCESS;
-}
+ if (&urb->trasac_list == urb->last_finished_td)
+ ListFirst(&urb->trasac_list, pthis)
+ else
+ ListNext(&urb->trasac_list, urb->last_finished_td, pthis);
-static NTSTATUS
-uhci_internal_submit_int(
-PUHCI_DEV uhci,
-PURB urb
-)
-{
- LIST_ENTRY td_list, *pthis, *pnext;
- LONG i;
- LONG toggle = 0;
- LONG max_packet_size;
- PUHCI_TD ptd;
- BOOL ret;
-
- if( uhci == NULL || urb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- toggle = ( urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ) ? TRUE : FALSE;
- max_packet_size = endp_max_packet_size( urb->pendp );
-
- if( max_packet_size < urb->data_length || max_packet_size == 0 || max_packet_size > 64 )
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- lock_td_pool( &uhci->td_pool, TRUE );
- ptd = alloc_td( &uhci->td_pool );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- if( ptd == NULL )
- return STATUS_NO_MORE_ENTRIES;
-
- for( i = 1; i <= 7; i++ )
- {
- if( ( ( ULONG )max_packet_size ) >> i )
- continue;
- else
- break;
- }
-
- i --;
- i &= 7;
-
- urb->pipe = ( ( ( ULONG )urb->pendp->pusb_endp_desc->bInterval ) << 24 )
- | ( i << 21 )
- | ( toggle << 19 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( ( ( ULONG )dev_from_endp( urb->pendp )->dev_addr ) << 8 )
- | USB_DIR_IN
- | ( dev_from_endp( urb->pendp )->flags & USB_DEV_FLAG_LOW_SPEED )
- | USB_ENDPOINT_XFER_INT;
-
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT )
- | ( TD_CTRL_ACTIVE )
- | ( ( urb->data_length < max_packet_size ? TD_CTRL_SPD : 0 ) )
- | ( TD_CTRL_IOC ),
- ( ( ( ULONG )max_packet_size - 1 ) << 21 )
- | ( toggle << 19 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( ( ( ULONG )dev_from_endp( urb->pendp )->dev_addr & 0x7f) << 8 )
- | USB_PID_IN,
- MmGetPhysicalAddress( urb->data_buffer ).LowPart );
-
- toggle ^= 1;
- urb->td_count = 1;
-
- InitializeListHead( &urb->trasac_list );
- InsertTailList( &urb->trasac_list, &ptd->ptde->vert_link );
-
- //indirectly guarded by pending_endp_list_lock
- if( uhci_claim_bandwidth( uhci, urb, TRUE ) == FALSE )
- {
- InitializeListHead( &urb->trasac_list );
-
- lock_td_pool( &uhci->td_pool, TRUE );
- free_td( &uhci->td_pool, ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
-
- urb->pendp->flags = ( urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE )
- | ( toggle << 31 );
- usb_endp_busy_count_inc( urb->pendp );
-
- uhci_insert_urb_to_schedule( uhci, urb, ret );
-
- if( ret == FALSE )
- {
- lock_td_pool( &uhci->td_pool, TRUE );
- if( ptd )
- free_td( &uhci->td_pool, ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- InitializeListHead( &urb->trasac_list );
- usb_endp_busy_count_dec( urb->pendp );
- urb->pendp->flags = ( urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE ) | ( ( toggle ^ 1 ) << 31 );
- uhci_claim_bandwidth( uhci, urb, FALSE );
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
+ while (pthis)
+ {
+ if ((((PTD_EXTENSION) pthis)->flags & UHCI_ITEM_FLAG_TYPE) != UHCI_ITEM_FLAG_TD)
+ {
+ ListNext(&urb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ continue;
+ }
+ else
+ {
+ ptde = (PTD_EXTENSION) pthis;
+ ptd = ptde->ptd;
+ ASSERT(ptd != NULL);
+
+ if (ptd->status & TD_CTRL_ACTIVE)
+ {
+ //still active
+ ret = FALSE;
+ break;
+ }
+ //let's see whether error occured
+ if ((ptd->status & TD_CTRL_ANY_ERROR) == 0)
+ {
+ urb->last_finished_td = pthis;
+ ListNext(&urb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ continue;
+ }
+ else
+ {
+ urb->status = ptd->status;
+ pthis = NULL;
+ continue;
+ }
+ }
+ }
-static NTSTATUS
-uhci_internal_submit_iso(
-PUHCI_DEV uhci,
-PURB urb
-)
-{
- PUHCI_TD ptd;
- LIST_ENTRY td_list, *pthis, *pnext;
- int i;
- BOOL toggle, ret;
- KIRQL old_irql;
-
- if( uhci == NULL || urb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- if( urb->iso_frame_count == 0 )
- return STATUS_INVALID_PARAMETER;
-
- lock_td_pool( &uhci->td_pool, TRUE );
-
- if( can_transfer( &uhci->td_pool, urb->iso_frame_count ) == FALSE )
- {
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
- }
-
- ptd = alloc_tds( &uhci->td_pool, urb->iso_frame_count );
- unlock_td_pool( &uhci->td_pool, TRUE );
-
- if( ptd == NULL )
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- InsertTailList( &ptd->ptde->vert_link, &td_list );
- ListFirst( &td_list, pthis );
-
- urb->td_count = urb->iso_frame_count;
-
- urb->pipe = ( ( ( ULONG )urb->iso_packet_desc[ 0 ].length ) << 21 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( ( ( ULONG )dev_from_endp( urb->pendp )->dev_addr ) << 8 )
- | ( ( ULONG )endp_dir( urb->pendp ) )
- | USB_ENDPOINT_XFER_ISOC;
-
-
- for( i = 0; i < urb->iso_frame_count && pthis; i++ )
- {
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
- uhci_fill_td( ptd,
- ( 3 << TD_CTRL_C_ERR_SHIFT )
- | ( TD_CTRL_ACTIVE )
- | ( TD_CTRL_IOS ),
- ( ( ( ULONG )urb->iso_packet_desc[ i ].length - 1 ) << 21 )
- | ( 0 << 19 )
- | ( ( ULONG )endp_num( urb->pendp ) << 15 )
- | ( ( ( ULONG )dev_from_endp( urb->pendp )->dev_addr ) << 8 )
- | ( ( urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN )
- ? USB_PID_OUT : USB_PID_IN ),
- MmGetPhysicalAddress( &urb->data_buffer[ urb->iso_packet_desc[ i ].offset ] ).LowPart );
-
- toggle ^= 1;
- ListNext( &td_list, pthis, pnext );
- pthis = pnext;
- }
-
- ptd->status |= TD_CTRL_IOC; //need interrupt
-
- ListFirst( &td_list, pthis );
- RemoveEntryList( &td_list );
-
- InsertTailList( pthis, &urb->trasac_list );
-
- //indirectly guarded by pending_endp_list_lock
- if( uhci_claim_bandwidth( uhci, urb, TRUE ) == FALSE )
- {
- //bad news: we can not allocate the enough bandwidth for the urb
- RemoveEntryList( &urb->trasac_list );
- InitializeListHead( &urb->trasac_list );
-
- lock_td_pool( &uhci->td_pool, TRUE );
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
- return STATUS_NO_MORE_ENTRIES;
-
- }
- usb_endp_busy_count_inc( urb->pendp );
- uhci_insert_urb_to_schedule( uhci, urb, ret );
- if( ret == FALSE )
- {
- usb_endp_busy_count_dec( urb->pendp );
- RemoveEntryList( &urb->trasac_list );
-
- lock_td_pool( &uhci->td_pool, TRUE );
- free_tds( &uhci->td_pool, ( ( PTD_EXTENSION )pthis )->ptd );
- unlock_td_pool( &uhci->td_pool, TRUE );
- uhci_claim_bandwidth( uhci, urb, FALSE );
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
+ if (pthis == NULL)
+ ret = TRUE;
-static BOOL
-uhci_is_xfer_finished(
-PURB urb
-)
-// runs in uhci_isr
-{
- PLIST_ENTRY pthis, pnext;
- PUHCI_TD ptd;
- PUHCI_QH pqh;
- BOOL ret;
- PTD_EXTENSION ptde;
-
- if( urb->last_finished_td == NULL )
- {
- urb->last_finished_td = &urb->trasac_list;
- }
-
- if( &urb->trasac_list == urb->last_finished_td )
- ListFirst( &urb->trasac_list, pthis )
- else
- ListNext( &urb->trasac_list, urb->last_finished_td, pthis );
-
- while( pthis )
- {
- if( ( ( ( PTD_EXTENSION )pthis )->flags & UHCI_ITEM_FLAG_TYPE )
- != UHCI_ITEM_FLAG_TD )
- {
- ListNext( &urb->trasac_list, pthis, pnext );
- pthis = pnext;
- continue;
- }
- else
- {
- ptde = ( PTD_EXTENSION )pthis;
- ptd = ptde->ptd;
- ASSERT( ptd != NULL );
-
- if( ptd->status & TD_CTRL_ACTIVE )
- {
- //still active
- ret = FALSE;
- break;
- }
- //let's see whether error occured
- if( ( ptd->status & TD_CTRL_ANY_ERROR ) == 0 )
- {
- urb->last_finished_td = pthis;
- ListNext( &urb->trasac_list, pthis, pnext );
- pthis = pnext;
- continue;
- }
- else
- {
- urb->status = ptd->status;
- pthis = NULL;
- continue;
- }
- }
-
- }
-
- if( pthis == NULL )
- ret = TRUE;
-
- return ret;
+ return ret;
}
-static BOOL
-uhci_remove_urb_from_schedule(
-PUHCI_DEV uhci,
-PURB urb
-)
// executed in isr, and have frame_list_lock acquired, so
// never try to acquire any spin-lock
// remove the bulk urb from schedule, and mark it not in
// the schedule
+static BOOL
+uhci_remove_urb_from_schedule(PUHCI_DEV uhci, PURB urb)
{
- BOOL ret = FALSE;
- {
- switch( urb->pipe & USB_ENDPOINT_XFERTYPE_MASK )
- {
- case USB_ENDPOINT_XFER_BULK:
- {
- ret = uhci_remove_bulk_from_schedule( uhci, urb );
- break;
- }
- case USB_ENDPOINT_XFER_CONTROL:
- {
- ret = uhci_remove_ctrl_from_schedule( uhci, urb );
- break;
- }
- case USB_ENDPOINT_XFER_INT:
- {
- ret = uhci_remove_int_from_schedule( uhci, urb );
- break;
- }
- case USB_ENDPOINT_XFER_ISOC:
- {
- ret = uhci_remove_iso_from_schedule( uhci, urb );
- break;
- }
- }
- }
- return ret;
+ BOOL ret = FALSE;
+ {
+ switch (urb->pipe & USB_ENDPOINT_XFERTYPE_MASK)
+ {
+ case USB_ENDPOINT_XFER_BULK:
+ {
+ ret = uhci_remove_bulk_from_schedule(uhci, urb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ ret = uhci_remove_ctrl_from_schedule(uhci, urb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
+ ret = uhci_remove_int_from_schedule(uhci, urb);
+ break;
+ }
+ case USB_ENDPOINT_XFER_ISOC:
+ {
+ ret = uhci_remove_iso_from_schedule(uhci, urb);
+ break;
+ }
+ }
+ }
+ return ret;
}
-static BOOL
-uhci_remove_bulk_from_schedule(
-PUHCI_DEV uhci,
-PURB urb
-)
// executed in isr, and have frame_list_lock acquired, so
// never try to acquire any spin-lock
// remove the bulk urb from schedule, and mark it not in
// the schedule
+static BOOL
+uhci_remove_bulk_from_schedule(PUHCI_DEV uhci, PURB urb)
{
- PUHCI_QH pqh, pnext_qh, pprev_qh;
- PLIST_ENTRY pthis, pnext, pprev;
- LONG i;
-
- if( uhci == NULL || urb == NULL )
- return FALSE;
-
- ListFirst( &urb->trasac_list, pthis );
- pqh = ( ( PQH_EXTENSION )pthis )->pqh;
-
- ListFirst( &pqh->pqhe->hori_link, pnext );
- ListFirstPrev( &pqh->pqhe->hori_link, pprev );
-
- if( pprev == NULL || pnext == NULL )
- return FALSE;
-
- pnext_qh = struct_ptr( pnext, QH_EXTENSION, hori_link )->pqh;
- pprev_qh = struct_ptr( pprev, QH_EXTENSION, hori_link )->pqh;
-
- if( pprev != pnext )
- {
- //not the last one
- pprev_qh->link = pnext_qh->phy_addr;
- }
- else
- {
- //only two qhs in the list
- for( i = 0; i < UHCI_MAX_SKELQHS; i++ )
- {
- if( pprev_qh == uhci->skel_qh[ i ] )
- {
- break;
- }
- }
- ASSERT( i < UHCI_MAX_SKELQHS - 1 );
- pprev_qh->link = uhci->skel_qh[ i + 1 ]->phy_addr;
- }
- RemoveEntryList( &pqh->pqhe->hori_link );
-
- urb->flags &= ~URB_FLAG_IN_SCHEDULE;
-
- if( ( urb->pipe & USB_DEV_FLAG_LOW_SPEED ) == 0 )
- uhci_drop_fsbr( uhci );
-
- return TRUE;
+ PUHCI_QH pqh, pnext_qh, pprev_qh;
+ PLIST_ENTRY pthis, pnext, pprev;
+ LONG i;
+
+ if (uhci == NULL || urb == NULL)
+ return FALSE;
+
+ ListFirst(&urb->trasac_list, pthis);
+ pqh = ((PQH_EXTENSION) pthis)->pqh;
+
+ ListFirst(&pqh->pqhe->hori_link, pnext);
+ ListFirstPrev(&pqh->pqhe->hori_link, pprev);
+
+ if (pprev == NULL || pnext == NULL)
+ return FALSE;
+
+ pnext_qh = struct_ptr(pnext, QH_EXTENSION, hori_link)->pqh;
+ pprev_qh = struct_ptr(pprev, QH_EXTENSION, hori_link)->pqh;
+
+ if (pprev != pnext)
+ {
+ //not the last one
+ pprev_qh->link = pnext_qh->phy_addr;
+ }
+ else
+ {
+ //only two qhs in the list
+ for(i = 0; i < UHCI_MAX_SKELQHS; i++)
+ {
+ if (pprev_qh == uhci->skel_qh[i])
+ {
+ break;
+ }
+ }
+ ASSERT(i < UHCI_MAX_SKELQHS - 1);
+ pprev_qh->link = uhci->skel_qh[i + 1]->phy_addr;
+ }
+ RemoveEntryList(&pqh->pqhe->hori_link);
+
+ urb->flags &= ~URB_FLAG_IN_SCHEDULE;
+
+ if ((urb->pipe & USB_DEV_FLAG_LOW_SPEED) == 0)
+ uhci_drop_fsbr(uhci);
+
+ return TRUE;
}
static BOOL
-uhci_remove_iso_from_schedule(
-PUHCI_DEV uhci,
-PURB urb
-)
+uhci_remove_iso_from_schedule(PUHCI_DEV uhci, PURB urb)
{
- PUHCI_TD ptd, pnext_td, pprev_td;
- PLIST_ENTRY pthis, pnext, pprev;
- int i, idx;
+ PUHCI_TD ptd, pnext_td, pprev_td;
+ PLIST_ENTRY pthis, pnext, pprev;
+ int i, idx;
- if( uhci == NULL || urb == NULL )
- return FALSE;
+ if (uhci == NULL || urb == NULL)
+ return FALSE;
- ListFirst( &urb->trasac_list, pthis );
+ ListFirst(&urb->trasac_list, pthis);
- for( i = 0; i < urb->iso_frame_count && pthis; i++ )
- {
- ptd = ( ( PTD_EXTENSION )pthis )->ptd;
- idx = ( urb->iso_start_frame + i ) & ( UHCI_MAX_FRAMES - 1 );
+ for(i = 0; i < urb->iso_frame_count && pthis; i++)
+ {
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ idx = (urb->iso_start_frame + i) & (UHCI_MAX_FRAMES - 1);
- ListFirstPrev( &ptd->ptde->hori_link, pprev );
+ ListFirstPrev(&ptd->ptde->hori_link, pprev);
- if( pprev == NULL )
- return FALSE;
+ if (pprev == NULL)
+ return FALSE;
- if( pprev == &uhci->frame_list_cpu[ idx ].td_link )
- {
- uhci->frame_list[ idx ] = ptd->link;
- }
+ if (pprev == &uhci->frame_list_cpu[idx].td_link)
+ {
+ uhci->frame_list[idx] = ptd->link;
+ }
else
- {
- pprev_td = struct_ptr( pprev, TD_EXTENSION, hori_link )->ptd;
- pprev_td->link = ptd->link;
- }
-
- RemoveEntryList( &ptd->ptde->hori_link );
- ListNext( &urb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
-
- urb->flags &= ~URB_FLAG_IN_SCHEDULE;
- return TRUE;
+ {
+ pprev_td = struct_ptr(pprev, TD_EXTENSION, hori_link)->ptd;
+ pprev_td->link = ptd->link;
+ }
+
+ RemoveEntryList(&ptd->ptde->hori_link);
+ ListNext(&urb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+
+ urb->flags &= ~URB_FLAG_IN_SCHEDULE;
+ return TRUE;
}
static BOOL
-uhci_remove_int_from_schedule(
-PUHCI_DEV uhci,
-PURB urb
-)
+uhci_remove_int_from_schedule(PUHCI_DEV uhci, PURB urb)
{
- PUHCI_TD ptd, pnext_td, pprev_td;
- PLIST_ENTRY pthis, pnext, pprev;
- LONG i;
-
- if( uhci == NULL || urb == NULL )
- return FALSE;
-
- ListFirst( &urb->trasac_list, pthis );
- ptd = ( ( PTD_EXTENSION )pthis )->ptd;
- ListFirst( &ptd->ptde->hori_link, pnext );
- ListFirstPrev( &ptd->ptde->hori_link, pprev );
-
- if( pprev == NULL || pnext == NULL )
- return FALSE;
-
- pnext_td = struct_ptr( pnext, TD_EXTENSION, hori_link )->ptd;
- pprev_td = struct_ptr( pprev, TD_EXTENSION, hori_link )->ptd;
-
- if( pprev_td != pnext_td )
- pprev_td->link = pnext_td->phy_addr;
- else
- {
- //the last one
- for( i = UHCI_MAX_SKELTDS - 2; i >= 0; i-- )
- {
- //UHCI_MAX_SKELTDS -1 skel tds for int transfer
- if( pprev_td == uhci->skel_td[ i ] )
- break;
- }
-
- ASSERT( i >= 0 );
- if( i == 0 )
- {
- pprev_td->link = uhci->skel_qh[ 0 ]->phy_addr;
- }
- else
- {
- pprev_td->link = uhci->skel_td[ i - 1 ]->phy_addr;
- }
- }
- RemoveEntryList( &ptd->ptde->hori_link );
-
- urb->flags &= ~URB_FLAG_IN_SCHEDULE;
- return TRUE;
+ PUHCI_TD ptd, pnext_td, pprev_td;
+ PLIST_ENTRY pthis, pnext, pprev;
+ LONG i;
+
+ if (uhci == NULL || urb == NULL)
+ return FALSE;
+
+ ListFirst(&urb->trasac_list, pthis);
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ ListFirst(&ptd->ptde->hori_link, pnext);
+ ListFirstPrev(&ptd->ptde->hori_link, pprev);
+
+ if (pprev == NULL || pnext == NULL)
+ return FALSE;
+
+ pnext_td = struct_ptr(pnext, TD_EXTENSION, hori_link)->ptd;
+ pprev_td = struct_ptr(pprev, TD_EXTENSION, hori_link)->ptd;
+
+ if (pprev_td != pnext_td)
+ pprev_td->link = pnext_td->phy_addr;
+ else
+ {
+ //the last one
+ for(i = UHCI_MAX_SKELTDS - 2; i >= 0; i--)
+ {
+ //UHCI_MAX_SKELTDS -1 skel tds for int transfer
+ if (pprev_td == uhci->skel_td[i])
+ break;
+ }
+
+ ASSERT(i >= 0);
+ if (i == 0)
+ {
+ pprev_td->link = uhci->skel_qh[0]->phy_addr;
+ }
+ else
+ {
+ pprev_td->link = uhci->skel_td[i - 1]->phy_addr;
+ }
+ }
+ RemoveEntryList(&ptd->ptde->hori_link);
+
+ urb->flags &= ~URB_FLAG_IN_SCHEDULE;
+ return TRUE;
}
static BOOL
-uhci_insert_tds_qh(
-PUHCI_QH pqh,
-PUHCI_TD td_chain
-)
+uhci_insert_tds_qh(PUHCI_QH pqh, PUHCI_TD td_chain)
{
- if( pqh == NULL || td_chain == NULL )
- return FALSE;
+ if (pqh == NULL || td_chain == NULL)
+ return FALSE;
- InsertTailList( &td_chain->ptde->vert_link, &pqh->pqhe->vert_link );
- pqh->element = td_chain->phy_addr;
- return TRUE;
+ InsertTailList(&td_chain->ptde->vert_link, &pqh->pqhe->vert_link);
+ pqh->element = td_chain->phy_addr;
+ return TRUE;
}
static BOOL
-uhci_insert_qh_urb(
-PURB urb,
-PUHCI_QH qh_chain
-)
+uhci_insert_qh_urb(PURB urb, PUHCI_QH qh_chain)
{
- if( urb == NULL || qh_chain == NULL )
- return FALSE;
+ if (urb == NULL || qh_chain == NULL)
+ return FALSE;
- InsertTailList( &qh_chain->pqhe->vert_link, &urb->trasac_list );
- qh_chain->pqhe->purb = urb;
- return TRUE;
+ InsertTailList(&qh_chain->pqhe->vert_link, &urb->trasac_list);
+ qh_chain->pqhe->purb = urb;
+ return TRUE;
}
-static BOOL
-uhci_insert_urb_schedule(
-PUHCI_DEV uhci,
-PURB urb
-)
// must have dev_lock and frame_list_lock acquired
+static BOOL
+uhci_insert_urb_schedule(PUHCI_DEV uhci, PURB urb)
{
- PUHCI_QH pqh, pskel_qh, pnext_qh;
- PUHCI_TD ptd, plast_td;
- PLIST_ENTRY pthis, pnext;
- int i;
-
- if( uhci == NULL || urb == NULL )
- return FALSE;
-
- ListFirst( &urb->trasac_list, pthis );
- if( pthis == NULL )
- return FALSE;
-
- InsertTailList( &uhci->urb_list, ( PLIST_ENTRY )urb );
+ PUHCI_QH pqh, pskel_qh, pnext_qh;
+ PUHCI_TD ptd, plast_td;
+ PLIST_ENTRY pthis, pnext;
+ int i;
- urb->flags &= ~URB_FLAG_STATE_MASK;
- urb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE;
+ if (uhci == NULL || urb == NULL)
+ return FALSE;
+ ListFirst(&urb->trasac_list, pthis);
+ if (pthis == NULL)
+ return FALSE;
- switch( endp_type( urb->pendp ) )
- {
- case USB_ENDPOINT_XFER_CONTROL:
- {
- pqh = ( ( PQH_EXTENSION )pthis )->pqh;
+ InsertTailList(&uhci->urb_list, (PLIST_ENTRY) urb);
- if( ( dev_from_endp( urb->pendp )->flags & USB_DEV_FLAG_LOW_SPEED ) == 0 )
- {
- pskel_qh = uhci->skel_hs_control_qh;
- pnext_qh = uhci->skel_bulk_qh;
- }
- else
- {
- pskel_qh = uhci->skel_ls_control_qh;
- pnext_qh = uhci->skel_hs_control_qh;
- }
+ urb->flags &= ~URB_FLAG_STATE_MASK;
+ urb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE;
- ListFirstPrev( &pskel_qh->pqhe->hori_link,
- pthis );
- if( pthis == NULL )
- pthis = &pskel_qh->pqhe->hori_link;
+ switch (endp_type(urb->pendp))
+ {
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ pqh = ((PQH_EXTENSION) pthis)->pqh;
+
+ if ((dev_from_endp(urb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) == 0)
+ {
+ pskel_qh = uhci->skel_hs_control_qh;
+ pnext_qh = uhci->skel_bulk_qh;
+ }
+ else
+ {
+ pskel_qh = uhci->skel_ls_control_qh;
+ pnext_qh = uhci->skel_hs_control_qh;
+ }
+
+ ListFirstPrev(&pskel_qh->pqhe->hori_link, pthis);
+
+ if (pthis == NULL)
+ pthis = &pskel_qh->pqhe->hori_link;
+
+ InsertTailList(&pskel_qh->pqhe->hori_link, &pqh->pqhe->hori_link);
+ pqh->link = pnext_qh->phy_addr;
+ struct_ptr(pthis, QH_EXTENSION, hori_link)->pqh->link = pqh->phy_addr;
- InsertTailList( &pskel_qh->pqhe->hori_link, &pqh->pqhe->hori_link );
- pqh->link = pnext_qh->phy_addr;
- struct_ptr( pthis, QH_EXTENSION, hori_link )->pqh->link = pqh->phy_addr;
+ //full speed band reclaimation
+ if ((urb->pipe & USB_DEV_FLAG_LOW_SPEED) == 0)
+ {
+ uhci->fsbr_cnt++;
+ if (uhci->fsbr_cnt == 1)
+ {
+ uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr;
+ }
+ }
+ return TRUE;
+ }
+ case USB_ENDPOINT_XFER_BULK:
+ {
+ pqh = ((PQH_EXTENSION) pthis)->pqh;
+
+ ListFirstPrev(&uhci->skel_bulk_qh->pqhe->hori_link, pthis);
+
+ if (pthis == NULL)
+ pthis = &uhci->skel_bulk_qh->pqhe->hori_link;
+
+ InsertTailList(&uhci->skel_bulk_qh->pqhe->hori_link, &pqh->pqhe->hori_link);
+
+ pqh->link = uhci->skel_term_qh->phy_addr;
+ struct_ptr(pthis, QH_EXTENSION, hori_link)->pqh->link = pqh->phy_addr;
//full speed band reclaimation
- if( ( urb->pipe & USB_DEV_FLAG_LOW_SPEED ) == 0 )
- {
- uhci->fsbr_cnt++;
- if( uhci->fsbr_cnt == 1 )
- {
- uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr;
- }
- }
- return TRUE;
- }
- case USB_ENDPOINT_XFER_BULK:
- {
- pqh = ( ( PQH_EXTENSION )pthis )->pqh;
-
- ListFirstPrev( &uhci->skel_bulk_qh->pqhe->hori_link,
- pthis );
-
- if( pthis == NULL )
- pthis = &uhci->skel_bulk_qh->pqhe->hori_link;
-
- InsertTailList( &uhci->skel_bulk_qh->pqhe->hori_link,
- &pqh->pqhe->hori_link );
-
- pqh->link = uhci->skel_term_qh->phy_addr;
- struct_ptr( pthis, QH_EXTENSION, hori_link )->pqh->link =
- pqh->phy_addr;
-
- //full speed band reclaimation
- uhci->fsbr_cnt++;
- if( uhci->fsbr_cnt == 1 )
- {
- uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr;;
- }
-
- return TRUE;
- }
- case USB_ENDPOINT_XFER_INT:
- {
+ uhci->fsbr_cnt++;
+ if (uhci->fsbr_cnt == 1)
+ {
+ uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr;;
+ }
+
+ return TRUE;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
//bandwidth claim is done outside
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
-
- get_int_idx( urb, i );
-
- ListFirstPrev( &uhci->skel_td[ i ]->ptde->hori_link, pthis );
- if( pthis == NULL )
- pthis = &uhci->skel_td[ i ]->ptde->hori_link;
-
- InsertTailList( &uhci->skel_td[ i ]->ptde->hori_link, &ptd->ptde->hori_link );
-
- if( i > 0 )
- {
- ptd->link = uhci->skel_td[ i - 1 ]->phy_addr;
- }
- else if( i == 0 )
- {
- ptd->link = uhci->skel_qh[ 0 ]->phy_addr;
- }
- //finally link the previous td to this td
- struct_ptr( pthis, TD_EXTENSION, hori_link )->ptd->link = ptd->phy_addr;
- return TRUE;
- }
- case USB_ENDPOINT_XFER_ISOC:
- {
-
- for( i = 0; i < urb->iso_frame_count; i++ )
- {
- ptd = ( ( PTD_EXTENSION ) pthis )->ptd;
- InsertTailList( &uhci->frame_list_cpu[ ( urb->iso_start_frame + i ) & 0x3ff ].td_link,
- &ptd->ptde->hori_link );
-
- if( IsListEmpty( &uhci->frame_list_cpu[ ( urb->iso_start_frame + i ) & 0x3ff ].td_link ) == TRUE )
- {
- ptd->link = uhci->frame_list[ ( urb->iso_start_frame + i ) & 0x3ff ];
- uhci->frame_list[ i ] = ptd->phy_addr;
- }
- else
- {
- ListFirstPrev( &uhci->frame_list_cpu[ ( urb->iso_start_frame + i ) & 0x3ff ].td_link, pnext );
- plast_td = struct_ptr( pnext, TD_EXTENSION, hori_link )->ptd;
- ptd->link = plast_td->link;
- plast_td->link = ptd->phy_addr;
- }
-
- ListNext( &urb->trasac_list, pthis, pnext );
- pthis = pnext;
- }
- return TRUE;
-
- }
- }
- return FALSE;
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+
+ get_int_idx(urb, i);
+
+ ListFirstPrev(&uhci->skel_td[i]->ptde->hori_link, pthis);
+ if (pthis == NULL)
+ pthis = &uhci->skel_td[i]->ptde->hori_link;
+
+ InsertTailList(&uhci->skel_td[i]->ptde->hori_link, &ptd->ptde->hori_link);
+
+ if (i > 0)
+ {
+ ptd->link = uhci->skel_td[i - 1]->phy_addr;
+ }
+ else if (i == 0)
+ {
+ ptd->link = uhci->skel_qh[0]->phy_addr;
+ }
+ //finally link the previous td to this td
+ struct_ptr(pthis, TD_EXTENSION, hori_link)->ptd->link = ptd->phy_addr;
+ return TRUE;
+ }
+ case USB_ENDPOINT_XFER_ISOC:
+ {
+
+ for(i = 0; i < urb->iso_frame_count; i++)
+ {
+ ptd = ((PTD_EXTENSION) pthis)->ptd;
+ InsertTailList(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link,
+ &ptd->ptde->hori_link);
+
+ if (IsListEmpty(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link) == TRUE)
+ {
+ ptd->link = uhci->frame_list[(urb->iso_start_frame + i) & 0x3ff];
+ uhci->frame_list[i] = ptd->phy_addr;
+ }
+ else
+ {
+ ListFirstPrev(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link, pnext);
+ plast_td = struct_ptr(pnext, TD_EXTENSION, hori_link)->ptd;
+ ptd->link = plast_td->link;
+ plast_td->link = ptd->phy_addr;
+ }
+
+ ListNext(&urb->trasac_list, pthis, pnext);
+ pthis = pnext;
+ }
+ return TRUE;
+
+ }
+ }
+ return FALSE;
}
-BOOLEAN
-uhci_sync_insert_urb_schedule(
-PVOID context
-)
//this function used as the KeSynchronizeExecution param to delegate control to uhci_insert_urb_schedule
-{
- PSYNC_PARAM sync_param;
- PUHCI_DEV uhci;
- PURB purb;
+BOOLEAN
+uhci_sync_insert_urb_schedule(PVOID context)
+{
+ PSYNC_PARAM sync_param;
+ PUHCI_DEV uhci;
+ PURB purb;
- sync_param = ( PSYNC_PARAM ) context;
- if( sync_param == NULL )
- return FALSE;
+ sync_param = (PSYNC_PARAM) context;
+ if (sync_param == NULL)
+ return FALSE;
- uhci = sync_param->uhci;
- purb = ( PURB )sync_param->context;
+ uhci = sync_param->uhci;
+ purb = (PURB) sync_param->context;
- if( uhci == NULL || purb == NULL )
- return ( UCHAR )sync_param->ret = FALSE;
+ if (uhci == NULL || purb == NULL)
+ return (UCHAR) sync_param->ret = FALSE;
- return ( UCHAR )( sync_param->ret = uhci_insert_urb_schedule( uhci, purb ) );
+ return (UCHAR) (sync_param->ret = uhci_insert_urb_schedule(uhci, purb));
}
+// be sure pending_endp_list_lock acquired
static BOOL
-uhci_claim_bandwidth(
-PUHCI_DEV uhci,
-PURB urb,
-BOOL claim_bw //true to claim band-width, false to free band-width
-)
-// be sure pending_endp_list_lock acuqired
+uhci_claim_bandwidth(PUHCI_DEV uhci,
+ PURB urb,
+ BOOL claim_bw //true to claim bandwidth, false to free bandwidth
+ )
{
- UCHAR type;
- BOOL ls, can_alloc;
- LONG bus_time, us;
- LONG i, idx, j, start_frame, interval;
-
- if( urb == NULL )
- return FALSE;
-
- can_alloc = TRUE;
-
- type = ( UCHAR )( urb->pipe & USB_ENDPOINT_XFERTYPE_MASK );
- if( type == USB_ENDPOINT_XFER_BULK || type == USB_ENDPOINT_XFER_CONTROL )
- {
- return FALSE;
- }
-
- ls = ( urb->pipe & USB_DEV_FLAG_LOW_SPEED )
- ? TRUE : FALSE;
-
- if( type == USB_ENDPOINT_XFER_INT )
- {
- start_frame = 0;
- i = urb->data_length;
- bus_time = usb_calc_bus_time( ls, FALSE, FALSE, i );
- us = ns_to_us( bus_time );
-
- i = ( urb->pipe >> 24 ); //polling interval
-
- for( interval = 0, j = 0; j < 8; j++ )
- {
- if( i & ( 1 << j ) )
- {
- interval = j;
- }
- }
-
- interval = 1 << interval;
- start_frame = interval - 1;
-
- if( claim_bw )
- {
-
- for( idx = 0; idx < UHCI_MAX_FRAMES; idx += interval )
- {
- if( uhci->frame_bw[ idx ] < us )
- {
- can_alloc = FALSE;
- break;
- }
- }
-
- if( !can_alloc )
- {
- return FALSE;
- }
-
- for( idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval )
- {
- uhci->frame_bw[ idx ] -= us;
- }
- }
- else
- {
- for( idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval )
- {
- uhci->frame_bw[ idx ] += us;
- }
- }
+ UCHAR type;
+ BOOL ls, can_alloc;
+ LONG bus_time, us;
+ LONG i, idx, j, start_frame, interval;
+
+ if (urb == NULL)
+ return FALSE;
+
+ can_alloc = TRUE;
+
+ type = (UCHAR) (urb->pipe & USB_ENDPOINT_XFERTYPE_MASK);
+ if (type == USB_ENDPOINT_XFER_BULK || type == USB_ENDPOINT_XFER_CONTROL)
+ {
+ return FALSE;
+ }
+
+ ls = (urb->pipe & USB_DEV_FLAG_LOW_SPEED) ? TRUE : FALSE;
+
+ if (type == USB_ENDPOINT_XFER_INT)
+ {
+ start_frame = 0;
+ i = urb->data_length;
+ bus_time = usb_calc_bus_time(ls, FALSE, FALSE, i);
+ us = ns_to_us(bus_time);
+
+ i = (urb->pipe >> 24); //polling interval
+
+ for(interval = 0, j = 0; j < 8; j++)
+ {
+ if (i & (1 << j))
+ {
+ interval = j;
+ }
+ }
+
+ interval = 1 << interval;
+ start_frame = interval - 1;
+
+ if (claim_bw)
+ {
+
+ for(idx = 0; idx < UHCI_MAX_FRAMES; idx += interval)
+ {
+ if (uhci->frame_bw[idx] < us)
+ {
+ can_alloc = FALSE;
+ break;
+ }
+ }
+
+ if (!can_alloc)
+ {
+ return FALSE;
+ }
+
+ for(idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval)
+ {
+ uhci->frame_bw[idx] -= us;
+ }
+ }
+ else
+ {
+ for(idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval)
+ {
+ uhci->frame_bw[idx] += us;
+ }
+ }
+
+ }
+ else if (type == USB_ENDPOINT_XFER_ISOC)
+ {
+ if (claim_bw)
+ {
+ for(i = 0; i < urb->iso_frame_count; i++)
+ {
+ bus_time = usb_calc_bus_time(FALSE,
+ (urb->pipe & USB_DIR_IN)
+ ? TRUE : FALSE, TRUE, urb->iso_packet_desc[i].length);
+
+ urb->iso_packet_desc[i].bus_time = ns_to_us(bus_time);
+ }
+
+ for(i = 0; i < urb->iso_frame_count; i++)
+ {
+ if (uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] < urb->iso_packet_desc[i].bus_time)
+ {
+ can_alloc = FALSE;
+ break;
+ }
+ }
+
+ if (!can_alloc)
+ {
+ return FALSE;
+ }
+
+ for(i = 0; i < urb->iso_frame_count; i++)
+ {
+ uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] -= urb->iso_packet_desc[i].bus_time;
+ }
+ }
+ else
+ {
+ for(i = 0; i < urb->iso_frame_count; i++)
+ {
+ uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] += urb->iso_packet_desc[i].bus_time;
+ }
+ }
}
- else if( type == USB_ENDPOINT_XFER_ISOC )
- {
- if( claim_bw )
- {
- for( i = 0; i < urb->iso_frame_count; i++ )
- {
- bus_time = usb_calc_bus_time(
- FALSE,
- ( urb->pipe & USB_DIR_IN )
- ? TRUE : FALSE,
- TRUE,
- urb->iso_packet_desc[ i ].length );
-
- urb->iso_packet_desc[ i ].bus_time = ns_to_us( bus_time );
- }
-
- for( i = 0; i < urb->iso_frame_count ; i++ )
- {
- if( uhci->frame_bw[ ( urb->iso_start_frame + i ) & 0x3ff ]
- < urb->iso_packet_desc[ i ].bus_time )
- {
- can_alloc = FALSE;
- break;
- }
- }
-
- if( !can_alloc )
- {
- return FALSE;
- }
-
- for( i = 0; i < urb->iso_frame_count ; i++ )
- {
- uhci->frame_bw[ ( urb->iso_start_frame + i ) & 0x3ff ]
- -= urb->iso_packet_desc[ i ].bus_time;
- }
- }
- else
- {
- for( i = 0; i < urb->iso_frame_count ; i++ )
- {
- uhci->frame_bw[ ( urb->iso_start_frame + i ) & 0x3ff ]
- += urb->iso_packet_desc[ i ].bus_time;
- }
- }
-
- }
-
- return TRUE;
+
+ return TRUE;
}
+//cancel a single urb
BOOLEAN
-uhci_sync_cancel_urb(
-PVOID context
-)
+uhci_sync_cancel_urb(PVOID context)
{
- //cancel a single urb
- PUHCI_DEV uhci;
- PSYNC_PARAM sync_param;
- PURB purb2, dest_urb;
- PLIST_ENTRY pthis, pnext;
- BOOL found = FALSE;
-
- if( context == NULL )
- return FALSE;
-
- sync_param = ( PSYNC_PARAM )context;
- uhci = sync_param->uhci;
- dest_urb = ( PURB )sync_param->context;
-
- if( uhci == NULL || dest_urb == NULL )
- return ( UCHAR )sync_param->ret = FALSE;
-
- ListFirst( &uhci->urb_list, pthis );
- while( pthis )
- {
- purb2 = ( PURB ) pthis;
- if( purb2 == dest_urb )
- {
- found = TRUE;
- purb2->flags |= URB_FLAG_FORCE_CANCEL;
- break;
- }
- ListNext( &uhci->urb_list, pthis, pnext );
- pthis = pnext;
- }
- if( found )
- uhci->skel_term_td->status |= TD_CTRL_IOC;
-
- return ( UCHAR )( sync_param->ret = found );
+ PUHCI_DEV uhci;
+ PSYNC_PARAM sync_param;
+ PURB purb2, dest_urb;
+ PLIST_ENTRY pthis, pnext;
+ BOOL found = FALSE;
+ if (context == NULL)
+ return FALSE;
+
+ sync_param = (PSYNC_PARAM) context;
+ uhci = sync_param->uhci;
+ dest_urb = (PURB) sync_param->context;
+
+ if (uhci == NULL || dest_urb == NULL)
+ return (UCHAR) sync_param->ret = FALSE;
+
+ ListFirst(&uhci->urb_list, pthis);
+ while (pthis)
+ {
+ purb2 = (PURB) pthis;
+ if (purb2 == dest_urb)
+ {
+ found = TRUE;
+ purb2->flags |= URB_FLAG_FORCE_CANCEL;
+ break;
+ }
+ ListNext(&uhci->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+ if (found)
+ uhci->skel_term_td->status |= TD_CTRL_IOC;
+
+ return (UCHAR) (sync_param->ret = found);
}
-NTSTATUS
-uhci_cancel_urb(
-PUHCI_DEV uhci,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
//note any fields of the purb can not be referenced unless it is found in some queue
+NTSTATUS
+uhci_cancel_urb(PUHCI_DEV uhci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- NTSTATUS status;
- PLIST_ENTRY pthis, pnext;
- BOOL found;
- PURB purb2;
-
- SYNC_PARAM sync_param;
-
- USE_IRQL;
-
- if( uhci == NULL || purb == NULL || pdev == NULL || pendp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- lock_dev( pdev, FALSE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- //delegate to remove device for this job
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- if( dev_from_endp( pendp ) != pdev )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_INVALID_PARAMETER;
- }
-
- if( endp_state( pendp ) == USB_ENDP_FLAG_STALL )
- {
- //it will be canceled in uhci_process_pending_endp
- unlock_dev( pdev, FALSE );
- return USB_STATUS_ENDPOINT_HALTED;
- }
-
- found = FALSE;
- ListFirst( &pendp->urb_list, pthis );
- while( pthis )
- {
- purb2 = ( PURB ) pthis;
- if( purb2 == purb )
- {
- found = TRUE;
- RemoveEntryList( pthis );
- InitializeListHead( pthis );
- break;
- }
- ListNext( &pendp->urb_list, pthis, pnext );
- pthis = pnext;
- }
- unlock_dev( pdev, FALSE );
-
- if( found )
- {
- purb->status = STATUS_CANCELLED;
-
- uhci_generic_urb_completion( purb, purb->context );
-
- lock_dev( pdev, FALSE );
- pdev->ref_count --;
- unlock_dev( pdev, FALSE );
- return STATUS_SUCCESS;
- }
-
- // search the urb in the urb-list and try to cancel
- sync_param.uhci = uhci;
- sync_param.context = purb;
-
- KeSynchronizeExecution( uhci->pdev_ext->uhci_int, uhci_sync_cancel_urb, &sync_param );
-
- found = sync_param.ret;
-
- if( found )
- return USB_STATUS_CANCELING;
-
- return STATUS_INVALID_PARAMETER;
+ NTSTATUS status;
+ PLIST_ENTRY pthis, pnext;
+ BOOL found;
+ PURB purb2;
+
+ SYNC_PARAM sync_param;
+
+ USE_IRQL;
+
+ if (uhci == NULL || purb == NULL || pdev == NULL || pendp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_dev(pdev, FALSE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ //delegate to remove device for this job
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ if (dev_from_endp(pendp) != pdev)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
+ {
+ //it will be canceled in uhci_process_pending_endp
+ unlock_dev(pdev, FALSE);
+ return USB_STATUS_ENDPOINT_HALTED;
+ }
+
+ found = FALSE;
+ ListFirst(&pendp->urb_list, pthis);
+ while (pthis)
+ {
+ purb2 = (PURB) pthis;
+ if (purb2 == purb)
+ {
+ found = TRUE;
+ RemoveEntryList(pthis);
+ InitializeListHead(pthis);
+ break;
+ }
+ ListNext(&pendp->urb_list, pthis, pnext);
+ pthis = pnext;
+ }
+ unlock_dev(pdev, FALSE);
+
+ if (found)
+ {
+ purb->status = STATUS_CANCELLED;
+
+ uhci_generic_urb_completion(purb, purb->context);
+
+ lock_dev(pdev, FALSE);
+ pdev->ref_count--;
+ unlock_dev(pdev, FALSE);
+ return STATUS_SUCCESS;
+ }
+
+ // search the urb in the urb-list and try to cancel
+ sync_param.uhci = uhci;
+ sync_param.context = purb;
+
+ KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_cancel_urb, &sync_param);
+
+ found = sync_param.ret;
+
+ if (found)
+ return USB_STATUS_CANCELING;
+
+ return STATUS_INVALID_PARAMETER;
}
VOID
-uhci_generic_urb_completion(
-PURB purb,
-PVOID context
-)
+uhci_generic_urb_completion(PURB purb, PVOID context)
{
- PUSB_DEV pdev;
- KIRQL cur_irql;
- USE_IRQL;
-
- old_irql = KeGetCurrentIrql();
- if( old_irql > DISPATCH_LEVEL )
- TRAP();
-
- if( old_irql < DISPATCH_LEVEL )
- KeRaiseIrql(DISPATCH_LEVEL, &old_irql);
-
- pdev = purb->pdev;
- if( purb == NULL )
- return;
-
- if( pdev == NULL )
- return;
-
- lock_dev( pdev, TRUE );
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- goto LBL_CLIENT_PROCESS;
- }
- if( usb_error( purb->status ) )
- {
- pdev->error_count++;
- }
-
- if( purb->pendp == &pdev->default_endp )
- {
- if( usb_halted( purb->status ) )
- {
- pdev->time_out_count++;
- if( pdev->time_out_count > 3 )
- {
- dev_set_state( pdev, USB_DEV_STATE_ZOMB );
- uhci_dbg_print( DBGLVL_MAXIMUM, ("uhci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n", pdev ) );
- }
- }
- else
- pdev->time_out_count = 0;
-
- }
- unlock_dev( pdev, TRUE );
-
- LBL_CLIENT_PROCESS:
- if( purb->completion )
- purb->completion( purb, context );
-
- if( old_irql < DISPATCH_LEVEL )
- KeLowerIrql( old_irql );
-
- return;
+ PUSB_DEV pdev;
+ KIRQL cur_irql;
+ USE_IRQL;
+
+ old_irql = KeGetCurrentIrql();
+ if (old_irql > DISPATCH_LEVEL)
+ TRAP();
+
+ if (old_irql < DISPATCH_LEVEL)
+ KeRaiseIrql(DISPATCH_LEVEL, &old_irql);
+
+ pdev = purb->pdev;
+ if (purb == NULL)
+ return;
+
+ if (pdev == NULL)
+ return;
+
+ lock_dev(pdev, TRUE);
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ goto LBL_CLIENT_PROCESS;
+ }
+ if (usb_error(purb->status))
+ {
+ pdev->error_count++;
+ }
+
+ if (purb->pendp == &pdev->default_endp)
+ {
+ if (usb_halted(purb->status))
+ {
+ pdev->time_out_count++;
+ if (pdev->time_out_count > 3)
+ {
+ dev_set_state(pdev, USB_DEV_STATE_ZOMB);
+ uhci_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
+ pdev));
+ }
+ }
+ else
+ pdev->time_out_count = 0;
+
+ }
+ unlock_dev(pdev, TRUE);
+
+ LBL_CLIENT_PROCESS:
+ if (purb->completion)
+ purb->completion(purb, context);
+
+ if (old_irql < DISPATCH_LEVEL)
+ KeLowerIrql(old_irql);
+
+ return;
}
NTSTATUS
-uhci_rh_submit_urb(
-PUSB_DEV pdev,
-PURB purb
-)
+uhci_rh_submit_urb(PUSB_DEV pdev, PURB purb)
{
- PUSB_DEV_MANAGER dev_mgr;
- PTIMER_SVC ptimer;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUHCI_DEV uhci;
- NTSTATUS status;
+ PUSB_DEV_MANAGER dev_mgr;
+ PTIMER_SVC ptimer;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUHCI_DEV uhci;
+ NTSTATUS status;
#ifndef INCLUDE_EHCI
- PHUB_EXTENSION hub_ext;
+ PHUB_EXTENSION hub_ext;
#else
- PHUB2_EXTENSION hub_ext;
+ PHUB2_EXTENSION hub_ext;
#endif
- PUSB_PORT_STATUS ps, psret;
- LONG i;
-
- USE_IRQL;
- if( pdev == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- dev_mgr = dev_mgr_from_dev( pdev );
-
- KeAcquireSpinLock( &dev_mgr->timer_svc_list_lock, &old_irql );
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- uhci = uhci_from_hcd( pdev->hcd );
- psetup = ( PUSB_CTRL_SETUP_PACKET ) purb->setup_packet;
+ PUSB_PORT_STATUS ps, psret;
+ LONG i;
+
+ USE_IRQL;
+ if (pdev == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+
+ KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ uhci = uhci_from_hcd(pdev->hcd);
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
#ifndef INCLUDE_EHCI
- hub_ext = ( ( PHUB_EXTENSION )pdev->dev_ext );
+ hub_ext = ((PHUB_EXTENSION) pdev->dev_ext);
#else
- hub_ext = ( ( PHUB2_EXTENSION )pdev->dev_ext );
+ hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext);
#endif
-
- switch( endp_type( purb->pendp ) )
- {
- case USB_ENDPOINT_XFER_CONTROL:
- {
- if( psetup->bmRequestType == 0xa3 \
- && psetup->bRequest == USB_REQ_GET_STATUS )
- {
- //get-port-status
- if( psetup->wIndex == 0 \
- || psetup->wIndex > 2 \
- || psetup->wLength < 4 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
- if( psetup->wIndex == 1 )
- {
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBPORTSC1 ) );
- ps = &hub_ext->rh_port1_status;
- }
- else
- {
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBPORTSC2 ) );
- ps = &hub_ext->rh_port2_status;
- }
-
- psret = ( PUSB_PORT_STATUS )purb->data_buffer;
- ps->wPortStatus = 0;
-
- if( status & USBPORTSC_CCS )
- {
- ps->wPortStatus |= USB_PORT_STAT_CONNECTION;
- }
- if( status & USBPORTSC_PE )
- {
- ps->wPortStatus |= USB_PORT_STAT_ENABLE;
- }
- if( status & USBPORTSC_PR )
- {
- ps->wPortStatus |= USB_PORT_STAT_RESET;
- }
- if( status & USBPORTSC_SUSP )
- {
- ps->wPortStatus |= USB_PORT_STAT_SUSPEND;
- }
- if( status & USBPORTSC_LSDA )
- {
- ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED;
- }
-
- //always power on
- ps->wPortStatus |= USB_PORT_STAT_POWER;
-
- //now set change field
- if( status & USBPORTSC_CSC )
- {
- ps->wPortChange |= USB_PORT_STAT_C_CONNECTION;
- }
- if( status & USBPORTSC_PEC )
- {
- ps->wPortChange |= USB_PORT_STAT_C_ENABLE;
- }
-
- //don't touch other fields, will be filled by
- //other function
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( \
- "uhci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n", \
- ps->wPortStatus,
- ps->wPortChange,
- ps ) );
-
- psret->wPortChange = ps->wPortChange;
- psret->wPortStatus = ps->wPortStatus;
-
- purb->status = STATUS_SUCCESS;
-
- break;
- }
- else if( psetup->bmRequestType == 0x23 \
- && psetup->bRequest == USB_REQ_CLEAR_FEATURE )
- {
- //clear-port-feature
- if( psetup->wIndex == 0 || psetup->wIndex > 2 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
- if( psetup->wIndex == 1 )
- {
- i = USBPORTSC1;
- ps = &hub_ext->rh_port1_status;
- }
- else
- {
- i = USBPORTSC2;
- ps = &hub_ext->rh_port2_status;
- }
-
- purb->status = STATUS_SUCCESS;
- switch( psetup->wValue )
- {
- case USB_PORT_FEAT_C_CONNECTION:
- {
- ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
- SET_RH_PORTSTAT( i, USBPORTSC_CSC );
- status = READ_PORT_USHORT( ( PUSHORT ) ( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex, status ) );
- break;
- }
- case USB_PORT_FEAT_C_ENABLE:
- {
- ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE;
- SET_RH_PORTSTAT( i, USBPORTSC_PEC );
- status = READ_PORT_USHORT( ( PUSHORT ) ( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex, status ) );
- break;
- }
- case USB_PORT_FEAT_C_RESET:
- {
- ps->wPortChange &= ~USB_PORT_STAT_C_RESET;
- //the reset signal is down in rh_timer_svc_reset_port_completion
- //so enable the port here
- status = READ_PORT_USHORT( ( PUSHORT ) ( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n", psetup->wIndex, status ) );
- break;
- }
- case USB_PORT_FEAT_ENABLE:
- {
- ps->wPortStatus &= ~USB_PORT_STAT_ENABLE;
- CLR_RH_PORTSTAT( i, USBPORTSC_PE );
- status = READ_PORT_USHORT( ( PUSHORT ) ( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex, status ) );
- break;
- }
- default:
- purb->status = STATUS_UNSUCCESSFUL;
- }
- break;
- }
- else if( psetup->bmRequestType == 0xd3 \
- && psetup->bRequest == HUB_REQ_GET_STATE )
- {
- // get bus state
- if( psetup->wIndex == 0 ||\
- psetup->wIndex > 2 ||\
- psetup->wLength == 0 )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- if( psetup->wIndex == 1 )
- {
- i = USBPORTSC1;
- }
- else
- {
- i = USBPORTSC2;
- }
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + i ) );
- purb->data_buffer[ 0 ] = ( status & USBPORTSC_LS );
-
- // reverse the order
- purb->data_buffer[ 0 ] ^= 0x3;
- purb->status = STATUS_SUCCESS;
- break;
- }
- else if( psetup->bmRequestType == 0x23 \
- && psetup->bRequest == USB_REQ_SET_FEATURE )
- {
- //reset port
- if( psetup->wValue != USB_PORT_FEAT_RESET )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- uhci_dbg_print( DBGLVL_MAXIMUM, ("uhci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue ) );
- break;
- }
- if( psetup->wIndex == 1 )
- {
- i = USBPORTSC1;
- }
- else
- {
- i = USBPORTSC2;
- }
-
- ptimer = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms
- ptimer->context = ( ULONG )purb;
- ptimer->pdev = pdev;
- ptimer->func = rh_timer_svc_reset_port_completion;
-
- //start the timer
- pdev->ref_count += 2; //one for timer and one for urb
-
- status = READ_PORT_USHORT( ( PUSHORT ) ( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status ) );
- InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link );
- purb->status = STATUS_PENDING;
- }
- else
- {
- purb->status = STATUS_INVALID_PARAMETER;
- }
- break;
- }
- case USB_ENDPOINT_XFER_INT:
- {
- ptimer = alloc_timer_svc( &dev_mgr->timer_svc_pool, 1 );
- ptimer->threshold = RH_INTERVAL;
- ptimer->context = ( ULONG )purb;
- ptimer->pdev = pdev;
- ptimer->func = rh_timer_svc_int_completion;
-
- //start the timer
- InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link );
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count ) );
- pdev->ref_count += 2; //one for timer and one for urb
-
- purb->status = STATUS_PENDING;
- break;
- }
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_ISOC:
- default:
- {
- purb->status = STATUS_INVALID_PARAMETER;
- break;
- }
- }
- unlock_dev( pdev, FALSE );
- KeReleaseSpinLock( &dev_mgr->timer_svc_list_lock, old_irql );
- return purb->status;
+
+ switch (endp_type(purb->pendp))
+ {
+ case USB_ENDPOINT_XFER_CONTROL:
+ {
+ if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS)
+ {
+ //get-port-status
+ if (psetup->wIndex == 0 || psetup->wIndex > 2 || psetup->wLength < 4)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ if (psetup->wIndex == 1)
+ {
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC1));
+ ps = &hub_ext->rh_port1_status;
+ }
+ else
+ {
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC2));
+ ps = &hub_ext->rh_port2_status;
+ }
+
+ psret = (PUSB_PORT_STATUS) purb->data_buffer;
+ ps->wPortStatus = 0;
+
+ if (status & USBPORTSC_CCS)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (status & USBPORTSC_PE)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ if (status & USBPORTSC_PR)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (status & USBPORTSC_SUSP)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (status & USBPORTSC_LSDA)
+ {
+ ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+
+ //always power on
+ ps->wPortStatus |= USB_PORT_STAT_POWER;
+
+ //now set change field
+ if (status & USBPORTSC_CSC)
+ {
+ ps->wPortChange |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (status & USBPORTSC_PEC)
+ {
+ ps->wPortChange |= USB_PORT_STAT_C_ENABLE;
+ }
+
+ //don't touch other fields, will be filled by
+ //other function
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
+ ps->wPortStatus, ps->wPortChange, ps));
+
+ psret->wPortChange = ps->wPortChange;
+ psret->wPortStatus = ps->wPortStatus;
+
+ purb->status = STATUS_SUCCESS;
+
+ break;
+ }
+ else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE)
+ {
+ //clear-port-feature
+ if (psetup->wIndex == 0 || psetup->wIndex > 2)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ if (psetup->wIndex == 1)
+ {
+ i = USBPORTSC1;
+ ps = &hub_ext->rh_port1_status;
+ }
+ else
+ {
+ i = USBPORTSC2;
+ ps = &hub_ext->rh_port2_status;
+ }
+
+ purb->status = STATUS_SUCCESS;
+ switch (psetup->wValue)
+ {
+ case USB_PORT_FEAT_C_CONNECTION:
+ {
+ ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
+ SET_RH_PORTSTAT(i, USBPORTSC_CSC);
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex,
+ status));
+ break;
+ }
+ case USB_PORT_FEAT_C_ENABLE:
+ {
+ ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE;
+ SET_RH_PORTSTAT(i, USBPORTSC_PEC);
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex,
+ status));
+ break;
+ }
+ case USB_PORT_FEAT_C_RESET:
+ {
+ ps->wPortChange &= ~USB_PORT_STAT_C_RESET;
+ //the reset signal is down in rh_timer_svc_reset_port_completion
+ //so enable the port here
+ status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
+ psetup->wIndex, status));
+ break;
+ }
+ case USB_PORT_FEAT_ENABLE:
+ {
+ ps->wPortStatus &= ~USB_PORT_STAT_ENABLE;
+ CLR_RH_PORTSTAT(i, USBPORTSC_PE);
+ status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex,
+ status));
+ break;
+ }
+ default:
+ purb->status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+ else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE)
+ {
+ // get bus state
+ if (psetup->wIndex == 0 || psetup->wIndex > 2 || psetup->wLength == 0)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (psetup->wIndex == 1)
+ {
+ i = USBPORTSC1;
+ }
+ else
+ {
+ i = USBPORTSC2;
+ }
+ status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i));
+ purb->data_buffer[0] = (status & USBPORTSC_LS);
+
+ // reverse the order
+ purb->data_buffer[0] ^= 0x3;
+ purb->status = STATUS_SUCCESS;
+ break;
+ }
+ else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_SET_FEATURE)
+ {
+ //reset port
+ if (psetup->wValue != USB_PORT_FEAT_RESET)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ uhci_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue));
+ break;
+ }
+ if (psetup->wIndex == 1)
+ {
+ i = USBPORTSC1;
+ }
+ else
+ {
+ i = USBPORTSC2;
+ }
+
+ ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms
+ ptimer->context = (ULONG) purb;
+ ptimer->pdev = pdev;
+ ptimer->func = rh_timer_svc_reset_port_completion;
+
+ //start the timer
+ pdev->ref_count += 2; //one for timer and one for urb
+
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status));
+ InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link);
+ purb->status = STATUS_PENDING;
+ }
+ else
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ case USB_ENDPOINT_XFER_INT:
+ {
+ ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
+ ptimer->threshold = RH_INTERVAL;
+ ptimer->context = (ULONG) purb;
+ ptimer->pdev = pdev;
+ ptimer->func = rh_timer_svc_int_completion;
+
+ //start the timer
+ InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link);
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("uhci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count));
+ pdev->ref_count += 2; //one for timer and one for urb
+
+ purb->status = STATUS_PENDING;
+ break;
+ }
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_ISOC:
+ default:
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ unlock_dev(pdev, FALSE);
+ KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
+ return purb->status;
}
//must have rh dev_lock acquired
BOOL
-uhci_rh_reset_port(
-PHCD hcd,
-UCHAR port_idx
-)
+uhci_rh_reset_port(PHCD hcd, UCHAR port_idx)
{
- LONG i;
- PUHCI_DEV uhci;
- ULONG status;
-
- if( port_idx != 1 && port_idx != 2 )
- return FALSE;
-
- if( hcd == NULL )
- return FALSE;
-
- if( port_idx == 1 )
- {
- i = USBPORTSC1;
- }
- else
- {
- i = USBPORTSC2;
- }
-
- uhci = uhci_from_hcd( hcd );
- //assert the reset signal,(implicitly disable the port)
- SET_RH_PORTSTAT( i, USBPORTSC_PR );
- usb_wait_ms_dpc( 50 );
- //clear the reset signal, delay port enable till clearing port feature
- CLR_RH_PORTSTAT( i, USBPORTSC_PR );
- usb_wait_us_dpc( 10 );
- SET_RH_PORTSTAT( i, USBPORTSC_PE );
- //recovery time 10ms
- usb_wait_ms_dpc( 10 );
- SET_RH_PORTSTAT( i, 0x0a );
-
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + i ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_reset_port(): status after written=0x%x\n", status ) );
-
- return TRUE;
+ LONG i;
+ PUHCI_DEV uhci;
+ ULONG status;
+
+ if (port_idx != 1 && port_idx != 2)
+ return FALSE;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ if (port_idx == 1)
+ {
+ i = USBPORTSC1;
+ }
+ else
+ {
+ i = USBPORTSC2;
+ }
+
+ uhci = uhci_from_hcd(hcd);
+ //assert the reset signal,(implicitly disable the port)
+ SET_RH_PORTSTAT(i, USBPORTSC_PR);
+ usb_wait_ms_dpc(50);
+ //clear the reset signal, delay port enable till clearing port feature
+ CLR_RH_PORTSTAT(i, USBPORTSC_PR);
+ usb_wait_us_dpc(10);
+ SET_RH_PORTSTAT(i, USBPORTSC_PE);
+ //recovery time 10ms
+ usb_wait_ms_dpc(10);
+ SET_RH_PORTSTAT(i, 0x0a);
+
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i));
+ usb_dbg_print(DBGLVL_MAXIMUM, ("uhci_rh_reset_port(): status after written=0x%x\n", status));
+
+ return TRUE;
}
NTSTATUS
-uhci_dispatch_irp(
-IN PDEVICE_OBJECT DeviceObject,
-IN PIRP irp
-)
+uhci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)
{
- PDEVICE_EXTENSION pdev_ext;
- PUSB_DEV_MANAGER dev_mgr;
- PUHCI_DEV uhci;
-
- pdev_ext = DeviceObject->DeviceExtension;
- uhci = pdev_ext->uhci;
-
- dev_mgr = uhci->hcd_interf.hcd_get_dev_mgr( &uhci->hcd_interf );
- return dev_mgr_dispatch( dev_mgr, irp );
+ PDEVICE_EXTENSION pdev_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUHCI_DEV uhci;
+
+ pdev_ext = DeviceObject->DeviceExtension;
+ uhci = pdev_ext->uhci;
+
+ dev_mgr = uhci->hcd_interf.hcd_get_dev_mgr(&uhci->hcd_interf);
+ return dev_mgr_dispatch(dev_mgr, irp);
}
VOID
-uhci_unload(
-IN PDRIVER_OBJECT DriverObject
-)
+uhci_unload(IN PDRIVER_OBJECT DriverObject)
{
- PDEVICE_OBJECT pdev;
- PDEVICE_EXTENSION pdev_ext;
- PUSB_DEV_MANAGER dev_mgr;
- LONG i;
-
- pdev = DriverObject->DeviceObject;
-
- if( pdev == NULL )
- return;
-
- pdev_ext = pdev->DeviceExtension;
- if( pdev_ext == NULL )
- return;
-
- dev_mgr = &g_dev_mgr;
- if( dev_mgr == NULL )
- return;
- //
- // set the termination flag
- //
- dev_mgr->term_flag = TRUE;
+ PDEVICE_OBJECT pdev;
+ PDEVICE_EXTENSION pdev_ext;
+ PUSB_DEV_MANAGER dev_mgr;
+ LONG i;
+
+ pdev = DriverObject->DeviceObject;
+
+ if (pdev == NULL)
+ return;
+
+ pdev_ext = pdev->DeviceExtension;
+ if (pdev_ext == NULL)
+ return;
+
+ dev_mgr = &g_dev_mgr;
+ if (dev_mgr == NULL)
+ return;
+ //
+ // set the termination flag
+ //
+ dev_mgr->term_flag = TRUE;
+
//
- // wake up the thread if it is
- //
- KeSetEvent( &dev_mgr->wake_up_event, 0, FALSE );
- KeWaitForSingleObject(
- dev_mgr->pthread,
- Executive,
- KernelMode,
- TRUE,
- NULL);
- ObDereferenceObject( dev_mgr->pthread );
- dev_mgr->pthread = NULL;
- // for( i = 0; i < dev_mgr->hcd_count; i++ )
- // dev_mgr->hcd_array[ i ]->hcd_release( dev_mgr->hcd_array[ i ]);
- dev_mgr_release_hcd( dev_mgr );
-
- return;
+ // wake up the thread if it is
+ //
+ KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
+ KeWaitForSingleObject(dev_mgr->pthread, Executive, KernelMode, TRUE, NULL);
+ ObDereferenceObject(dev_mgr->pthread);
+ dev_mgr->pthread = NULL;
+ // for( i = 0; i < dev_mgr->hcd_count; i++ )
+ // dev_mgr->hcd_array[ i ]->hcd_release( dev_mgr->hcd_array[ i ]);
+ dev_mgr_release_hcd(dev_mgr);
+
+ return;
}
//the following are for hcd interface methods
VOID
-uhci_set_dev_mgr(
-struct _HCD* hcd,
-PUSB_DEV_MANAGER dev_mgr )
+uhci_set_dev_mgr(struct _HCD * hcd, PUSB_DEV_MANAGER dev_mgr)
{
- hcd->dev_mgr = dev_mgr;
+ hcd->dev_mgr = dev_mgr;
}
PUSB_DEV_MANAGER
-uhci_get_dev_mgr(
-struct _HCD* hcd
-)
+uhci_get_dev_mgr(struct _HCD *hcd)
{
- return hcd->dev_mgr;
+ return hcd->dev_mgr;
}
-ULONG
-uhci_get_type(
-struct _HCD* hcd
-)
+ULONG
+uhci_get_type(struct _HCD * hcd)
{
- return ( hcd->flags & HCD_TYPE_MASK );
+ return (hcd->flags & HCD_TYPE_MASK);
}
VOID
-uhci_set_id(
-struct _HCD* hcd,
-UCHAR id
-)
+uhci_set_id(struct _HCD * hcd, UCHAR id)
{
- hcd->flags &= ~HCD_ID_MASK;
- hcd->flags |= ( HCD_ID_MASK & id );
+ hcd->flags &= ~HCD_ID_MASK;
+ hcd->flags |= (HCD_ID_MASK & id);
}
UCHAR
-uhci_get_id(
-struct _HCD* hcd
-)
+uhci_get_id(struct _HCD *hcd)
{
- return ( UCHAR )( hcd->flags & HCD_ID_MASK );
+ return (UCHAR) (hcd->flags & HCD_ID_MASK);
}
UCHAR
-uhci_alloc_addr(
-struct _HCD* hcd
-)
+uhci_alloc_addr(struct _HCD * hcd)
{
- LONG i;
- if( hcd == NULL )
- return 0;
-
- for( i = 1; i < MAX_DEVS; i ++ )
- {
- if( hcd->dev_addr_map[ i >> 3 ] & ( 1 << ( i & 7 ) ) )
- {
- continue;
- }
- else
- {
- break;
- }
- }
-
- if( i >= MAX_DEVS )
- return 0xff;
-
- hcd->dev_addr_map[ i >> 3 ] |= ( 1 << ( i & 7 ) );
- hcd->conn_count++;
- return ( BYTE )i;
+ LONG i;
+ if (hcd == NULL)
+ return 0;
+
+ for(i = 1; i < MAX_DEVS; i++)
+ {
+ if (hcd->dev_addr_map[i >> 3] & (1 << (i & 7)))
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (i >= MAX_DEVS)
+ return 0xff;
+
+ hcd->dev_addr_map[i >> 3] |= (1 << (i & 7));
+ hcd->conn_count++;
+ return (BYTE) i;
}
+
VOID
-uhci_free_addr(
-struct _HCD* hcd,
-UCHAR addr
-)
-{
- if( addr & 0x80 )
- return;
-
- if( hcd == NULL )
- return;
-
- hcd->dev_addr_map[ addr >> 3 ] &= ~( 1 << ( addr & 7 ) );
- return;
-
+uhci_free_addr(struct _HCD * hcd, UCHAR addr)
+{
+ if (addr & 0x80)
+ return;
+
+ if (hcd == NULL)
+ return;
+
+ hcd->dev_addr_map[addr >> 3] &= ~(1 << (addr & 7));
+ return;
+
}
NTSTATUS
-uhci_submit_urb2(
-struct _HCD* hcd,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb )
+uhci_submit_urb2(struct _HCD * hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- return uhci_submit_urb( uhci_from_hcd( hcd ), pdev, pendp, purb );
+ return uhci_submit_urb(uhci_from_hcd(hcd), pdev, pendp, purb);
}
PUSB_DEV
-uhci_get_root_hub(
-struct _HCD* hcd
-)
+uhci_get_root_hub(struct _HCD * hcd)
{
- return uhci_from_hcd( hcd )->root_hub;
+ return uhci_from_hcd(hcd)->root_hub;
}
+
VOID
-uhci_set_root_hub(
-struct _HCD* hcd,
-PUSB_DEV root_hub
-)
+uhci_set_root_hub(struct _HCD * hcd, PUSB_DEV root_hub)
{
- if( hcd == NULL || root_hub == NULL )
- return;
- uhci_from_hcd( hcd )->root_hub = root_hub;
- return;
+ if (hcd == NULL || root_hub == NULL)
+ return;
+ uhci_from_hcd(hcd)->root_hub = root_hub;
+ return;
}
BOOL
-uhci_remove_device2(
-struct _HCD* hcd,
-PUSB_DEV pdev
-)
+uhci_remove_device2(struct _HCD * hcd, PUSB_DEV pdev)
{
- if( hcd == NULL || pdev == NULL )
- return FALSE;
+ if (hcd == NULL || pdev == NULL)
+ return FALSE;
- return uhci_remove_device( uhci_from_hcd( hcd ), pdev );
+ return uhci_remove_device(uhci_from_hcd(hcd), pdev);
}
-BOOL uhci_hcd_release(
-struct _HCD* hcd
-)
+BOOL
+uhci_hcd_release(struct _HCD * hcd)
{
- PUHCI_DEV uhci;
- PDEVICE_EXTENSION pdev_ext;
+ PUHCI_DEV uhci;
+ PDEVICE_EXTENSION pdev_ext;
+
+ if (hcd == NULL)
+ return FALSE;
- if( hcd == NULL )
- return FALSE;
-
- uhci = uhci_from_hcd( hcd );
- pdev_ext = uhci->pdev_ext;
+ uhci = uhci_from_hcd(hcd);
+ pdev_ext = uhci->pdev_ext;
- return uhci_release( pdev_ext->pdev_obj );
+ return uhci_release(pdev_ext->pdev_obj);
}
NTSTATUS
-uhci_cancel_urb2(
-struct _HCD* hcd,
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURB purb
-)
+uhci_cancel_urb2(struct _HCD * hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
{
- PUHCI_DEV uhci;
- if( hcd == NULL )
- return STATUS_INVALID_PARAMETER;
-
- uhci = uhci_from_hcd( hcd );
- return uhci_cancel_urb( uhci, pdev, pendp, purb );
+ PUHCI_DEV uhci;
+ if (hcd == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ uhci = uhci_from_hcd(hcd);
+ return uhci_cancel_urb(uhci, pdev, pendp, purb);
}
BOOL
-uhci_rh_get_dev_change(
-PHCD hcd,
-PBYTE buf
-)
+uhci_rh_get_dev_change(PHCD hcd, PBYTE buf)
{
- PUHCI_DEV uhci;
- ULONG status;
+ PUHCI_DEV uhci;
+ ULONG status;
- if( hcd == NULL || buf == NULL )
- return FALSE;
+ if (hcd == NULL || buf == NULL)
+ return FALSE;
- uhci = uhci_from_hcd( hcd );
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBPORTSC1 ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "uhci_rh_get_dev_change(): rh port1 status=0x%x\n", status ) );
+ uhci = uhci_from_hcd(hcd);
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC1));
+ usb_dbg_print(DBGLVL_MAXIMUM, ("uhci_rh_get_dev_change(): rh port1 status=0x%x\n", status));
- if( ( status & USBPORTSC_PEC ) || ( status & USBPORTSC_CSC ) )
- {
- buf[ 0 ] |= ( 1 << 1 );
- }
+ if ((status & USBPORTSC_PEC) || (status & USBPORTSC_CSC))
+ {
+ buf[0] |= (1 << 1);
+ }
- status = READ_PORT_USHORT( ( PUSHORT )( uhci->port_base + USBPORTSC2 ) );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "rh_timer_svc_int_completion(): rh port2 status=0x%x\n", status ) );
+ status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC2));
+ usb_dbg_print(DBGLVL_MAXIMUM, ("rh_timer_svc_int_completion(): rh port2 status=0x%x\n", status));
- if( ( status & USBPORTSC_PEC ) || ( status & USBPORTSC_CSC ) )
- {
- buf[ 0 ] |= ( 1 << 2 );
- }
- return TRUE;
+ if ((status & USBPORTSC_PEC) || (status & USBPORTSC_CSC))
+ {
+ buf[0] |= (1 << 2);
+ }
+ return TRUE;
}
NTSTATUS
-uhci_dispatch(
-PHCD hcd,
-LONG disp_code,
-PVOID param ) // locking depends on type of code
+uhci_dispatch(PHCD hcd, LONG disp_code, PVOID param) // locking depends on type of code
{
- ULONG status;
-
- if( hcd == NULL )
- return FALSE;
-
- switch( disp_code )
- {
- case HCD_DISP_READ_PORT_COUNT:
- {
- if( param == NULL )
- return STATUS_INVALID_PARAMETER;
- *( ( PUCHAR )param ) = 2;
- return STATUS_SUCCESS;
- }
- case HCD_DISP_READ_RH_DEV_CHANGE:
- {
- if( uhci_rh_get_dev_change( hcd, param ) == FALSE )
- return STATUS_INVALID_PARAMETER;
- return STATUS_SUCCESS;
- }
- }
- return STATUS_NOT_IMPLEMENTED;
+ ULONG status;
+
+ if (hcd == NULL)
+ return FALSE;
+
+ switch (disp_code)
+ {
+ case HCD_DISP_READ_PORT_COUNT:
+ {
+ if (param == NULL)
+ return STATUS_INVALID_PARAMETER;
+ *((PUCHAR) param) = 2;
+ return STATUS_SUCCESS;
+ }
+ case HCD_DISP_READ_RH_DEV_CHANGE:
+ {
+ if (uhci_rh_get_dev_change(hcd, param) == FALSE)
+ return STATUS_INVALID_PARAMETER;
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_NOT_IMPLEMENTED;
}
+
VOID
-uhci_init_hcd_interface(
-PUHCI_DEV uhci
-)
-{
- uhci->hcd_interf.hcd_set_dev_mgr = uhci_set_dev_mgr;
- uhci->hcd_interf.hcd_get_dev_mgr = uhci_get_dev_mgr;
- uhci->hcd_interf.hcd_get_type = uhci_get_type;
- uhci->hcd_interf.hcd_set_id = uhci_set_id;
- uhci->hcd_interf.hcd_get_id = uhci_get_id;
- uhci->hcd_interf.hcd_alloc_addr = uhci_alloc_addr;
- uhci->hcd_interf.hcd_free_addr = uhci_free_addr;
- uhci->hcd_interf.hcd_submit_urb = uhci_submit_urb2;
- uhci->hcd_interf.hcd_generic_urb_completion = uhci_generic_urb_completion;
- uhci->hcd_interf.hcd_get_root_hub = uhci_get_root_hub;
- uhci->hcd_interf.hcd_set_root_hub = uhci_set_root_hub;
- uhci->hcd_interf.hcd_remove_device = uhci_remove_device2;
- uhci->hcd_interf.hcd_rh_reset_port = uhci_rh_reset_port;
- uhci->hcd_interf.hcd_release = uhci_hcd_release;
- uhci->hcd_interf.hcd_cancel_urb = uhci_cancel_urb2;
- uhci->hcd_interf.hcd_start = uhci_start;
- uhci->hcd_interf.hcd_dispatch = uhci_dispatch;
-
- uhci->hcd_interf.flags = HCD_TYPE_UHCI; //hcd types | hcd id
+uhci_init_hcd_interface(PUHCI_DEV uhci)
+{
+ uhci->hcd_interf.hcd_set_dev_mgr = uhci_set_dev_mgr;
+ uhci->hcd_interf.hcd_get_dev_mgr = uhci_get_dev_mgr;
+ uhci->hcd_interf.hcd_get_type = uhci_get_type;
+ uhci->hcd_interf.hcd_set_id = uhci_set_id;
+ uhci->hcd_interf.hcd_get_id = uhci_get_id;
+ uhci->hcd_interf.hcd_alloc_addr = uhci_alloc_addr;
+ uhci->hcd_interf.hcd_free_addr = uhci_free_addr;
+ uhci->hcd_interf.hcd_submit_urb = uhci_submit_urb2;
+ uhci->hcd_interf.hcd_generic_urb_completion = uhci_generic_urb_completion;
+ uhci->hcd_interf.hcd_get_root_hub = uhci_get_root_hub;
+ uhci->hcd_interf.hcd_set_root_hub = uhci_set_root_hub;
+ uhci->hcd_interf.hcd_remove_device = uhci_remove_device2;
+ uhci->hcd_interf.hcd_rh_reset_port = uhci_rh_reset_port;
+ uhci->hcd_interf.hcd_release = uhci_hcd_release;
+ uhci->hcd_interf.hcd_cancel_urb = uhci_cancel_urb2;
+ uhci->hcd_interf.hcd_start = uhci_start;
+ uhci->hcd_interf.hcd_dispatch = uhci_dispatch;
+
+ uhci->hcd_interf.flags = HCD_TYPE_UHCI; //hcd types | hcd id
}
NTSTATUS
-generic_dispatch_irp(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- PDEVEXT_HEADER dev_ext;
-
- dev_ext = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
-
- if( dev_ext && dev_ext->dispatch )
- return dev_ext->dispatch( dev_obj, irp );
-
- irp->IoStatus.Information = 0;
-
- EXIT_DISPATCH( STATUS_UNSUCCESSFUL, irp );
+ PDEVEXT_HEADER dev_ext;
+
+ dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+
+ if (dev_ext && dev_ext->dispatch)
+ return dev_ext->dispatch(dev_obj, irp);
+
+ irp->IoStatus.Information = 0;
+
+ EXIT_DISPATCH(STATUS_UNSUCCESSFUL, irp);
}
VOID
-generic_start_io(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+generic_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- PDEVEXT_HEADER dev_ext;
-
- KIRQL old_irql;
-
- IoAcquireCancelSpinLock( &old_irql );
- if (irp != dev_obj->CurrentIrp || irp->Cancel)
- {
- IoReleaseCancelSpinLock(old_irql);
- return;
- }
- else
- {
- IoSetCancelRoutine(irp, NULL);
- IoReleaseCancelSpinLock(old_irql);
- }
-
- dev_ext = ( PDEVEXT_HEADER )dev_obj->DeviceExtension;
-
- if( dev_ext && dev_ext->start_io )
- {
- dev_ext->start_io( dev_obj, irp );
- return;
- }
-
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-
- IoStartNextPacket( dev_obj, FALSE );
- IoCompleteRequest( irp, IO_NO_INCREMENT );
+ PDEVEXT_HEADER dev_ext;
+
+ KIRQL old_irql;
+
+ IoAcquireCancelSpinLock(&old_irql);
+ if (irp != dev_obj->CurrentIrp || irp->Cancel)
+ {
+ IoReleaseCancelSpinLock(old_irql);
+ return;
+ }
+ else
+ {
+ IoSetCancelRoutine(irp, NULL);
+ IoReleaseCancelSpinLock(old_irql);
+ }
+
+ dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
+
+ if (dev_ext && dev_ext->start_io)
+ {
+ dev_ext->start_io(dev_obj, irp);
+ return;
+ }
+
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+
+ IoStartNextPacket(dev_obj, FALSE);
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
}
NTSTATUS
-DriverEntry(
- IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
- )
+DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT dev_obj = NULL;
BOOLEAN fRes;
#if DBG
- // should be done before any debug output is done.
+ // should be done before any debug output is done.
// read our debug verbosity level from the registry
//NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path
- // L"DebugLevel", // REG_DWORD ValueName
- // &gDebugLevel ); // Value receiver
+ // L"DebugLevel", // REG_DWORD ValueName
+ // &gDebugLevel ); // Value receiver
- // debug_level = DBGLVL_MAXIMUM;
+ // debug_level = DBGLVL_MAXIMUM;
#endif
- uhci_dbg_print_cond( DBGLVL_MINIMUM , DEBUG_UHCI, ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer ));
+ uhci_dbg_print_cond(DBGLVL_MINIMUM, DEBUG_UHCI,
+ ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer));
// Remember our driver object, for when we create our child PDO
usb_driver_obj = DriverObject;
//
// Create dispatch points for create, close, unload
- DriverObject->MajorFunction[ IRP_MJ_CREATE ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = generic_dispatch_irp;
DriverObject->DriverUnload = uhci_unload;
// User mode DeviceIoControl() calls will be routed here
- DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_INTERNAL_DEVICE_CONTROL ] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = generic_dispatch_irp;
// User mode ReadFile()/WriteFile() calls will be routed here
- DriverObject->MajorFunction[ IRP_MJ_WRITE ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_READ ] = generic_dispatch_irp;
-
- DriverObject->MajorFunction[ IRP_MJ_SHUTDOWN ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_SCSI ] = generic_dispatch_irp;
- DriverObject->MajorFunction[ IRP_MJ_FLUSH_BUFFERS ] = generic_dispatch_irp;
-
- DriverObject->DriverStartIo = generic_start_io;
- // routines for handling system PNP and power management requests
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_READ] = generic_dispatch_irp;
+
+ DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_SCSI] = generic_dispatch_irp;
+ DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = generic_dispatch_irp;
+
+ DriverObject->DriverStartIo = generic_start_io;
+ // routines for handling system PNP and power management requests
//DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp;
// The Functional Device Object (FDO) will not be created for PNP devices until
// this routine is called upon device plug-in.
- RtlZeroMemory( &g_dev_mgr, sizeof( USB_DEV_MANAGER ) );
- g_dev_mgr.usb_driver_obj = DriverObject;
+ RtlZeroMemory(&g_dev_mgr, sizeof(USB_DEV_MANAGER));
+ g_dev_mgr.usb_driver_obj = DriverObject;
#ifdef INCLUDE_EHCI
- ehci_probe( DriverObject, RegistryPath, &g_dev_mgr );
+ ehci_probe(DriverObject, RegistryPath, &g_dev_mgr);
#endif
- uhci_probe( DriverObject, RegistryPath, &g_dev_mgr );
+ uhci_probe(DriverObject, RegistryPath, &g_dev_mgr);
+
+ if (dev_mgr_strobe(&g_dev_mgr) == FALSE)
+ {
- if( dev_mgr_strobe( &g_dev_mgr ) == FALSE )
- {
+ dev_mgr_release_hcd(&g_dev_mgr);
+ return STATUS_UNSUCCESSFUL;
+ }
- dev_mgr_release_hcd( &g_dev_mgr );
- return STATUS_UNSUCCESSFUL;
- }
+ dev_mgr_start_hcd(&g_dev_mgr);
- dev_mgr_start_hcd( &g_dev_mgr );
-
- uhci_dbg_print_cond( DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus));
- return STATUS_SUCCESS;
+ uhci_dbg_print_cond(DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus));
+ return STATUS_SUCCESS;
}
//note: the initialization will be in the following order
return;\
}
-extern VOID
-gendrv_startio(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-);
+extern VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
-NTSYSAPI
-NTSTATUS
-NTAPI
-ZwLoadDriver(
-IN PUNICODE_STRING DriverServiceName
-);
+NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);
NTSYSAPI
NTSTATUS
NTAPI
-ObOpenObjectByName(
-IN POBJECT_ATTRIBUTES ObjectAttributes,
-IN POBJECT_TYPE ObjectType OPTIONAL,
-IN KPROCESSOR_MODE AccessMode,
-IN OUT PACCESS_STATE AccessState OPTIONAL,
-IN ACCESS_MASK DesiredAccess OPTIONAL,
-IN OUT PVOID ParseContext OPTIONAL,
-OUT PHANDLE Handle
-);
+ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN POBJECT_TYPE ObjectType OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN OUT PACCESS_STATE AccessState OPTIONAL,
+ IN ACCESS_MASK DesiredAccess OPTIONAL,
+ IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle);
-VOID
-umss_start_io(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-);
+VOID umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
-NTSTATUS
-umss_port_dispatch_routine(
-PDEVICE_OBJECT pdev_obj,
-PIRP irp
-);
+NTSTATUS umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
-BOOL
-umss_connect(
-PCONNECT_DATA dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL umss_connect(PCONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
-BOOL
-umss_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-BOOL
-umss_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-NTSTATUS
-umss_dispatch_routine(
-PDEVICE_OBJECT pdev_obj,
-PIRP irp
-);
+NTSTATUS umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
-VOID
-umss_set_cfg_completion(
-PURB purb,
-PVOID pcontext
-);
+VOID umss_set_cfg_completion(PURB purb, PVOID pcontext);
-VOID
-umss_start_create_device(
-IN PVOID Parameter
-);
+VOID umss_start_create_device(IN PVOID Parameter);
-BOOL
-umss_delete_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdrvr,
-PDEVICE_OBJECT dev_obj,
-BOOL is_if
-);
+BOOL umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOL is_if);
-BOOL
-umss_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-);
+BOOL umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
-NTSTATUS
-umss_process_srb(
-PDEVICE_OBJECT dev_obj,
-PIRP irp );
+NTSTATUS umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp);
-VOID
-umss_load_class_driver(
-PVOID context
-);
+VOID umss_load_class_driver(PVOID context);
-BOOL
-umss_tsc_to_sff(
-PIO_PACKET io_packet
-);
+BOOL umss_tsc_to_sff(PIO_PACKET io_packet);
-VOID
-umss_fix_sff_result(
-PIO_PACKET io_packet,
-SCSI_REQUEST_BLOCK *srb
-);
+VOID umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK * srb);
PDEVICE_OBJECT
-umss_create_port_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+umss_create_port_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- // currently a port device is a connection point
- // and upper driver use this to register itself
- // with umss driver for future notification of
- // pnp event. 2004-03-22 23:12:41
- UCHAR dev_name[ 64 ];
- STRING string;
- NTSTATUS status;
- PDEVICE_OBJECT pdev;
- UNICODE_STRING name_string, symb_link;
- PUMSS_PORT_DEV_EXT pdev_ext;
-
- sprintf( dev_name, "\\Device\\usbPort_%d", ( int )0 );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &name_string, &string, TRUE );
- pdev = NULL;
-
- status = IoCreateDevice(
- dev_mgr->usb_driver_obj,
- sizeof( UMSS_PORT_DEV_EXT ),
- &name_string,
- FILE_USB_DEV_TYPE,
- 0,
- TRUE,
- &pdev);
-
- if( status == STATUS_SUCCESS )
- {
- //
- // We do buffered io
- //
- pdev->Flags |= DO_BUFFERED_IO;
-
- pdev->Flags &= ~DO_DEVICE_INITIALIZING;
- pdev->StackSize = 2; //one for fdo, one for file device obj
-
- pdev_ext = ( PUMSS_PORT_DEV_EXT )pdev->DeviceExtension;
-
- pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
- pdev_ext->dev_ext_hdr.dispatch = umss_port_dispatch_routine;
- pdev_ext->dev_ext_hdr.start_io = NULL;
- pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
- pdev_ext->pdriver = pdriver;
-
- sprintf( dev_name, "\\DosDevices\\usbPort%d", ( int )0 );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoCreateSymbolicLink( &symb_link, &name_string );
- RtlFreeUnicodeString( &symb_link );
-
- }
-
- RtlFreeUnicodeString( &name_string );
- return pdev;
+ // currently a port device is a connection point
+ // and upper driver use this to register itself
+ // with umss driver for future notification of
+ // pnp event. 2004-03-22 23:12:41
+ UCHAR dev_name[64];
+ STRING string;
+ NTSTATUS status;
+ PDEVICE_OBJECT pdev;
+ UNICODE_STRING name_string, symb_link;
+ PUMSS_PORT_DEV_EXT pdev_ext;
+
+ sprintf(dev_name, "\\Device\\usbPort_%d", (int)0);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
+ pdev = NULL;
+
+ status = IoCreateDevice(dev_mgr->usb_driver_obj,
+ sizeof(UMSS_PORT_DEV_EXT), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);
+
+ if (status == STATUS_SUCCESS)
+ {
+ //
+ // We do buffered io
+ //
+ pdev->Flags |= DO_BUFFERED_IO;
+
+ pdev->Flags &= ~DO_DEVICE_INITIALIZING;
+ pdev->StackSize = 2; //one for fdo, one for file device obj
+
+ pdev_ext = (PUMSS_PORT_DEV_EXT) pdev->DeviceExtension;
+
+ pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
+ pdev_ext->dev_ext_hdr.dispatch = umss_port_dispatch_routine;
+ pdev_ext->dev_ext_hdr.start_io = NULL;
+ pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
+ pdev_ext->pdriver = pdriver;
+
+ sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoCreateSymbolicLink(&symb_link, &name_string);
+ RtlFreeUnicodeString(&symb_link);
+
+ }
+
+ RtlFreeUnicodeString(&name_string);
+ return pdev;
}
BOOL
-umss_delete_port_device(
-PDEVICE_OBJECT dev_obj
-)
+umss_delete_port_device(PDEVICE_OBJECT dev_obj)
{
- UCHAR dev_name[ 64 ];
- STRING string;
- UNICODE_STRING symb_link;
-
- if( dev_obj == NULL )
- return FALSE;
-
- // remove the symbolic link
- sprintf( dev_name, "\\DosDevices\\usbPort%d", ( int )0 );
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoDeleteSymbolicLink( &symb_link );
- RtlFreeUnicodeString( &symb_link );
-
- if( dev_obj->ReferenceCount == 0 )
- {
- IoDeleteDevice( dev_obj );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_delete_port_device(): port device object is removed\n" ) );
- }
- return TRUE;
+ UCHAR dev_name[64];
+ STRING string;
+ UNICODE_STRING symb_link;
+
+ if (dev_obj == NULL)
+ return FALSE;
+
+ // remove the symbolic link
+ sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoDeleteSymbolicLink(&symb_link);
+ RtlFreeUnicodeString(&symb_link);
+
+ if (dev_obj->ReferenceCount == 0)
+ {
+ IoDeleteDevice(dev_obj);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_port_device(): port device object is removed\n"));
+ }
+ return TRUE;
}
-NTSTATUS
-umss_port_dispatch_routine(
-PDEVICE_OBJECT pdev_obj,
-PIRP irp
-)
// FIXME!!! there can not be sent IOCTL_SUBMIT_URB_XXX while
// the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device.
-// not resolved yet.
+// not resolved yet.
// 2004-03-22 23:12:26
+NTSTATUS
+umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp)
{
- KIRQL irql;
- ULONG ctrl_code;
- NTSTATUS status;
- PIO_STACK_LOCATION irp_stack;
- PUMSS_PORT_DEV_EXT pdev_ext;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
-
- USE_IRQL;
-
- if( pdev_obj == NULL || irp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- status = STATUS_SUCCESS;
- irp_stack = IoGetCurrentIrpStackLocation( irp );
- ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
-
- pdev_ext = ( PUMSS_PORT_DEV_EXT )pdev_obj->DeviceExtension;
-
- switch( irp_stack->MajorFunction )
- {
- case IRP_MJ_INTERNAL_DEVICE_CONTROL:
- {
- switch( ctrl_code )
- {
- case IOCTL_REGISTER_DRIVER:
- {
- PCLASS_DRV_REG_INFO pcdri;
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( CLASS_DRV_REG_INFO ) )
- {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
-
- pcdri = irp->AssociatedIrp.SystemBuffer;
- if( pcdri->fdo_driver == NULL || pcdri->add_device == NULL || pcdri->pnp_dispatch == NULL )
- {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdev_ext->pdriver->driver_ext;
- pdrvr_ext->class_driver_info.fdo_driver = pcdri->fdo_driver;
- pdrvr_ext->class_driver_info.add_device = pcdri->add_device;
- pdrvr_ext->class_driver_info.pnp_dispatch = pcdri->pnp_dispatch;
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- case IOCTL_REVOKE_DRIVER:
- {
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdev_ext->pdriver->driver_ext;
- pdrvr_ext->class_driver_info.fdo_driver = NULL;
- pdrvr_ext->class_driver_info.add_device = NULL;
- pdrvr_ext->class_driver_info.pnp_dispatch = NULL;
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- }
- }
- case IRP_MJ_CREATE:
- case IRP_MJ_CLOSE:
- {
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- }
- EXIT_DISPATCH( STATUS_INVALID_DEVICE_REQUEST, irp );
+ KIRQL irql;
+ ULONG ctrl_code;
+ NTSTATUS status;
+ PIO_STACK_LOCATION irp_stack;
+ PUMSS_PORT_DEV_EXT pdev_ext;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+
+ USE_IRQL;
+
+ if (pdev_obj == NULL || irp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ status = STATUS_SUCCESS;
+ irp_stack = IoGetCurrentIrpStackLocation(irp);
+ ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
+
+ pdev_ext = (PUMSS_PORT_DEV_EXT) pdev_obj->DeviceExtension;
+
+ switch (irp_stack->MajorFunction)
+ {
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+ {
+ switch (ctrl_code)
+ {
+ case IOCTL_REGISTER_DRIVER:
+ {
+ PCLASS_DRV_REG_INFO pcdri;
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CLASS_DRV_REG_INFO))
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+
+ pcdri = irp->AssociatedIrp.SystemBuffer;
+ if (pcdri->fdo_driver == NULL || pcdri->add_device == NULL || pcdri->pnp_dispatch == NULL)
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
+ pdrvr_ext->class_driver_info.fdo_driver = pcdri->fdo_driver;
+ pdrvr_ext->class_driver_info.add_device = pcdri->add_device;
+ pdrvr_ext->class_driver_info.pnp_dispatch = pcdri->pnp_dispatch;
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ case IOCTL_REVOKE_DRIVER:
+ {
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
+ pdrvr_ext->class_driver_info.fdo_driver = NULL;
+ pdrvr_ext->class_driver_info.add_device = NULL;
+ pdrvr_ext->class_driver_info.pnp_dispatch = NULL;
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ }
+ }
+ case IRP_MJ_CREATE:
+ case IRP_MJ_CLOSE:
+ {
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ }
+ EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
BOOL
-umss_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+umss_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- UNICODE_STRING unicode_string;
- NTSTATUS status;
-
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- //init driver structure, no PNP table functions
- pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
- pdriver->driver_desc.vendor_id = 0x0dd8; // USB Vendor ID
- pdriver->driver_desc.product_id = 0x0003; // USB Product ID.
- pdriver->driver_desc.release_num = 0x100; // Release Number of Device
-
- pdriver->driver_desc.config_val = 1; // Configuration Value
- pdriver->driver_desc.if_num = 1; // Interface Number
- pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // 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 Mass Storage driver"; // Driver name for Name Registry
- pdriver->driver_desc.dev_class = USB_CLASS_MASS_STORAGE;
- pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
- pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
-
- pdriver->driver_ext = usb_alloc_mem( NonPagedPool, sizeof( UMSS_DRVR_EXTENSION ) );
- pdriver->driver_ext_size = sizeof( UMSS_DRVR_EXTENSION );
-
- RtlZeroMemory( pdriver->driver_ext, sizeof( UMSS_DRVR_EXTENSION ) );
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdriver->driver_ext;
- pdrvr_ext->dev_count = 0;
- InitializeListHead( &pdrvr_ext->dev_list );
- ExInitializeFastMutex( &pdrvr_ext->dev_list_mutex );
-
- pdriver->disp_tbl.version = 1;
- pdriver->disp_tbl.dev_connect = umss_connect;
- pdriver->disp_tbl.dev_disconnect = umss_disconnect;
- pdriver->disp_tbl.dev_stop = umss_stop;
- pdriver->disp_tbl.dev_reserved = NULL;
-
- if( ( pdrvr_ext->port_dev_obj = umss_create_port_device( dev_mgr, pdriver ) ) == NULL )
- {
- usb_free_mem( pdriver->driver_ext );
- pdriver->driver_ext = NULL;
- pdriver->driver_ext_size = 0;
- pdriver->disp_tbl.dev_connect = NULL;
- pdriver->disp_tbl.dev_stop = NULL;
- pdriver->disp_tbl.dev_disconnect = NULL;
- return FALSE;
- }
-
- umss_load_class_driver( NULL );
-
- // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_driver_init(): umss driver is initialized\n") );
- return TRUE;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ UNICODE_STRING unicode_string;
+ NTSTATUS status;
+
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ //init driver structure, no PNP table functions
+ pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
+ pdriver->driver_desc.vendor_id = 0x0dd8; // USB Vendor ID
+ pdriver->driver_desc.product_id = 0x0003; // USB Product ID.
+ pdriver->driver_desc.release_num = 0x100; // Release Number of Device
+
+ pdriver->driver_desc.config_val = 1; // Configuration Value
+ pdriver->driver_desc.if_num = 1; // Interface Number
+ pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // 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 Mass Storage driver"; // Driver name for Name Registry
+ pdriver->driver_desc.dev_class = USB_CLASS_MASS_STORAGE;
+ pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
+ pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
+
+ pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION));
+ pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION);
+
+ RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION));
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
+ pdrvr_ext->dev_count = 0;
+ InitializeListHead(&pdrvr_ext->dev_list);
+ ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex);
+
+ pdriver->disp_tbl.version = 1;
+ pdriver->disp_tbl.dev_connect = umss_connect;
+ pdriver->disp_tbl.dev_disconnect = umss_disconnect;
+ pdriver->disp_tbl.dev_stop = umss_stop;
+ pdriver->disp_tbl.dev_reserved = NULL;
+
+ if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL)
+ {
+ usb_free_mem(pdriver->driver_ext);
+ pdriver->driver_ext = NULL;
+ pdriver->driver_ext_size = 0;
+ pdriver->disp_tbl.dev_connect = NULL;
+ pdriver->disp_tbl.dev_stop = NULL;
+ pdriver->disp_tbl.dev_disconnect = NULL;
+ return FALSE;
+ }
+
+ umss_load_class_driver(NULL);
+
+ // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_init(): umss driver is initialized\n"));
+ return TRUE;
}
BOOL
-umss_driver_destroy(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+umss_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION ) pdriver->driver_ext;
- umss_delete_port_device( pdrvr_ext->port_dev_obj );
- pdrvr_ext->port_dev_obj = NULL;
-
- ASSERT( IsListEmpty( &pdrvr_ext->dev_list ) == TRUE );
- usb_free_mem( pdriver->driver_ext );
- pdriver->driver_ext = NULL;
- pdriver->driver_ext_size = 0;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_driver_destroy(): umss driver is destroyed\n" ) );
- return TRUE;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
+ umss_delete_port_device(pdrvr_ext->port_dev_obj);
+ pdrvr_ext->port_dev_obj = NULL;
+
+ ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE);
+ usb_free_mem(pdriver->driver_ext);
+ pdriver->driver_ext = NULL;
+ pdriver->driver_ext_size = 0;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_destroy(): umss driver is destroyed\n"));
+ return TRUE;
}
PDEVICE_OBJECT
-umss_create_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER umss_drvr,
-DEV_HANDLE dev_handle,
-BOOL is_if
-)
+umss_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER umss_drvr, DEV_HANDLE dev_handle, BOOL is_if)
{
- UCHAR dev_name[ 64 ], dev_id;
- STRING string;
- NTSTATUS status;
- PDEVICE_OBJECT pdev;
- UNICODE_STRING name_string, symb_link;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- PUMSS_DEVICE_EXTENSION pdev_ext;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_create_device(): entering...\n" ) );
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )umss_drvr->driver_ext;
- dev_id = ( UCHAR )dev_id_from_handle( dev_handle ); // pdrvr_ext->dev_count;
-
- if( is_if == FALSE )
- sprintf( dev_name, "\\Device\\umssdev_%d", ( int )dev_id );
- else
- sprintf( dev_name, "\\Device\\umssifdev_%d", ( int )dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &name_string, &string, TRUE );
- pdev = NULL;
-
- status = IoCreateDevice(
- dev_mgr->usb_driver_obj,
- sizeof( UMSS_DEVICE_EXTENSION ),
- &name_string,
- FILE_USB_DEV_TYPE,
- 0,
- TRUE,
- &pdev);
-
- if( status == STATUS_SUCCESS )
- {
- //
- // We do direct io
- //
- pdev->Flags |= DO_DIRECT_IO;
-
- pdev->Flags &= ~DO_DEVICE_INITIALIZING;
- pdev->StackSize = 2; //one for fdo, one for file device obj
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )pdev->DeviceExtension;
-
- //may be accessed by other thread
- ExAcquireFastMutex( &pdrvr_ext->dev_list_mutex );
- InsertTailList( &pdrvr_ext->dev_list, &pdev_ext->dev_obj_link );
- pdrvr_ext->dev_count++;
- ExReleaseFastMutex( &pdrvr_ext->dev_list_mutex );
-
- if( is_if )
- pdev_ext->flags |= UMSS_DEV_FLAG_IF_DEV;
-
- pdev_ext->umss_dev_id = dev_id;
- pdev_ext->pdo = pdev;
- pdev_ext->dev_handle = dev_handle;
- pdev_ext->dev_mgr = dev_mgr;
- pdev_ext->pdriver = umss_drvr;
-
- pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
- pdev_ext->dev_ext_hdr.dispatch = umss_dispatch_routine;
- pdev_ext->dev_ext_hdr.start_io = umss_start_io;
- pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
-
- if( is_if == FALSE )
- sprintf( dev_name, "\\DosDevices\\umssdev%d", ( int )dev_id );
- else
- sprintf( dev_name, "\\DosDevices\\umssifdev%d", ( int )dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoCreateSymbolicLink( &symb_link, &name_string );
- RtlFreeUnicodeString( &symb_link );
- KeInitializeEvent( &pdev_ext->sync_event, SynchronizationEvent, FALSE );
- KeInitializeSpinLock( &pdev_ext->dev_lock );
-
- }
- RtlFreeUnicodeString( &name_string );
- return pdev;
+ UCHAR dev_name[64], dev_id;
+ STRING string;
+ NTSTATUS status;
+ PDEVICE_OBJECT pdev;
+ UNICODE_STRING name_string, symb_link;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_create_device(): entering...\n"));
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) umss_drvr->driver_ext;
+ dev_id = (UCHAR) dev_id_from_handle(dev_handle); // pdrvr_ext->dev_count;
+
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\Device\\umssdev_%d", (int)dev_id);
+ else
+ sprintf(dev_name, "\\Device\\umssifdev_%d", (int)dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
+ pdev = NULL;
+
+ status = IoCreateDevice(dev_mgr->usb_driver_obj,
+ sizeof(UMSS_DEVICE_EXTENSION),
+ &name_string,
+ FILE_USB_DEV_TYPE,
+ 0,
+ TRUE,
+ &pdev);
+
+ if (status == STATUS_SUCCESS)
+ {
+ //
+ // We do direct io
+ //
+ pdev->Flags |= DO_DIRECT_IO;
+
+ pdev->Flags &= ~DO_DEVICE_INITIALIZING;
+ pdev->StackSize = 2; //one for fdo, one for file device obj
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev->DeviceExtension;
+
+ //may be accessed by other thread
+ ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
+ InsertTailList(&pdrvr_ext->dev_list, &pdev_ext->dev_obj_link);
+ pdrvr_ext->dev_count++;
+ ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
+
+ if (is_if)
+ pdev_ext->flags |= UMSS_DEV_FLAG_IF_DEV;
+
+ pdev_ext->umss_dev_id = dev_id;
+ pdev_ext->pdo = pdev;
+ pdev_ext->dev_handle = dev_handle;
+ pdev_ext->dev_mgr = dev_mgr;
+ pdev_ext->pdriver = umss_drvr;
+
+ pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
+ pdev_ext->dev_ext_hdr.dispatch = umss_dispatch_routine;
+ pdev_ext->dev_ext_hdr.start_io = umss_start_io;
+ pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
+
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)dev_id);
+ else
+ sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoCreateSymbolicLink(&symb_link, &name_string);
+ RtlFreeUnicodeString(&symb_link);
+ KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
+ KeInitializeSpinLock(&pdev_ext->dev_lock);
+
+ }
+ RtlFreeUnicodeString(&name_string);
+ return pdev;
}
BOOL
-umss_connect(
-PCONNECT_DATA param,
-DEV_HANDLE dev_handle
-)
+umss_connect(PCONNECT_DATA param, DEV_HANDLE dev_handle)
{
- PURB purb;
- NTSTATUS status;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DRIVER pdrvr;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_connect(): entering...\n" ) );
-
- dev_mgr = param->dev_mgr;
- pdrvr = param->pdriver;
-
- //directly set the configuration
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb == NULL )
- return FALSE;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- urb_init( ( purb ) );
-
- purb->endp_handle = dev_handle | 0xffff;
- purb->data_buffer = NULL;
- purb->data_length = 0;
- purb->completion = umss_set_cfg_completion;
- purb->context = dev_mgr;
- purb->reference = ( LONG )pdrvr;
- psetup->bmRequestType = 0;
- psetup->bRequest = USB_REQ_SET_CONFIGURATION;
- psetup->wValue = 1;
- psetup->wIndex = 0;
- psetup->wLength = 0;
-
- status = usb_submit_urb( dev_mgr, purb );
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb );
- return FALSE;
- }
- return TRUE;
+ PURB purb;
+ NTSTATUS status;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DRIVER pdrvr;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_connect(): entering...\n"));
+
+ dev_mgr = param->dev_mgr;
+ pdrvr = param->pdriver;
+
+ //directly set the configuration
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb == NULL)
+ return FALSE;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ urb_init((purb));
+
+ purb->endp_handle = dev_handle | 0xffff;
+ purb->data_buffer = NULL;
+ purb->data_length = 0;
+ purb->completion = umss_set_cfg_completion;
+ purb->context = dev_mgr;
+ purb->reference = (LONG) pdrvr;
+ psetup->bmRequestType = 0;
+ psetup->bRequest = USB_REQ_SET_CONFIGURATION;
+ psetup->wValue = 1;
+ psetup->wIndex = 0;
+ psetup->wLength = 0;
+
+ status = usb_submit_urb(dev_mgr, purb);
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ return FALSE;
+ }
+ return TRUE;
}
VOID
-umss_set_cfg_completion(
-PURB purb,
-PVOID pcontext
-)
+umss_set_cfg_completion(PURB purb, PVOID pcontext)
{
- PUSB_CTRL_SETUP_PACKET psetup;
- PUCHAR buf;
- PWORK_QUEUE_ITEM pwork_item;
- PUMSS_CREATE_DATA pcd;
- DEV_HANDLE dev_handle;
- NTSTATUS status;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_DRIVER pdrvr;
-
- if( purb == NULL || pcontext == NULL )
- return;
-
- dev_mgr = ( PUSB_DEV_MANAGER ) pcontext;
- pdrvr = ( PUSB_DRIVER )purb->reference;
- dev_handle = purb->endp_handle & ~0xffff;
-
-
- if( purb->status != STATUS_SUCCESS )
- {
- usb_free_mem( purb );
- return;
- }
-
- buf = usb_alloc_mem( NonPagedPool, 512 );
- if( buf == NULL )
- {
- usb_free_mem( purb );
- return;
- }
-
- //now let's get the descs, one configuration, one interface and two endpoint
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- purb->data_buffer = buf;
- purb->data_length = 512;
- purb->completion = NULL; //this is an immediate request, no needs completion
- purb->context = dev_mgr;
- 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( purb );
- purb = NULL;
-
- if( status != STATUS_SUCCESS )
- {
- usb_free_mem( buf );
- buf = NULL;
- return;
- }
-
- pcd = usb_alloc_mem( NonPagedPool, sizeof( WORK_QUEUE_ITEM ) + sizeof( UMSS_CREATE_DATA ) );
- if( pcd == NULL )
- {
- usb_free_mem( buf );
- buf = NULL;
- return;
- }
-
- pcd->desc_buf = buf;
- pcd->dev_handle = dev_handle;
- pcd->dev_mgr = dev_mgr;
- pcd->pdriver = pdrvr;
- pwork_item = ( PWORK_QUEUE_ITEM )( &pcd[ 1 ] );
-
- ExInitializeWorkItem( pwork_item, umss_start_create_device, ( PVOID )pcd );
- ExQueueWorkItem( pwork_item, DelayedWorkQueue );
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUCHAR buf;
+ PWORK_QUEUE_ITEM pwork_item;
+ PUMSS_CREATE_DATA pcd;
+ DEV_HANDLE dev_handle;
+ NTSTATUS status;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_DRIVER pdrvr;
+
+ if (purb == NULL || pcontext == NULL)
+ return;
+
+ dev_mgr = (PUSB_DEV_MANAGER) pcontext;
+ pdrvr = (PUSB_DRIVER) purb->reference;
+ dev_handle = purb->endp_handle & ~0xffff;
+
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ usb_free_mem(purb);
+ return;
+ }
+
+ buf = usb_alloc_mem(NonPagedPool, 512);
+ if (buf == NULL)
+ {
+ usb_free_mem(purb);
+ return;
+ }
+
+ //now let's get the descs, one configuration, one interface and two endpoint
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ purb->data_buffer = buf;
+ purb->data_length = 512;
+ purb->completion = NULL; //this is an immediate request, no needs completion
+ purb->context = dev_mgr;
+ 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(purb);
+ purb = NULL;
+
+ if (status != STATUS_SUCCESS)
+ {
+ usb_free_mem(buf);
+ buf = NULL;
+ return;
+ }
+
+ pcd = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_CREATE_DATA));
+ if (pcd == NULL)
+ {
+ usb_free_mem(buf);
+ buf = NULL;
+ return;
+ }
+
+ pcd->desc_buf = buf;
+ pcd->dev_handle = dev_handle;
+ pcd->dev_mgr = dev_mgr;
+ pcd->pdriver = pdrvr;
+ pwork_item = (PWORK_QUEUE_ITEM) (&pcd[1]);
+
+ ExInitializeWorkItem(pwork_item, umss_start_create_device, (PVOID) pcd);
+ ExQueueWorkItem(pwork_item, DelayedWorkQueue);
}
VOID
-umss_start_create_device(
-IN PVOID Parameter
-)
+umss_start_create_device(IN PVOID Parameter)
{
- LONG i;
- PUCHAR desc_buf;
- NTSTATUS status;
- PUSB_DEV pdev;
- DEV_HANDLE dev_handle;
- PUSB_DRIVER pdrvr;
- PDEVICE_OBJECT pdev_obj;
- PUSB_DEV_MANAGER dev_mgr;
- PUMSS_CREATE_DATA pcd;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_ENDPOINT_DESC pendp_desc;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PUSB_CONFIGURATION_DESC pconfig_desc;
-
- USE_IRQL;
-
- if( Parameter == NULL )
- return;
-
- pcd = ( PUMSS_CREATE_DATA )Parameter;
- desc_buf = pcd->desc_buf;
- dev_mgr = pcd->dev_mgr;
- dev_handle = pcd->dev_handle;
- pdrvr = pcd->pdriver;
- usb_free_mem( pcd );
- pcd = NULL;
-
- status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- usb_free_mem( desc_buf );
- return;
- }
-
- pdev_obj = umss_create_device( dev_mgr, pdrvr, dev_handle, FALSE );
-
- lock_dev( pdev, FALSE );
- if( pdev_obj == NULL || \
- dev_state( pdev ) == USB_DEV_STATE_ZOMB || \
- dev_mgr_set_driver( dev_mgr, dev_handle, pdrvr, pdev ) == FALSE )
- {
- usb_free_mem( desc_buf );
- unlock_dev( pdev, FALSE );
-
- if( pdev_obj )
- umss_delete_device( dev_mgr, pdrvr, pdev_obj, FALSE );
-
- usb_unlock_dev( pdev );
- return;
- }
- unlock_dev( pdev, FALSE );
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )pdev_obj->DeviceExtension;
-
- pdev_ext->desc_buf = desc_buf;
- pdev_ext->pif_desc = NULL;
- pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
-
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )desc_buf;
- pif_desc = ( PUSB_INTERFACE_DESC )( &pconfig_desc[ 1 ] );
- //search for our if
- for( i = 0; ( ( UCHAR ) i ) < pconfig_desc->bNumInterfaces; i++ )
- {
- if( pif_desc->bLength == sizeof( USB_INTERFACE_DESC ) \
- && pif_desc->bDescriptorType == USB_DT_INTERFACE )
- {
- if( pif_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE )
- {
- pdev_ext->pif_desc = pif_desc;
- pdev_ext->if_idx = ( UCHAR )i;
- break;
- }
- else
- {
- if( usb_skip_if_and_altif( ( PUCHAR* )&pif_desc ) == FALSE )
- break;
- }
- }
- else
- {
- break;
- }
- }
-
- if( pdev_ext->pif_desc )
- {
- pendp_desc = ( PUSB_ENDPOINT_DESC )&pif_desc[ 1 ];
- for( i = 0; ( ( UCHAR )i ) < pif_desc->bNumEndpoints; i++ )
- {
- if( pendp_desc->bDescriptorType == USB_DT_ENDPOINT \
- && pendp_desc->bLength == sizeof( USB_ENDPOINT_DESC ) )
- {
- if( ( pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) \
- == USB_ENDPOINT_XFER_INT )
- {
- pdev_ext->pint_endp_desc = pendp_desc;
- pdev_ext->int_endp_idx = ( UCHAR )i;
- }
- else if( ( pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) \
- == USB_ENDPOINT_XFER_BULK )
- {
- if( pendp_desc->bEndpointAddress & USB_DIR_IN )
- {
- pdev_ext->pin_endp_desc = pendp_desc;
- pdev_ext->in_endp_idx = ( UCHAR )i;
- }
- else
- {
- pdev_ext->pout_endp_desc = pendp_desc;
- pdev_ext->out_endp_idx = ( UCHAR )i;
- }
- }
- pendp_desc = &pendp_desc[ 1 ];
- }
- else
- break;
- }
- }
- usb_unlock_dev( pdev );
- return;
+ LONG i;
+ PUCHAR desc_buf;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ DEV_HANDLE dev_handle;
+ PUSB_DRIVER pdrvr;
+ PDEVICE_OBJECT pdev_obj;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUMSS_CREATE_DATA pcd;
+ PUSB_INTERFACE_DESC pif_desc;
+ PUSB_ENDPOINT_DESC pendp_desc;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+
+ USE_IRQL;
+
+ if (Parameter == NULL)
+ return;
+
+ pcd = (PUMSS_CREATE_DATA) Parameter;
+ desc_buf = pcd->desc_buf;
+ dev_mgr = pcd->dev_mgr;
+ dev_handle = pcd->dev_handle;
+ pdrvr = pcd->pdriver;
+ usb_free_mem(pcd);
+ pcd = NULL;
+
+ status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ usb_free_mem(desc_buf);
+ return;
+ }
+
+ pdev_obj = umss_create_device(dev_mgr, pdrvr, dev_handle, FALSE);
+
+ lock_dev(pdev, FALSE);
+ if (pdev_obj == NULL ||
+ dev_state(pdev) == USB_DEV_STATE_ZOMB ||
+ dev_mgr_set_driver(dev_mgr, dev_handle, pdrvr, pdev) == FALSE)
+ {
+ usb_free_mem(desc_buf);
+ unlock_dev(pdev, FALSE);
+
+ if (pdev_obj)
+ umss_delete_device(dev_mgr, pdrvr, pdev_obj, FALSE);
+
+ usb_unlock_dev(pdev);
+ return;
+ }
+ unlock_dev(pdev, FALSE);
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
+
+ pdev_ext->desc_buf = desc_buf;
+ pdev_ext->pif_desc = NULL;
+ pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
+
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf;
+ pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
+ //search for our if
+ for(i = 0; ((UCHAR) i) < pconfig_desc->bNumInterfaces; i++)
+ {
+ if (pif_desc->bLength == sizeof(USB_INTERFACE_DESC) && pif_desc->bDescriptorType == USB_DT_INTERFACE)
+ {
+ if (pif_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
+ {
+ pdev_ext->pif_desc = pif_desc;
+ pdev_ext->if_idx = (UCHAR) i;
+ break;
+ }
+ else
+ {
+ if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (pdev_ext->pif_desc)
+ {
+ pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
+ for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++)
+ {
+ if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT
+ && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
+ {
+ if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ {
+ pdev_ext->pint_endp_desc = pendp_desc;
+ pdev_ext->int_endp_idx = (UCHAR) i;
+ }
+ else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+ {
+ if (pendp_desc->bEndpointAddress & USB_DIR_IN)
+ {
+ pdev_ext->pin_endp_desc = pendp_desc;
+ pdev_ext->in_endp_idx = (UCHAR) i;
+ }
+ else
+ {
+ pdev_ext->pout_endp_desc = pendp_desc;
+ pdev_ext->out_endp_idx = (UCHAR) i;
+ }
+ }
+ pendp_desc = &pendp_desc[1];
+ }
+ else
+ break;
+ }
+ }
+ usb_unlock_dev(pdev);
+ return;
}
BOOL
-umss_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- return TRUE;
+ return TRUE;
}
BOOL
-umss_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
+umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
- PDEVICE_OBJECT dev_obj;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_DRIVER pdrvr;
-
- if( dev_mgr == NULL || dev_handle == 0 )
- return FALSE;
-
- pdev = NULL;
- //special use of the lock dev, simply use this routine to get the dev
- status = usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev );
- if( pdev == NULL )
- {
- return FALSE;
- }
- if( status == STATUS_SUCCESS )
- {
- // must be a bug
- TRAP();
- usb_unlock_dev( pdev );
- }
- pdrvr = pdev->dev_driver;
- dev_obj = pdev->dev_obj;
- pdev = NULL;
-
- return umss_delete_device( dev_mgr, pdrvr, dev_obj, FALSE );
+ PDEVICE_OBJECT dev_obj;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_DRIVER pdrvr;
+
+ if (dev_mgr == NULL || dev_handle == 0)
+ return FALSE;
+
+ pdev = NULL;
+ //special use of the lock dev, simply use this routine to get the dev
+ status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
+ if (pdev == NULL)
+ {
+ return FALSE;
+ }
+ if (status == STATUS_SUCCESS)
+ {
+ // must be a bug
+ TRAP();
+ usb_unlock_dev(pdev);
+ }
+ pdrvr = pdev->dev_driver;
+ dev_obj = pdev->dev_obj;
+ pdev = NULL;
+
+ return umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
}
VOID
-umss_deferred_delete_device(
-PVOID context
-)
+umss_deferred_delete_device(PVOID context)
{
- PDEVICE_OBJECT dev_obj;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- LARGE_INTEGER interval;
-
- if( context == NULL )
- return;
-
- dev_obj = ( PDEVICE_OBJECT )context;
- pdev_ext = dev_obj->DeviceExtension;
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdev_ext->pdriver->driver_ext;
-
- interval.QuadPart = -20000; //two ms
-
- for( ; ; )
- {
- if( dev_obj->ReferenceCount )
- KeDelayExecutionThread( KernelMode, TRUE, &interval );
- else
- {
- KeDelayExecutionThread( KernelMode, TRUE, &interval );
- if( dev_obj->ReferenceCount == 0 )
- break;
- }
- }
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_deferred_delete_device(): delete device, 0x%x\n", dev_obj ) );
-
- ExAcquireFastMutex( &pdrvr_ext->dev_list_mutex );
- RemoveEntryList( &pdev_ext->dev_obj_link );
- pdrvr_ext->dev_count--;
- ExReleaseFastMutex( &pdrvr_ext->dev_list_mutex );
-
- IoDeleteDevice( dev_obj );
- return;
+ PDEVICE_OBJECT dev_obj;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ LARGE_INTEGER interval;
+
+ if (context == NULL)
+ return;
+
+ dev_obj = (PDEVICE_OBJECT) context;
+ pdev_ext = dev_obj->DeviceExtension;
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
+
+ interval.QuadPart = -20000; //two ms
+
+ for(;;)
+ {
+ if (dev_obj->ReferenceCount)
+ KeDelayExecutionThread(KernelMode, TRUE, &interval);
+ else
+ {
+ KeDelayExecutionThread(KernelMode, TRUE, &interval);
+ if (dev_obj->ReferenceCount == 0)
+ break;
+ }
+ }
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
+
+ ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
+ RemoveEntryList(&pdev_ext->dev_obj_link);
+ pdrvr_ext->dev_count--;
+ ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
+
+ IoDeleteDevice(dev_obj);
+ return;
}
BOOL
-umss_delete_device(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdrvr,
-PDEVICE_OBJECT dev_obj,
-BOOL is_if
-)
+umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOL is_if)
{
- UCHAR dev_name[ 64 ];
- STRING string;
- UNICODE_STRING symb_link;
-
- NTSTATUS status;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
-
- if( dev_obj == NULL )
- return FALSE;
-
- if( pdrvr == NULL || dev_mgr == NULL )
- return FALSE;
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )dev_obj->DeviceExtension;
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdrvr->driver_ext;
- if( is_if == FALSE )
- sprintf( dev_name, "\\DosDevices\\umssdev%d", ( int )pdev_ext->umss_dev_id );
- else
- sprintf( dev_name, "\\DosDevices\\umssifdev%d", ( int )pdev_ext->umss_dev_id );
-
- RtlInitString( &string, dev_name );
- RtlAnsiStringToUnicodeString( &symb_link, &string, TRUE );
- IoDeleteSymbolicLink( &symb_link );
- RtlFreeUnicodeString( &symb_link );
-
- if( pdev_ext->desc_buf )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_delete_device(): delete desc_buf\n" ) );
- usb_free_mem( pdev_ext->desc_buf );
- pdev_ext->desc_buf = NULL;
-
- }
-
- if( dev_obj->ReferenceCount == 0 )
- {
- ExAcquireFastMutex( &pdrvr_ext->dev_list_mutex );
- RemoveEntryList( &pdev_ext->dev_obj_link );
- pdrvr_ext->dev_count--;
- ExReleaseFastMutex( &pdrvr_ext->dev_list_mutex );
-
- IoDeleteDevice( dev_obj );
- return TRUE;
- }
-
- //
- // FIXME: how if the driver unloading happens
- // since this is called in dev_mgr_disconnect_dev, umss_schedule_workitem
- // can not protect the USB_DEV object from be deleted. so the workitem
- // can not access anything relative to the USB_DEV object. In this case
- // we will tollerate the usb_query_and_lock_dev failure since it will
- // never success when come to this point, and we won't pass dev_mgr
- // and pdev to the function. But other scenarios, usb_query_and_lock_dev
- // can not fail if dev_mgr and pdev are passed valid.
- // When driver is unloading, don't know. Wish NT will unload the driver
- // only when all the devices to the driver are deleted.
- //
- umss_schedule_workitem( dev_obj, umss_deferred_delete_device, NULL, 0 );
- return TRUE;
+ UCHAR dev_name[64];
+ STRING string;
+ UNICODE_STRING symb_link;
+
+ NTSTATUS status;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+
+ if (dev_obj == NULL)
+ return FALSE;
+
+ if (pdrvr == NULL || dev_mgr == NULL)
+ return FALSE;
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
+ if (is_if == FALSE)
+ sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)pdev_ext->umss_dev_id);
+ else
+ sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)pdev_ext->umss_dev_id);
+
+ RtlInitString(&string, dev_name);
+ RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
+ IoDeleteSymbolicLink(&symb_link);
+ RtlFreeUnicodeString(&symb_link);
+
+ if (pdev_ext->desc_buf)
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_device(): delete desc_buf\n"));
+ usb_free_mem(pdev_ext->desc_buf);
+ pdev_ext->desc_buf = NULL;
+
+ }
+
+ if (dev_obj->ReferenceCount == 0)
+ {
+ ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
+ RemoveEntryList(&pdev_ext->dev_obj_link);
+ pdrvr_ext->dev_count--;
+ ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
+
+ IoDeleteDevice(dev_obj);
+ return TRUE;
+ }
+
+ //
+ // FIXME: how if the driver unloading happens
+ // since this is called in dev_mgr_disconnect_dev, umss_schedule_workitem
+ // can not protect the USB_DEV object from be deleted. so the workitem
+ // can not access anything relative to the USB_DEV object. In this case
+ // we will tollerate the usb_query_and_lock_dev failure since it will
+ // never success when come to this point, and we won't pass dev_mgr
+ // and pdev to the function. But other scenarios, usb_query_and_lock_dev
+ // can not fail if dev_mgr and pdev are passed valid.
+ // When driver is unloading, don't know. Wish NT will unload the driver
+ // only when all the devices to the driver are deleted.
+ //
+ umss_schedule_workitem(dev_obj, umss_deferred_delete_device, NULL, 0);
+ return TRUE;
}
VOID
-umss_submit_io_packet(
-PDEVICE_OBJECT dev_obj,
-PIO_PACKET io_packet
-)
+umss_submit_io_packet(PDEVICE_OBJECT dev_obj, PIO_PACKET io_packet)
{
- NTSTATUS status;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PUSB_DEV pdev;
-
- pdev_ext = dev_obj->DeviceExtension;
-
- // lock the dev, the pdev_ext->pif_desc won't go away.
- if( ( status = usb_query_and_lock_dev( pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev ) )
- != STATUS_SUCCESS )
- {
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_start_io(): error, device is not valid\n" ) );
- UMSS_COMPLETE_START_IO( dev_obj, status, io_packet->pirp );
- return;
- }
-
- if( pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY )
- {
- status = umss_bulkonly_startio( pdev_ext, io_packet );
- }
- else if( pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
- || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI )
- {
- status = umss_cbi_startio( pdev_ext, io_packet );
- }
- else
- {
- status = STATUS_DEVICE_PROTOCOL_ERROR;
- }
- usb_unlock_dev( pdev );
- UMSS_COMPLETE_START_IO( dev_obj, status, io_packet->pirp );
- return;
+ NTSTATUS status;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUSB_DEV pdev;
+
+ pdev_ext = dev_obj->DeviceExtension;
+
+ // lock the dev, the pdev_ext->pif_desc won't go away.
+ if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS)
+ {
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_start_io(): error, device is not valid\n"));
+ UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp);
+ return;
+ }
+
+ if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY)
+ {
+ status = umss_bulkonly_startio(pdev_ext, io_packet);
+ }
+ else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
+ || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
+ {
+ status = umss_cbi_startio(pdev_ext, io_packet);
+ }
+ else
+ {
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+ usb_unlock_dev(pdev);
+ UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp);
+ return;
}
VOID
-umss_start_io(
-IN PDEVICE_OBJECT dev_obj,
-IN PIRP irp
-)
+umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
{
- KIRQL irql;
- ULONG ctrl_code;
- NTSTATUS status;
- PIO_STACK_LOCATION irp_stack;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- IO_PACKET io_packet;
- PUSER_IO_PACKET user_io_packet;
-
- USE_IRQL;
-
- if( dev_obj == NULL || irp == NULL )
- return;
-
- status = STATUS_SUCCESS;
-
- irp_stack = IoGetCurrentIrpStackLocation( irp );
- ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )dev_obj->DeviceExtension;
-
- if( irp_stack->MajorFunction == IRP_MJ_SCSI )
- {
- umss_process_srb( dev_obj, irp );
- return;
- }
-
- if( irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL )
- {
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp );
- }
-
- switch( ctrl_code )
- {
- case IOCTL_UMSS_SUBMIT_CDB_IN:
- case IOCTL_UMSS_SUBMIT_CDB_OUT:
- case IOCTL_UMSS_SUBMIT_CDB:
- {
- PUSB_DEV pdev;
-
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( USER_IO_PACKET ) )
- {
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
- }
-
- user_io_packet = ( PUSER_IO_PACKET )irp->AssociatedIrp.SystemBuffer;
-
- if( user_io_packet->sub_class != pdev_ext->pif_desc->bInterfaceSubClass )
- {
- // not agree with the dev's subclass
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_DEVICE_PROTOCOL_ERROR, irp );
- }
-
- RtlZeroMemory( &io_packet, sizeof( io_packet ) );
- io_packet.cdb_length = user_io_packet->cdb_length;
- io_packet.lun = user_io_packet->lun;
-
- RtlCopyMemory( io_packet.cdb, user_io_packet->cdb, MAX_CDB_LENGTH );
-
- if( ctrl_code == IOCTL_UMSS_SUBMIT_CDB_IN )
- io_packet.flags |= USB_DIR_IN;
-
- if( ctrl_code != IOCTL_UMSS_SUBMIT_CDB )
- {
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength == 0 )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_BUFFER_TOO_SMALL, irp );
-
- io_packet.data_buffer = MmGetSystemAddressForMdl( irp->MdlAddress );
- io_packet.data_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
-
- if( io_packet.data_length > MAX_BULK_TRANSFER_LENGTH )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_BUFFER_TOO_SMALL, irp );
-
- //synchronize the buffer
- if( io_packet.flags & USB_DIR_IN )
- KeFlushIoBuffers( irp->MdlAddress, TRUE, TRUE );
- else
- KeFlushIoBuffers( irp->MdlAddress, FALSE, TRUE );
- }
-
- io_packet.pirp = irp;
- umss_submit_io_packet( dev_obj, &io_packet );
- return;
- }
- case IOCTL_SCSI_PASS_THROUGH:
- {
- PSCSI_PASS_THROUGH pass_through;
- IO_PACKET io_packet;
-
- pass_through = irp->AssociatedIrp.SystemBuffer;
-
- if( pass_through->DataTransferLength &&
- pass_through->DataBufferOffset != sizeof( SCSI_PASS_THROUGH ) )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
-
- if( pass_through->SenseInfoLength &&
- ( pass_through->SenseInfoOffset !=
- pass_through->DataBufferOffset + pass_through->DataTransferLength ) )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
-
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength <
- ( sizeof( SCSI_PASS_THROUGH ) +
- pass_through->SenseInfoLength +
- pass_through->DataTransferLength ) )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_BUFFER_TOO_SMALL, irp );
-
- RtlZeroMemory( &io_packet, sizeof( io_packet ) );
-
- io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
- if( pass_through->DataIn )
- io_packet.flags |= IOP_FLAG_DIR_IN;
-
- io_packet.data_buffer = ( PVOID )&pass_through[ 1 ];
- io_packet.data_length = pass_through->DataTransferLength;
-
- if( pass_through->SenseInfoLength )
- {
- io_packet.sense_data = ( ( PUCHAR )pass_through ) + pass_through->SenseInfoOffset;
- io_packet.sense_data_length = pass_through->SenseInfoLength;
- io_packet.flags |= IOP_FLAG_REQ_SENSE;
- }
-
- io_packet.cdb_length = pass_through->CdbLength;
- RtlCopyMemory( io_packet.cdb, pass_through->Cdb, sizeof( io_packet.cdb ) );
- io_packet.lun = 0;
- io_packet.pirp = irp;
- umss_submit_io_packet( dev_obj, &io_packet );
- return;
- }
- case IOCTL_SCSI_PASS_THROUGH_DIRECT:
- {
- PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
- IO_PACKET io_packet;
-
- pass_through_direct = irp->AssociatedIrp.SystemBuffer;
-
- if( pass_through_direct->SenseInfoLength &&
- pass_through_direct->SenseInfoOffset != sizeof( SCSI_PASS_THROUGH_DIRECT ) )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_PARAMETER, irp );
-
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength <
- sizeof( SCSI_PASS_THROUGH_DIRECT ) + pass_through_direct->SenseInfoLength )
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_BUFFER_TOO_SMALL, irp );
-
- RtlZeroMemory( &io_packet, sizeof( io_packet ) );
-
- io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
- if( pass_through_direct->DataIn )
- io_packet.flags |= IOP_FLAG_DIR_IN;
-
- io_packet.data_buffer = pass_through_direct->DataBuffer;
- io_packet.data_length = pass_through_direct->DataTransferLength;
-
- if( pass_through_direct->SenseInfoLength )
- {
- io_packet.sense_data = ( ( PUCHAR )pass_through_direct ) + pass_through_direct->SenseInfoOffset;
- io_packet.sense_data_length = pass_through_direct->SenseInfoLength;
- io_packet.flags |= IOP_FLAG_REQ_SENSE;
- }
-
- io_packet.cdb_length = pass_through_direct->CdbLength;
- RtlCopyMemory( io_packet.cdb, pass_through_direct->Cdb, sizeof( io_packet.cdb ) );
- io_packet.lun = 0;
- io_packet.pirp = irp;
- umss_submit_io_packet( dev_obj, &io_packet );
- return;
- }
- case IOCTL_SUBMIT_URB_RD:
- case IOCTL_SUBMIT_URB_NOIO:
- case IOCTL_SUBMIT_URB_WR:
- {
- gendrv_startio( dev_obj, irp );
- return;
- }
- default:
- UMSS_COMPLETE_START_IO( dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp );
- }
- return;
+ KIRQL irql;
+ ULONG ctrl_code;
+ NTSTATUS status;
+ PIO_STACK_LOCATION irp_stack;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ IO_PACKET io_packet;
+ PUSER_IO_PACKET user_io_packet;
+
+ USE_IRQL;
+
+ if (dev_obj == NULL || irp == NULL)
+ return;
+
+ status = STATUS_SUCCESS;
+
+ irp_stack = IoGetCurrentIrpStackLocation(irp);
+ ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
+
+ if (irp_stack->MajorFunction == IRP_MJ_SCSI)
+ {
+ umss_process_srb(dev_obj, irp);
+ return;
+ }
+
+ if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
+ {
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
+ }
+
+ switch (ctrl_code)
+ {
+ case IOCTL_UMSS_SUBMIT_CDB_IN:
+ case IOCTL_UMSS_SUBMIT_CDB_OUT:
+ case IOCTL_UMSS_SUBMIT_CDB:
+ {
+ PUSB_DEV pdev;
+
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(USER_IO_PACKET))
+ {
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+ }
+
+ user_io_packet = (PUSER_IO_PACKET) irp->AssociatedIrp.SystemBuffer;
+
+ if (user_io_packet->sub_class != pdev_ext->pif_desc->bInterfaceSubClass)
+ {
+ // not agree with the dev's subclass
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_DEVICE_PROTOCOL_ERROR, irp);
+ }
+
+ RtlZeroMemory(&io_packet, sizeof(io_packet));
+ io_packet.cdb_length = user_io_packet->cdb_length;
+ io_packet.lun = user_io_packet->lun;
+
+ RtlCopyMemory(io_packet.cdb, user_io_packet->cdb, MAX_CDB_LENGTH);
+
+ if (ctrl_code == IOCTL_UMSS_SUBMIT_CDB_IN)
+ io_packet.flags |= USB_DIR_IN;
+
+ if (ctrl_code != IOCTL_UMSS_SUBMIT_CDB)
+ {
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength == 0)
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
+
+ io_packet.data_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
+ io_packet.data_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
+
+ if (io_packet.data_length > MAX_BULK_TRANSFER_LENGTH)
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
+
+ //synchronize the buffer
+ if (io_packet.flags & USB_DIR_IN)
+ KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
+ else
+ KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
+ }
+
+ io_packet.pirp = irp;
+ umss_submit_io_packet(dev_obj, &io_packet);
+ return;
+ }
+ case IOCTL_SCSI_PASS_THROUGH:
+ {
+ PSCSI_PASS_THROUGH pass_through;
+ IO_PACKET io_packet;
+
+ pass_through = irp->AssociatedIrp.SystemBuffer;
+
+ if (pass_through->DataTransferLength &&
+ pass_through->DataBufferOffset != sizeof(SCSI_PASS_THROUGH))
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+
+ if (pass_through->SenseInfoLength &&
+ (pass_through->SenseInfoOffset !=
+ pass_through->DataBufferOffset + pass_through->DataTransferLength))
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength <
+ (sizeof(SCSI_PASS_THROUGH) +
+ pass_through->SenseInfoLength + pass_through->DataTransferLength))
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
+
+ RtlZeroMemory(&io_packet, sizeof(io_packet));
+
+ io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
+ if (pass_through->DataIn)
+ io_packet.flags |= IOP_FLAG_DIR_IN;
+
+ io_packet.data_buffer = (PVOID) & pass_through[1];
+ io_packet.data_length = pass_through->DataTransferLength;
+
+ if (pass_through->SenseInfoLength)
+ {
+ io_packet.sense_data = ((PUCHAR) pass_through) + pass_through->SenseInfoOffset;
+ io_packet.sense_data_length = pass_through->SenseInfoLength;
+ io_packet.flags |= IOP_FLAG_REQ_SENSE;
+ }
+
+ io_packet.cdb_length = pass_through->CdbLength;
+ RtlCopyMemory(io_packet.cdb, pass_through->Cdb, sizeof(io_packet.cdb));
+ io_packet.lun = 0;
+ io_packet.pirp = irp;
+ umss_submit_io_packet(dev_obj, &io_packet);
+ return;
+ }
+ case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+ {
+ PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
+ IO_PACKET io_packet;
+
+ pass_through_direct = irp->AssociatedIrp.SystemBuffer;
+
+ if (pass_through_direct->SenseInfoLength &&
+ pass_through_direct->SenseInfoOffset != sizeof(SCSI_PASS_THROUGH_DIRECT))
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
+
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength <
+ sizeof(SCSI_PASS_THROUGH_DIRECT) + pass_through_direct->SenseInfoLength)
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
+
+ RtlZeroMemory(&io_packet, sizeof(io_packet));
+
+ io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
+ if (pass_through_direct->DataIn)
+ io_packet.flags |= IOP_FLAG_DIR_IN;
+
+ io_packet.data_buffer = pass_through_direct->DataBuffer;
+ io_packet.data_length = pass_through_direct->DataTransferLength;
+
+ if (pass_through_direct->SenseInfoLength)
+ {
+ io_packet.sense_data = ((PUCHAR) pass_through_direct) + pass_through_direct->SenseInfoOffset;
+ io_packet.sense_data_length = pass_through_direct->SenseInfoLength;
+ io_packet.flags |= IOP_FLAG_REQ_SENSE;
+ }
+
+ io_packet.cdb_length = pass_through_direct->CdbLength;
+ RtlCopyMemory(io_packet.cdb, pass_through_direct->Cdb, sizeof(io_packet.cdb));
+ io_packet.lun = 0;
+ io_packet.pirp = irp;
+ umss_submit_io_packet(dev_obj, &io_packet);
+ return;
+ }
+ case IOCTL_SUBMIT_URB_RD:
+ case IOCTL_SUBMIT_URB_NOIO:
+ case IOCTL_SUBMIT_URB_WR:
+ {
+ gendrv_startio(dev_obj, irp);
+ return;
+ }
+ default:
+ UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
+ }
+ return;
}
-NTSTATUS
-umss_dispatch_routine(
-PDEVICE_OBJECT pdev_obj,
-PIRP irp
-)
// bugbug!!! there can not be sent IOCTL_SUBMIT_URB_XXX while
// the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device.
// not resolved yet.
+NTSTATUS
+umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp)
{
- KIRQL irql;
- ULONG ctrl_code;
- NTSTATUS status;
- PIO_STACK_LOCATION irp_stack;
- PUMSS_DEVICE_EXTENSION pdev_ext;
-
- USE_IRQL;
-
- if( pdev_obj == NULL || irp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- status = STATUS_SUCCESS;
- irp_stack = IoGetCurrentIrpStackLocation (irp);
- ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )pdev_obj->DeviceExtension;
-
- switch( irp_stack->MajorFunction )
- {
- case IRP_MJ_CREATE:
- case IRP_MJ_CLOSE:
- {
- return dev_mgr_dispatch( pdev_ext->dev_mgr, irp );
- }
- case IRP_MJ_INTERNAL_DEVICE_CONTROL:
- {
- // function code to receive scsi request
- UMSS_EXIT_DISPATCH( pdev_obj, STATUS_PENDING, irp );
- }
- case IRP_MJ_DEVICE_CONTROL:
- {
- switch( ctrl_code )
- {
- case IOCTL_UMSS_SET_FDO:
- {
- PDEVICE_OBJECT fdo;
- PUSB_DEV pdev;
- USE_IRQL;
-
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( PDEVICE_OBJECT ) ) {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
-
- fdo = ( PDEVICE_OBJECT )( ( PULONG )irp->AssociatedIrp.SystemBuffer )[ 0 ];
- if( fdo == NULL )
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- //
- // we have to test the usb dev's state to determine whether set or not the fdo
- //
-
- if( usb_query_and_lock_dev( pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev ) != STATUS_SUCCESS )
- EXIT_DISPATCH( STATUS_DEVICE_DOES_NOT_EXIST, irp );
-
- lock_dev( pdev, FALSE );
-
- if( dev_state( pdev ) >= USB_DEV_STATE_BEFORE_ZOMB ||
- dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
- EXIT_DISPATCH( STATUS_DEVICE_DOES_NOT_EXIST, irp );
- }
-
- pdev_ext->fdo = fdo;
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
- irp->IoStatus.Information = 0;
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
-
- case IOCTL_GET_DEV_DESC:
- {
- PGET_DEV_DESC_REQ pgddr;
- if( irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof( GET_DEV_DESC_REQ ) )
- {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
- pgddr = irp->AssociatedIrp.SystemBuffer;
- if( pgddr->dev_handle != ( pdev_ext->dev_handle & 0xffff0000 ) )
- {
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
- // an immediate request
- return dev_mgr_dispatch( pdev_ext->dev_mgr, irp );
- }
- case IOCTL_SUBMIT_URB_RD:
- case IOCTL_SUBMIT_URB_NOIO:
- case IOCTL_SUBMIT_URB_WR:
- {
- PURB purb;
- DEV_HANDLE endp_handle;
-
- 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( !default_endp_handle( endp_handle ) )
- {
- //no permit to other interface if interface dev
- if( ( pdev_ext->flags & UMSS_DEV_FLAG_IF_DEV )
- && if_idx_from_handle( endp_handle ) != pdev_ext->if_idx )
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
- }
- // FIXME: this is dangeous
- // return dev_mgr_dispatch( pdev_ext->dev_mgr, irp );
- UMSS_EXIT_DISPATCH( pdev_obj, STATUS_PENDING, irp );
- }
- case IOCTL_GET_DEV_HANDLE:
- {
- PUCHAR user_buffer;
- ULONG user_buffer_length;
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( LONG ) )
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
-
- *( ( PLONG )irp->AssociatedIrp.SystemBuffer ) = pdev_ext->dev_handle;
- irp->IoStatus.Information = sizeof( LONG );
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
-
- //
- // request from scsi class driver
- //
- case IOCTL_SCSI_PASS_THROUGH:
- case IOCTL_SCSI_PASS_THROUGH_DIRECT:
- //
- // direct cdb request
- //
- case IOCTL_UMSS_SUBMIT_CDB:
- case IOCTL_UMSS_SUBMIT_CDB_OUT:
- case IOCTL_UMSS_SUBMIT_CDB_IN:
- {
- UMSS_EXIT_DISPATCH( pdev_obj, STATUS_PENDING, irp );
- }
- case IOCTL_SCSI_GET_INQUIRY_DATA:
- {
- PSCSI_ADAPTER_BUS_INFO adapter_info;
- PSCSI_BUS_DATA bus_data;
- PSCSI_INQUIRY_DATA inq_dat;
- PINQUIRYDATA inq;
- IO_PACKET io_packet;
- ULONG required_size;
-
- required_size = sizeof( SCSI_ADAPTER_BUS_INFO )
- + sizeof( SCSI_BUS_DATA )
- + sizeof( SCSI_INQUIRY_DATA )
- + INQUIRYDATABUFFERSIZE;
-
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < required_size )
- UMSS_EXIT_DISPATCH( pdev_obj, STATUS_BUFFER_TOO_SMALL, irp );
-
- RtlZeroMemory( &io_packet, sizeof( io_packet ) );
-
- adapter_info = irp->AssociatedIrp.SystemBuffer;
- adapter_info->NumberOfBuses = 1;
- bus_data = &adapter_info->BusData[ 0 ];
- bus_data->NumberOfLogicalUnits = 1;
- bus_data->InitiatorBusId = 0;
- bus_data->InquiryDataOffset = sizeof( SCSI_ADAPTER_BUS_INFO );
- inq_dat = ( PVOID )&bus_data[ 1 ];
- inq_dat->PathId = 0;
- inq_dat->TargetId = pdev_ext->umss_dev_id;
- //
- // this is the dev_id for usb dev_manager
- //
- inq_dat->Lun = ( UCHAR )( pdev_ext->dev_handle >> 16 );
- inq_dat->DeviceClaimed = FALSE;
- inq_dat->InquiryDataLength = 36;
- inq_dat->NextInquiryDataOffset = 0;
- inq = ( PINQUIRYDATA )inq_dat->InquiryData;
-
- RtlZeroMemory( inq, sizeof( INQUIRYDATA ) );
- inq->DeviceType = DIRECT_ACCESS_DEVICE;
- inq->DeviceTypeQualifier = 0;
- inq->RemovableMedia = 1;
-
- //
- // pretend to comply scsi primary 2 command set
- //
-
- inq->Versions = 0x04;
-
- //
- // the format is in scsi-2 format
- //
-
- inq->ResponseDataFormat = 0x02;
-
- //
- // we are the poor scsi device
- //
-
- inq->AdditionalLength = 31;
- inq->SoftReset = 0;
- inq->CommandQueue = 0;
- inq->LinkedCommands = 0;
- inq->RelativeAddressing = 0;
- RtlCopyMemory( &inq->VendorId, "Unknown", 7 );
- RtlCopyMemory( &inq->ProductId, "USB Mass Storage", 16 );
- irp->IoStatus.Information = required_size;
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- case IOCTL_SCSI_GET_CAPABILITIES:
- {
- PIO_SCSI_CAPABILITIES port_cap;
-
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( IO_SCSI_CAPABILITIES ) )
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
-
- port_cap = ( PIO_SCSI_CAPABILITIES ) irp->AssociatedIrp.SystemBuffer;
- port_cap->Length = sizeof( IO_SCSI_CAPABILITIES );
- port_cap->MaximumTransferLength = 65536;
- port_cap->MaximumPhysicalPages = 65536 / PAGE_SIZE;
- port_cap->SupportedAsynchronousEvents = 0;
- port_cap->AlignmentMask = 0x10;
- port_cap->TaggedQueuing = FALSE;
- port_cap->AdapterScansDown = FALSE;
- port_cap->AdapterUsesPio = FALSE;
- irp->IoStatus.Information = sizeof( IO_SCSI_CAPABILITIES );
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- case IOCTL_SCSI_GET_ADDRESS:
- {
- PSCSI_ADDRESS paddr;
- if( irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( SCSI_ADDRESS ) )
- EXIT_DISPATCH( STATUS_INVALID_PARAMETER, irp );
-
- paddr = ( PSCSI_ADDRESS )irp->AssociatedIrp.SystemBuffer;
-
- paddr->Length = sizeof( SCSI_ADDRESS );
- paddr->PortNumber = 0;
- paddr->PathId = 0;
- paddr->TargetId = pdev_ext->umss_dev_id;
- paddr->Lun = ( UCHAR )( pdev_ext->dev_handle >> 16 );
- irp->IoStatus.Information = sizeof( SCSI_ADDRESS );
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- case IOCTL_SCSI_RESCAN_BUS:
- {
- irp->IoStatus.Information = 0;
- EXIT_DISPATCH( STATUS_SUCCESS, irp );
- }
- default:
- {
- EXIT_DISPATCH( STATUS_INVALID_DEVICE_REQUEST, irp );
- }
- }
- }
- }
- EXIT_DISPATCH( STATUS_NOT_SUPPORTED, irp );
+ KIRQL irql;
+ ULONG ctrl_code;
+ NTSTATUS status;
+ PIO_STACK_LOCATION irp_stack;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+
+ USE_IRQL;
+
+ if (pdev_obj == NULL || irp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ status = STATUS_SUCCESS;
+ irp_stack = IoGetCurrentIrpStackLocation(irp);
+ ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
+
+ switch (irp_stack->MajorFunction)
+ {
+ case IRP_MJ_CREATE:
+ case IRP_MJ_CLOSE:
+ {
+ return dev_mgr_dispatch(pdev_ext->dev_mgr, irp);
+ }
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+ {
+ // function code to receive scsi request
+ UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
+ }
+ case IRP_MJ_DEVICE_CONTROL:
+ {
+ switch (ctrl_code)
+ {
+ case IOCTL_UMSS_SET_FDO:
+ {
+ PDEVICE_OBJECT fdo;
+ PUSB_DEV pdev;
+ USE_IRQL;
+
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PDEVICE_OBJECT))
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+
+ fdo = (PDEVICE_OBJECT) ((PULONG) irp->AssociatedIrp.SystemBuffer)[0];
+ if (fdo == NULL)
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ //
+ // we have to test the usb dev's state to determine whether set or not the fdo
+ //
+
+ if (usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev) !=
+ STATUS_SUCCESS)
+ EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp);
+
+ lock_dev(pdev, FALSE);
+
+ if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB || dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+ EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp);
+ }
+
+ pdev_ext->fdo = fdo;
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+ irp->IoStatus.Information = 0;
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+
+ case IOCTL_GET_DEV_DESC:
+ {
+ PGET_DEV_DESC_REQ pgddr;
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+ pgddr = irp->AssociatedIrp.SystemBuffer;
+ if (pgddr->dev_handle != (pdev_ext->dev_handle & 0xffff0000))
+ {
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+ // an immediate request
+ return dev_mgr_dispatch(pdev_ext->dev_mgr, irp);
+ }
+ case IOCTL_SUBMIT_URB_RD:
+ case IOCTL_SUBMIT_URB_NOIO:
+ case IOCTL_SUBMIT_URB_WR:
+ {
+ PURB purb;
+ DEV_HANDLE endp_handle;
+
+ 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 (!default_endp_handle(endp_handle))
+ {
+ //no permit to other interface if interface dev
+ if ((pdev_ext->flags & UMSS_DEV_FLAG_IF_DEV)
+ && if_idx_from_handle(endp_handle) != pdev_ext->if_idx)
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+ }
+ // FIXME: this is dangeous
+ // return dev_mgr_dispatch( pdev_ext->dev_mgr, irp );
+ UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
+ }
+ case IOCTL_GET_DEV_HANDLE:
+ {
+ PUCHAR user_buffer;
+ ULONG user_buffer_length;
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+
+ *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
+ irp->IoStatus.Information = sizeof(LONG);
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+
+ //
+ // request from scsi class driver
+ //
+ case IOCTL_SCSI_PASS_THROUGH:
+ case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+ //
+ // direct cdb request
+ //
+ case IOCTL_UMSS_SUBMIT_CDB:
+ case IOCTL_UMSS_SUBMIT_CDB_OUT:
+ case IOCTL_UMSS_SUBMIT_CDB_IN:
+ {
+ UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
+ }
+ case IOCTL_SCSI_GET_INQUIRY_DATA:
+ {
+ PSCSI_ADAPTER_BUS_INFO adapter_info;
+ PSCSI_BUS_DATA bus_data;
+ PSCSI_INQUIRY_DATA inq_dat;
+ PINQUIRYDATA inq;
+ IO_PACKET io_packet;
+ ULONG required_size;
+
+ required_size = sizeof(SCSI_ADAPTER_BUS_INFO)
+ + sizeof(SCSI_BUS_DATA) + sizeof(SCSI_INQUIRY_DATA) + INQUIRYDATABUFFERSIZE;
+
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < required_size)
+ UMSS_EXIT_DISPATCH(pdev_obj, STATUS_BUFFER_TOO_SMALL, irp);
+
+ RtlZeroMemory(&io_packet, sizeof(io_packet));
+
+ adapter_info = irp->AssociatedIrp.SystemBuffer;
+ adapter_info->NumberOfBuses = 1;
+ bus_data = &adapter_info->BusData[0];
+ bus_data->NumberOfLogicalUnits = 1;
+ bus_data->InitiatorBusId = 0;
+ bus_data->InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
+ inq_dat = (PVOID) & bus_data[1];
+ inq_dat->PathId = 0;
+ inq_dat->TargetId = pdev_ext->umss_dev_id;
+ //
+ // this is the dev_id for usb dev_manager
+ //
+ inq_dat->Lun = (UCHAR) (pdev_ext->dev_handle >> 16);
+ inq_dat->DeviceClaimed = FALSE;
+ inq_dat->InquiryDataLength = 36;
+ inq_dat->NextInquiryDataOffset = 0;
+ inq = (PINQUIRYDATA) inq_dat->InquiryData;
+
+ RtlZeroMemory(inq, sizeof(INQUIRYDATA));
+ inq->DeviceType = DIRECT_ACCESS_DEVICE;
+ inq->DeviceTypeQualifier = 0;
+ inq->RemovableMedia = 1;
+
+ //
+ // pretend to comply scsi primary 2 command set
+ //
+
+ inq->Versions = 0x04;
+
+ //
+ // the format is in scsi-2 format
+ //
+
+ inq->ResponseDataFormat = 0x02;
+
+ //
+ // we are the poor scsi device
+ //
+
+ inq->AdditionalLength = 31;
+ inq->SoftReset = 0;
+ inq->CommandQueue = 0;
+ inq->LinkedCommands = 0;
+ inq->RelativeAddressing = 0;
+ RtlCopyMemory(&inq->VendorId, "Unknown", 7);
+ RtlCopyMemory(&inq->ProductId, "USB Mass Storage", 16);
+ irp->IoStatus.Information = required_size;
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ case IOCTL_SCSI_GET_CAPABILITIES:
+ {
+ PIO_SCSI_CAPABILITIES port_cap;
+
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength <
+ sizeof(IO_SCSI_CAPABILITIES))
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+
+ port_cap = (PIO_SCSI_CAPABILITIES) irp->AssociatedIrp.SystemBuffer;
+ port_cap->Length = sizeof(IO_SCSI_CAPABILITIES);
+ port_cap->MaximumTransferLength = 65536;
+ port_cap->MaximumPhysicalPages = 65536 / PAGE_SIZE;
+ port_cap->SupportedAsynchronousEvents = 0;
+ port_cap->AlignmentMask = 0x10;
+ port_cap->TaggedQueuing = FALSE;
+ port_cap->AdapterScansDown = FALSE;
+ port_cap->AdapterUsesPio = FALSE;
+ irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ case IOCTL_SCSI_GET_ADDRESS:
+ {
+ PSCSI_ADDRESS paddr;
+ if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SCSI_ADDRESS))
+ EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
+
+ paddr = (PSCSI_ADDRESS) irp->AssociatedIrp.SystemBuffer;
+
+ paddr->Length = sizeof(SCSI_ADDRESS);
+ paddr->PortNumber = 0;
+ paddr->PathId = 0;
+ paddr->TargetId = pdev_ext->umss_dev_id;
+ paddr->Lun = (UCHAR) (pdev_ext->dev_handle >> 16);
+ irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ case IOCTL_SCSI_RESCAN_BUS:
+ {
+ irp->IoStatus.Information = 0;
+ EXIT_DISPATCH(STATUS_SUCCESS, irp);
+ }
+ default:
+ {
+ EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
+ }
+ }
+ }
+ }
+ EXIT_DISPATCH(STATUS_NOT_SUPPORTED, irp);
}
VOID
-umss_reset_pipe_completion(
-PURB purb,
-PVOID context
-)
+umss_reset_pipe_completion(PURB purb, PVOID context)
{
- PUMSS_DEVICE_EXTENSION pdev_ext;
- if( context == NULL )
- return;
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )context;
- pdev_ext->reset_pipe_status = purb->status;
- KeSetEvent( &pdev_ext->sync_event, 0, FALSE );
- return;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ if (context == NULL)
+ return;
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
+ pdev_ext->reset_pipe_status = purb->status;
+ KeSetEvent(&pdev_ext->sync_event, 0, FALSE);
+ return;
}
-NTSTATUS
-umss_reset_pipe(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-DEV_HANDLE endp_handle
-)
//can only be called at passive level
+NTSTATUS
+umss_reset_pipe(PUMSS_DEVICE_EXTENSION pdev_ext, DEV_HANDLE endp_handle)
{
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
-
- if( pdev_ext == NULL )
- return STATUS_INVALID_PARAMETER;
-
- status = usb_query_and_lock_dev( pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev );
-
- if( status != STATUS_SUCCESS )
- return STATUS_UNSUCCESSFUL;
-
- status = usb_reset_pipe_ex(
- pdev_ext->dev_mgr,
- endp_handle,
- umss_reset_pipe_completion,
- pdev_ext );
-
- if( status == STATUS_PENDING )
- {
- KeWaitForSingleObject(
- &pdev_ext->sync_event,
- Executive,
- KernelMode,
- TRUE,
- NULL );
- status = pdev_ext->reset_pipe_status;
- }
- usb_unlock_dev( pdev );
- return status;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+
+ if (pdev_ext == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev);
+
+ if (status != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+
+ status = usb_reset_pipe_ex(pdev_ext->dev_mgr, endp_handle, umss_reset_pipe_completion, pdev_ext);
+
+ if (status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL);
+ status = pdev_ext->reset_pipe_status;
+ }
+ usb_unlock_dev(pdev);
+ return status;
}
BOOL
-umss_gen_result_srb(
-PIO_PACKET io_packet,
-PSCSI_REQUEST_BLOCK srb,
-NTSTATUS status
-)
+umss_gen_result_srb(PIO_PACKET io_packet, PSCSI_REQUEST_BLOCK srb, NTSTATUS status)
{
- if( srb == NULL || io_packet == NULL )
- {
- return FALSE;
- }
- if( status == STATUS_SUCCESS )
- {
- PULONG dest_buf, src_buf;
- ULONG i;
-
- srb->SrbStatus = SRB_STATUS_SUCCESS;
-
- io_packet->pirp->IoStatus.Information = srb->DataTransferLength;
- if( ( io_packet->pirp->Flags & IRP_READ_OPERATION ) && !( io_packet->pirp->Flags & IRP_PAGING_IO ) )
- {
- src_buf = ( PULONG )io_packet->data_buffer;
- dest_buf = ( PULONG )srb->DataBuffer;
- if( src_buf && dest_buf )
- {
- for( i = 0; i < ( srb->DataTransferLength >> 2 ); i++ )
- {
- dest_buf[ i ] = src_buf[ i ];
- }
- }
- }
- }
- else if( status == STATUS_DEVICE_DOES_NOT_EXIST )
- {
- PSENSE_DATA sense_buf;
- srb->SrbStatus = SRB_STATUS_NO_DEVICE;
- srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
-
- //
- // let's build the srb status for class driver
- //
-
- srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- sense_buf = ( PSENSE_DATA )srb->SenseInfoBuffer;
-
- if( !( srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE ) )
- {
- RtlZeroMemory( srb->SenseInfoBuffer, srb->SenseInfoBufferLength );
- sense_buf->ErrorCode = 0x70;
- sense_buf->Valid = 1;
- sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
- sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
- sense_buf->AdditionalSenseLength = 10;
- }
- }
- else if( status == USB_STATUS_STALL_PID || status == USB_STATUS_CRC ||
- status == USB_STATUS_BTSTUFF || status == USB_STATUS_DATA_OVERRUN )
- {
- PSENSE_DATA sense_buf;
- srb->SrbStatus = SRB_STATUS_ERROR;
- srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
-
- srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- sense_buf = ( PSENSE_DATA )srb->SenseInfoBuffer;
-
- if( !( srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE ) )
- {
- RtlZeroMemory( srb->SenseInfoBuffer, srb->SenseInfoBufferLength );
- sense_buf->ErrorCode = 0x70;
- sense_buf->Valid = 1;
- sense_buf->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
- sense_buf->AdditionalSenseCode = 0;
- sense_buf->AdditionalSenseLength = 10;
- }
- }
- else
- {
- srb->SrbStatus = SRB_STATUS_ERROR;
- }
-
- if( ( io_packet->pirp->Flags & ( IRP_READ_OPERATION | IRP_WRITE_OPERATION ) ) && !( io_packet->pirp->Flags & IRP_PAGING_IO ) )
- {
- if( io_packet->data_buffer )
- {
- usb_free_mem( io_packet->data_buffer );
- io_packet->data_buffer = NULL;
- }
- }
- return TRUE;
+ if (srb == NULL || io_packet == NULL)
+ {
+ return FALSE;
+ }
+ if (status == STATUS_SUCCESS)
+ {
+ PULONG dest_buf, src_buf;
+ ULONG i;
+
+ srb->SrbStatus = SRB_STATUS_SUCCESS;
+
+ io_packet->pirp->IoStatus.Information = srb->DataTransferLength;
+ if ((io_packet->pirp->Flags & IRP_READ_OPERATION) && !(io_packet->pirp->Flags & IRP_PAGING_IO))
+ {
+ src_buf = (PULONG) io_packet->data_buffer;
+ dest_buf = (PULONG) srb->DataBuffer;
+ if (src_buf && dest_buf)
+ {
+ for(i = 0; i < (srb->DataTransferLength >> 2); i++)
+ {
+ dest_buf[i] = src_buf[i];
+ }
+ }
+ }
+ }
+ else if (status == STATUS_DEVICE_DOES_NOT_EXIST)
+ {
+ PSENSE_DATA sense_buf;
+ srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+
+ //
+ // let's build the srb status for class driver
+ //
+
+ srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
+
+ if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
+ {
+ RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
+ sense_buf->ErrorCode = 0x70;
+ sense_buf->Valid = 1;
+ sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
+ sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
+ sense_buf->AdditionalSenseLength = 10;
+ }
+ }
+ else if (status == USB_STATUS_STALL_PID || status == USB_STATUS_CRC ||
+ status == USB_STATUS_BTSTUFF || status == USB_STATUS_DATA_OVERRUN)
+ {
+ PSENSE_DATA sense_buf;
+ srb->SrbStatus = SRB_STATUS_ERROR;
+ srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+
+ srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
+
+ if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
+ {
+ RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
+ sense_buf->ErrorCode = 0x70;
+ sense_buf->Valid = 1;
+ sense_buf->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
+ sense_buf->AdditionalSenseCode = 0;
+ sense_buf->AdditionalSenseLength = 10;
+ }
+ }
+ else
+ {
+ srb->SrbStatus = SRB_STATUS_ERROR;
+ }
+
+ if ((io_packet->pirp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION))
+ && !(io_packet->pirp->Flags & IRP_PAGING_IO))
+ {
+ if (io_packet->data_buffer)
+ {
+ usb_free_mem(io_packet->data_buffer);
+ io_packet->data_buffer = NULL;
+ }
+ }
+ return TRUE;
}
BOOL
-umss_gen_result_ctrl(
-PDEVICE_OBJECT dev_obj,
-PIRP irp,
-NTSTATUS status
-)
+umss_gen_result_ctrl(PDEVICE_OBJECT dev_obj, PIRP irp, NTSTATUS status)
{
- PIO_STACK_LOCATION irp_stack;
- ULONG ctrl_code;
- PUMSS_DEVICE_EXTENSION pdev_ext;
-
- if( irp == NULL )
- return FALSE;
-
- irp->IoStatus.Information = 0;
- irp_stack = IoGetCurrentIrpStackLocation ( irp );
- ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
- pdev_ext = dev_obj->DeviceExtension;
-
- switch( ctrl_code )
- {
- case IOCTL_SCSI_PASS_THROUGH:
- {
- PSCSI_PASS_THROUGH pass_through;
- pass_through = irp->AssociatedIrp.SystemBuffer;
- irp->IoStatus.Status = status;
-
- // we have set these two value in bulkonly.c when data transfer complete
- // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
- // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
-
- if( status == STATUS_SUCCESS )
- irp->IoStatus.Information = pass_through->SenseInfoOffset + pass_through->SenseInfoLength;
- else
- pass_through->ScsiStatus = SCSISTAT_CHECK_CONDITION;
- return TRUE;
- }
- case IOCTL_SCSI_PASS_THROUGH_DIRECT:
- {
- PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
-
- pass_through_direct = irp->AssociatedIrp.SystemBuffer;
- pass_through_direct->ScsiStatus = 0;
- irp->IoStatus.Status = status;
-
- // we have set these two value in bulkonly.c when data transfer complete
- // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
- // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
-
- if( status == STATUS_SUCCESS )
- irp->IoStatus.Information = pass_through_direct->SenseInfoOffset + pass_through_direct->SenseInfoLength;
- else
- pass_through_direct->ScsiStatus = SCSISTAT_CHECK_CONDITION;
-
- return TRUE;
- }
- }
- return FALSE;
+ PIO_STACK_LOCATION irp_stack;
+ ULONG ctrl_code;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+
+ if (irp == NULL)
+ return FALSE;
+
+ irp->IoStatus.Information = 0;
+ irp_stack = IoGetCurrentIrpStackLocation(irp);
+ ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
+ pdev_ext = dev_obj->DeviceExtension;
+
+ switch (ctrl_code)
+ {
+ case IOCTL_SCSI_PASS_THROUGH:
+ {
+ PSCSI_PASS_THROUGH pass_through;
+ pass_through = irp->AssociatedIrp.SystemBuffer;
+ irp->IoStatus.Status = status;
+
+ // we have set these two value in bulkonly.c when data transfer complete
+ // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
+ // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
+
+ if (status == STATUS_SUCCESS)
+ irp->IoStatus.Information = pass_through->SenseInfoOffset + pass_through->SenseInfoLength;
+ else
+ pass_through->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+ return TRUE;
+ }
+ case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+ {
+ PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
+
+ pass_through_direct = irp->AssociatedIrp.SystemBuffer;
+ pass_through_direct->ScsiStatus = 0;
+ irp->IoStatus.Status = status;
+
+ // we have set these two value in bulkonly.c when data transfer complete
+ // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
+ // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
+
+ if (status == STATUS_SUCCESS)
+ irp->IoStatus.Information =
+ pass_through_direct->SenseInfoOffset + pass_through_direct->SenseInfoLength;
+ else
+ pass_through_direct->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
}
VOID
-umss_complete_request(
-PUMSS_DEVICE_EXTENSION pdev_ext,
-NTSTATUS status
-)
+umss_complete_request(PUMSS_DEVICE_EXTENSION pdev_ext, NTSTATUS status)
{
- PIRP pirp;
- KIRQL old_irql;
-
- PDEVICE_OBJECT dev_obj;
- PIO_STACK_LOCATION irp_stack;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_complete_request(): entering...\n" ) );
-
- pirp = pdev_ext->io_packet.pirp;
- dev_obj = pdev_ext->pdo;
-
- irp_stack = IoGetCurrentIrpStackLocation ( pirp );
-
- if( pdev_ext->io_packet.flags & IOP_FLAG_SRB_TRANSFER )
- {
- if( pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I )
- {
- umss_fix_sff_result( &pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb );
- }
- umss_gen_result_srb( &pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb, status );
- }
- else if( pdev_ext->io_packet.flags & IOP_FLAG_SCSI_CTRL_TRANSFER )
- umss_gen_result_ctrl( dev_obj, pirp, status );
-
- //this device has its irp queued
- if( status == STATUS_CANCELLED )
- {
- IoAcquireCancelSpinLock( &old_irql );
- if( dev_obj->CurrentIrp == pirp )
- {
- IoReleaseCancelSpinLock( old_irql );
- IoStartNextPacket( dev_obj, FALSE );
- }
- else
- {
- KeRemoveEntryDeviceQueue( &dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry );
- IoReleaseCancelSpinLock( old_irql );
- }
- }
- else
- // all requests come to this point from the irp queue
- IoStartNextPacket( dev_obj, FALSE );
-
- pirp->IoStatus.Status = status;
-
- if( status != STATUS_SUCCESS )
- pirp->IoStatus.Information = 0;
-
- IoCompleteRequest( pirp, IO_NO_INCREMENT );
- return;
+ PIRP pirp;
+ KIRQL old_irql;
+
+ PDEVICE_OBJECT dev_obj;
+ PIO_STACK_LOCATION irp_stack;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): entering...\n"));
+
+ pirp = pdev_ext->io_packet.pirp;
+ dev_obj = pdev_ext->pdo;
+
+ irp_stack = IoGetCurrentIrpStackLocation(pirp);
+
+ if (pdev_ext->io_packet.flags & IOP_FLAG_SRB_TRANSFER)
+ {
+ if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
+ {
+ umss_fix_sff_result(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb);
+ }
+ umss_gen_result_srb(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb, status);
+ }
+ else if (pdev_ext->io_packet.flags & IOP_FLAG_SCSI_CTRL_TRANSFER)
+ umss_gen_result_ctrl(dev_obj, pirp, status);
+
+ //this device has its irp queued
+ if (status == STATUS_CANCELLED)
+ {
+ IoAcquireCancelSpinLock(&old_irql);
+ if (dev_obj->CurrentIrp == pirp)
+ {
+ IoReleaseCancelSpinLock(old_irql);
+ IoStartNextPacket(dev_obj, FALSE);
+ }
+ else
+ {
+ KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
+ IoReleaseCancelSpinLock(old_irql);
+ }
+ }
+ else
+ // all requests come to this point from the irp queue
+ IoStartNextPacket(dev_obj, FALSE);
+
+ pirp->IoStatus.Status = status;
+
+ if (status != STATUS_SUCCESS)
+ pirp->IoStatus.Information = 0;
+
+ IoCompleteRequest(pirp, IO_NO_INCREMENT);
+ return;
}
BOOL
-umss_if_connect(
-PCONNECT_DATA params,
-DEV_HANDLE if_handle
-)
+umss_if_connect(PCONNECT_DATA params, DEV_HANDLE if_handle)
{
- PURB purb;
- LONG if_idx, i;
- PUCHAR desc_buf;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_DRIVER pdrvr;
- PUSB_INTERFACE_DESC pif_desc;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PUSB_CONFIGURATION_DESC pconfig_desc;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_ENDPOINT_DESC pendp_desc;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
-
- PDEVICE_OBJECT pdev_obj;
- USE_IRQL;
- //configuration is already set
- purb = NULL;
- desc_buf = NULL;
- pdev = NULL;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_if_connect(): entering...\n" ) );
-
- if( params == NULL )
- return FALSE;
-
- dev_mgr = params->dev_mgr;
- pdrvr = params->pdriver;
-
- if_idx = if_idx_from_handle( if_handle );
-
- purb = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb == NULL )
- goto ERROR_OUT;
-
- desc_buf = usb_alloc_mem( NonPagedPool, 512 );
- if( desc_buf == NULL )
- goto ERROR_OUT;
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- urb_init( ( purb ) );
-
- // now let's get the descs, one configuration, one interface and two endpoint
- psetup = ( PUSB_CTRL_SETUP_PACKET )( purb )->setup_packet;
- purb->endp_handle = if_handle | 0xffff;
- purb->data_buffer = desc_buf;
- purb->data_length = 512;
- purb->completion = NULL; // this is an immediate request, no needs completion
- purb->context = dev_mgr;
- 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( purb );
- purb = NULL;
-
- if( status != STATUS_SUCCESS )
- {
- goto ERROR_OUT;
- }
-
- status = usb_query_and_lock_dev( dev_mgr, if_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- goto ERROR_OUT;
- }
+ PURB purb;
+ LONG if_idx, i;
+ PUCHAR desc_buf;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_DRIVER pdrvr;
+ PUSB_INTERFACE_DESC pif_desc;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PUSB_CONFIGURATION_DESC pconfig_desc;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_ENDPOINT_DESC pendp_desc;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+
+ PDEVICE_OBJECT pdev_obj;
+ USE_IRQL;
+ //configuration is already set
+ purb = NULL;
+ desc_buf = NULL;
+ pdev = NULL;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_connect(): entering...\n"));
+
+ if (params == NULL)
+ return FALSE;
+
+ dev_mgr = params->dev_mgr;
+ pdrvr = params->pdriver;
+
+ if_idx = if_idx_from_handle(if_handle);
+
+ purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb == NULL)
+ goto ERROR_OUT;
+
+ desc_buf = usb_alloc_mem(NonPagedPool, 512);
+ if (desc_buf == NULL)
+ goto ERROR_OUT;
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ urb_init((purb));
+
+ // now let's get the descs, one configuration, one interface and two endpoint
+ psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
+ purb->endp_handle = if_handle | 0xffff;
+ purb->data_buffer = desc_buf;
+ purb->data_length = 512;
+ purb->completion = NULL; // this is an immediate request, no needs completion
+ purb->context = dev_mgr;
+ 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(purb);
+ purb = NULL;
+
+ if (status != STATUS_SUCCESS)
+ {
+ goto ERROR_OUT;
+ }
+
+ status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ goto ERROR_OUT;
+ }
#ifdef _TIANSHENG_DRIVER
- if( !( ( pdev->pusb_dev_desc->idVendor == 0x03eb && pdev->pusb_dev_desc->idProduct == 0x2002 )
- ||( pdev->pusb_dev_desc->idVendor == 0x0ea0 && pdev->pusb_dev_desc->idProduct == 0x6803 )
- ||( pdev->pusb_dev_desc->idVendor == 0x0ef5 && pdev->pusb_dev_desc->idProduct == 0x2202 ) ) )
- {
- // check TianSheng's product
- goto ERROR_OUT;
- }
+ if (!((pdev->pusb_dev_desc->idVendor == 0x03eb && pdev->pusb_dev_desc->idProduct == 0x2002)
+ || (pdev->pusb_dev_desc->idVendor == 0x0ea0 && pdev->pusb_dev_desc->idProduct == 0x6803)
+ || (pdev->pusb_dev_desc->idVendor == 0x0ef5 && pdev->pusb_dev_desc->idProduct == 0x2202)))
+ {
+ // check TianSheng's product
+ goto ERROR_OUT;
+ }
#endif
- pdev_obj = umss_create_device( dev_mgr, pdrvr, if_handle, TRUE );
- if( pdev_obj == NULL )
- {
- goto ERROR_OUT;
- }
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB ||
- dev_mgr_set_if_driver( dev_mgr, if_handle, pdrvr, pdev ) == FALSE )
- {
- unlock_dev( pdev, FALSE );
- if( pdev_obj )
- {
- umss_delete_device( dev_mgr, pdrvr, pdev_obj, TRUE );
- }
- goto ERROR_OUT;
- }
-
- if( pdev->usb_config )
- {
- pdev->usb_config->interf[ if_idx ].if_ext = pdev_obj;
- pdev->usb_config->interf[ if_idx ].if_ext_size = 0;
- }
- // olympus dev needs special care
- if( UMSS_OLYMPUS_VENDOR_ID == pdev->pusb_dev_desc->idVendor )
- status = TRUE;
- else
- status = FALSE;
-
- unlock_dev( pdev, FALSE );
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )pdev_obj->DeviceExtension;
-
- pdev_ext->desc_buf = desc_buf;
- pdev_ext->pif_desc = NULL;
- pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
- pconfig_desc = ( PUSB_CONFIGURATION_DESC )desc_buf;
- pif_desc = ( PUSB_INTERFACE_DESC )( &pconfig_desc[ 1 ] );
-
- if( status )
- pdev_ext->flags |= UMSS_DEV_FLAG_OLYMPUS_DEV;
-
- //search for our if
- for( i = 0; ( ( UCHAR ) i ) < if_idx; i++ )
- {
- if( usb_skip_if_and_altif( ( PUCHAR* )&pif_desc ) == FALSE )
- break;
- }
- pdev_ext->pif_desc = pif_desc;
-
- if( pdev_ext->pif_desc )
- {
- pendp_desc = ( PUSB_ENDPOINT_DESC )&pif_desc[ 1 ];
- for( i = 0; ( ( UCHAR )i ) < pif_desc->bNumEndpoints; i++ )
- {
- if( pendp_desc->bDescriptorType == USB_DT_ENDPOINT \
- && pendp_desc->bLength == sizeof( USB_ENDPOINT_DESC ) )
- {
- if( ( pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) \
- == USB_ENDPOINT_XFER_INT )
- {
- pdev_ext->pint_endp_desc = pendp_desc;
- pdev_ext->int_endp_idx = ( UCHAR )i;
- }
- else if( ( pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) \
- == USB_ENDPOINT_XFER_BULK )
- {
- if( pendp_desc->bEndpointAddress & USB_DIR_IN )
- {
- pdev_ext->pin_endp_desc = pendp_desc;
- pdev_ext->in_endp_idx = ( UCHAR )i;
- }
- else
- {
- pdev_ext->pout_endp_desc = pendp_desc;
- pdev_ext->out_endp_idx = ( UCHAR )i;
- }
- }
- pendp_desc = &pendp_desc[ 1 ];
- }
- else
- break;
- }
- }
-
- // notify the class driver, some device comes
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdrvr->driver_ext;
- if( pdrvr_ext &&
- pdrvr_ext->class_driver_info.add_device &&
- pdrvr_ext->class_driver_info.fdo_driver )
- pdrvr_ext->class_driver_info.add_device( pdrvr_ext->class_driver_info.fdo_driver, pdev_obj );
-
- usb_unlock_dev( pdev );
- return TRUE;
+ pdev_obj = umss_create_device(dev_mgr, pdrvr, if_handle, TRUE);
+ if (pdev_obj == NULL)
+ {
+ goto ERROR_OUT;
+ }
-ERROR_OUT:
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
+ dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
+ {
+ unlock_dev(pdev, FALSE);
+ if (pdev_obj)
+ {
+ umss_delete_device(dev_mgr, pdrvr, pdev_obj, TRUE);
+ }
+ goto ERROR_OUT;
+ }
+
+ if (pdev->usb_config)
+ {
+ pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
+ pdev->usb_config->interf[if_idx].if_ext_size = 0;
+ }
+ // olympus dev needs special care
+ if (UMSS_OLYMPUS_VENDOR_ID == pdev->pusb_dev_desc->idVendor)
+ status = TRUE;
+ else
+ status = FALSE;
+
+ unlock_dev(pdev, FALSE);
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
+
+ pdev_ext->desc_buf = desc_buf;
+ pdev_ext->pif_desc = NULL;
+ pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
+ pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf;
+ pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
+
+ if (status)
+ pdev_ext->flags |= UMSS_DEV_FLAG_OLYMPUS_DEV;
+
+ //search for our if
+ for(i = 0; ((UCHAR) i) < if_idx; i++)
+ {
+ if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
+ break;
+ }
+ pdev_ext->pif_desc = pif_desc;
+
+ if (pdev_ext->pif_desc)
+ {
+ pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
+ for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++)
+ {
+ if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT
+ && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
+ {
+ if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ {
+ pdev_ext->pint_endp_desc = pendp_desc;
+ pdev_ext->int_endp_idx = (UCHAR) i;
+ }
+ else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+ {
+ if (pendp_desc->bEndpointAddress & USB_DIR_IN)
+ {
+ pdev_ext->pin_endp_desc = pendp_desc;
+ pdev_ext->in_endp_idx = (UCHAR) i;
+ }
+ else
+ {
+ pdev_ext->pout_endp_desc = pendp_desc;
+ pdev_ext->out_endp_idx = (UCHAR) i;
+ }
+ }
+ pendp_desc = &pendp_desc[1];
+ }
+ else
+ break;
+ }
+ }
+
+ // notify the class driver, some device comes
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
+ if (pdrvr_ext && pdrvr_ext->class_driver_info.add_device && pdrvr_ext->class_driver_info.fdo_driver)
+ pdrvr_ext->class_driver_info.add_device(pdrvr_ext->class_driver_info.fdo_driver, pdev_obj);
- if( desc_buf )
- usb_free_mem( desc_buf );
+ usb_unlock_dev(pdev);
+ return TRUE;
- if( purb )
- usb_free_mem( purb );
+ERROR_OUT:
+ if (desc_buf)
+ usb_free_mem(desc_buf);
- usb_unlock_dev( pdev );
+ if (purb)
+ usb_free_mem(purb);
- desc_buf = NULL;
- purb = NULL;
+ usb_unlock_dev(pdev);
- return FALSE;
+ desc_buf = NULL;
+ purb = NULL;
+
+ return FALSE;
}
BOOL
-umss_if_disconnect(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle
-)
+umss_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
- LONG if_idx;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_DRIVER pdrvr;
- PDEVICE_OBJECT dev_obj;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- PUMSS_DEVICE_EXTENSION pdev_ext;
-
- if( dev_mgr == NULL || if_handle == 0 )
- return FALSE;
-
- pdev = NULL;
- if_idx = if_idx_from_handle( if_handle );
- //
- // special use of the lock dev, simply use this routine to get the dev
- //
- status = usb_query_and_lock_dev( dev_mgr, if_handle, &pdev );
- if( pdev == NULL )
- {
- return FALSE;
- }
- if( status == STATUS_SUCCESS )
- {
- // must be a bug
- TRAP();
- }
- if( pdev->usb_config )
- {
- pdrvr = pdev->usb_config->interf[ if_idx ].pif_drv;
- dev_obj = ( PDEVICE_OBJECT )pdev->usb_config->interf[ if_idx ].if_ext;
- }
- pdev = NULL;
-
- // notify the class driver, some device gone
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdrvr->driver_ext;
- pdev_ext = dev_obj->DeviceExtension;
- if( pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch )
- pdrvr_ext->class_driver_info.pnp_dispatch( dev_obj, UMSS_PNPMSG_DISCONNECT, NULL );
-
- // no need to unlock the dev
- return umss_delete_device( dev_mgr, pdrvr, dev_obj, TRUE );
+ LONG if_idx;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_DRIVER pdrvr;
+ PDEVICE_OBJECT dev_obj;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+
+ if (dev_mgr == NULL || if_handle == 0)
+ return FALSE;
+
+ pdev = NULL;
+ if_idx = if_idx_from_handle(if_handle);
+ //
+ // special use of the lock dev, simply use this routine to get the dev
+ //
+ status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
+ if (pdev == NULL)
+ {
+ return FALSE;
+ }
+ if (status == STATUS_SUCCESS)
+ {
+ // must be a bug
+ TRAP();
+ }
+ if (pdev->usb_config)
+ {
+ pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
+ dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
+ }
+ pdev = NULL;
+
+ // notify the class driver, some device gone
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
+ pdev_ext = dev_obj->DeviceExtension;
+ if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
+ pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_DISCONNECT, NULL);
+
+ // no need to unlock the dev
+ return umss_delete_device(dev_mgr, pdrvr, dev_obj, TRUE);
}
BOOL
-umss_if_stop(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE if_handle
-)
+umss_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
- LONG if_idx;
- NTSTATUS status;
- PUSB_DEV pdev;
- PUSB_DRIVER pdrvr;
- PDEVICE_OBJECT dev_obj;
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- PUMSS_DEVICE_EXTENSION pdev_ext;
-
- USE_IRQL;
-
- if( dev_mgr == NULL || if_handle == 0 )
- return FALSE;
-
- pdev = NULL;
- if_idx = if_idx_from_handle( if_handle );
-
- // special use of the lock dev, simply use this routine to get the dev
- status = usb_query_and_lock_dev( dev_mgr, if_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- return FALSE;
- }
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- return FALSE;
- }
-
- if( pdev->usb_config )
- {
- pdrvr = pdev->usb_config->interf[ if_idx ].pif_drv;
- dev_obj = ( PDEVICE_OBJECT )pdev->usb_config->interf[ if_idx ].if_ext;
- }
- unlock_dev( pdev, FALSE );
-
- // notify the class driver, some device stops
- pdev_ext = dev_obj->DeviceExtension;
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdrvr->driver_ext;
- if( pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch )
- pdrvr_ext->class_driver_info.pnp_dispatch( dev_obj, UMSS_PNPMSG_STOP, NULL );
-
- usb_unlock_dev( pdev );
- return TRUE;
+ LONG if_idx;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PUSB_DRIVER pdrvr;
+ PDEVICE_OBJECT dev_obj;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+
+ USE_IRQL;
+
+ if (dev_mgr == NULL || if_handle == 0)
+ return FALSE;
+
+ pdev = NULL;
+ if_idx = if_idx_from_handle(if_handle);
+
+ // special use of the lock dev, simply use this routine to get the dev
+ status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ return FALSE;
+ }
+
+ if (pdev->usb_config)
+ {
+ pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
+ dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
+ }
+ unlock_dev(pdev, FALSE);
+
+ // notify the class driver, some device stops
+ pdev_ext = dev_obj->DeviceExtension;
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
+ if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
+ pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_STOP, NULL);
+
+ usb_unlock_dev(pdev);
+ return TRUE;
}
VOID
-umss_load_class_driver(
-PVOID context
-)
+umss_load_class_driver(PVOID context)
{
- NTSTATUS status;
- UNICODE_STRING unicode_string;
-
- //
- // let's load the class driver
- //
- RtlInitUnicodeString(&unicode_string, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\usbstor");
- status = ZwLoadDriver( &unicode_string );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_load_class_driver(): try to load class driver, status=0x%x\n", status ) );
+ NTSTATUS status;
+ UNICODE_STRING unicode_string;
+
+ //
+ // let's load the class driver
+ //
+ RtlInitUnicodeString(&unicode_string,
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\usbstor");
+ status = ZwLoadDriver(&unicode_string);
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("umss_load_class_driver(): try to load class driver, status=0x%x\n", status));
}
+
BOOL
-umss_if_driver_init(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DRIVER pdriver
-)
+umss_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
- PUMSS_DRVR_EXTENSION pdrvr_ext;
- UNICODE_STRING unicode_string;
- NTSTATUS status;
-
- if( dev_mgr == NULL || pdriver == NULL )
- return FALSE;
-
- //init driver structure, no PNP table functions
-
- pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
- pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
- pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
- pdriver->driver_desc.release_num = 0x100; // Release Number of Device
-
- pdriver->driver_desc.config_val = 1; // Configuration Value
- pdriver->driver_desc.if_num = 1; // Interface Number
- pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // 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 Mass Storage interface 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_ext = usb_alloc_mem( NonPagedPool, sizeof( UMSS_DRVR_EXTENSION ) );
- pdriver->driver_ext_size = sizeof( UMSS_DRVR_EXTENSION );
-
- RtlZeroMemory( pdriver->driver_ext, sizeof( UMSS_DRVR_EXTENSION ) );
-
- pdrvr_ext = ( PUMSS_DRVR_EXTENSION )pdriver->driver_ext;
- pdrvr_ext->dev_count = 0;
- InitializeListHead( &pdrvr_ext->dev_list );
- ExInitializeFastMutex( &pdrvr_ext->dev_list_mutex );
-
- pdriver->disp_tbl.version = 1;
- pdriver->disp_tbl.dev_connect = umss_if_connect;
- pdriver->disp_tbl.dev_disconnect = umss_if_disconnect;
- pdriver->disp_tbl.dev_stop = umss_if_stop;
- pdriver->disp_tbl.dev_reserved = NULL;
-
- if( ( pdrvr_ext->port_dev_obj = umss_create_port_device( dev_mgr, pdriver ) ) == NULL )
- {
- usb_free_mem( pdriver->driver_ext );
- pdriver->driver_ext = NULL;
- pdriver->driver_ext_size = 0;
- pdriver->disp_tbl.dev_connect = NULL;
- pdriver->disp_tbl.dev_stop = NULL;
- pdriver->disp_tbl.dev_disconnect = NULL;
- return FALSE;
- }
-
- //
- // let's load the class driver
- //
-
- umss_load_class_driver( NULL );
-
- // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_if_driver_init(): umss driver is initialized\n" ) );
-
- return TRUE;
+ PUMSS_DRVR_EXTENSION pdrvr_ext;
+ UNICODE_STRING unicode_string;
+ NTSTATUS status;
+
+ if (dev_mgr == NULL || pdriver == NULL)
+ return FALSE;
+
+ //init driver structure, no PNP table functions
+
+ pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
+ pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
+ pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
+ pdriver->driver_desc.release_num = 0x100; // Release Number of Device
+
+ pdriver->driver_desc.config_val = 1; // Configuration Value
+ pdriver->driver_desc.if_num = 1; // Interface Number
+ pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // 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 Mass Storage interface 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_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION));
+ pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION);
+
+ RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION));
+
+ pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
+ pdrvr_ext->dev_count = 0;
+ InitializeListHead(&pdrvr_ext->dev_list);
+ ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex);
+
+ pdriver->disp_tbl.version = 1;
+ pdriver->disp_tbl.dev_connect = umss_if_connect;
+ pdriver->disp_tbl.dev_disconnect = umss_if_disconnect;
+ pdriver->disp_tbl.dev_stop = umss_if_stop;
+ pdriver->disp_tbl.dev_reserved = NULL;
+
+ if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL)
+ {
+ usb_free_mem(pdriver->driver_ext);
+ pdriver->driver_ext = NULL;
+ pdriver->driver_ext_size = 0;
+ pdriver->disp_tbl.dev_connect = NULL;
+ pdriver->disp_tbl.dev_stop = NULL;
+ pdriver->disp_tbl.dev_disconnect = NULL;
+ return FALSE;
+ }
+
+ //
+ // let's load the class driver
+ //
+ umss_load_class_driver(NULL);
+
+ // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_driver_init(): umss driver is initialized\n"));
+
+ return TRUE;
}
-PCLASS_DRV_REG_INFO
-umss_get_if_driver_info(
-PUSB_DEV_MANAGER dev_mgr,
-PUSB_DEV pdev,
-DEV_HANDLE if_handle
-)
// get the driver reg information for pnp notification to class
// driver.
// bug??? how if the driver info is returned while the driver
// is being unloaded.
// So the routine must be called when usb_query_and_lock_dev is
// called.
+PCLASS_DRV_REG_INFO
+umss_get_if_driver_info(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, DEV_HANDLE if_handle)
{
- PUMSS_DRVR_EXTENSION drvr_ext;
- ULONG if_idx;
- USE_IRQL;
+ PUMSS_DRVR_EXTENSION drvr_ext;
+ ULONG if_idx;
+ USE_IRQL;
- if_idx = if_idx_from_handle( if_handle );
- if( if_idx >= 4 ) // max interfaces per config supports. defined in td.h
- return NULL;
+ if_idx = if_idx_from_handle(if_handle);
+ if (if_idx >= 4) // max interfaces per config supports. defined in td.h
+ return NULL;
- ASSERT( pdev != NULL );
+ ASSERT(pdev != NULL);
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
- return NULL;
- }
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
+ return NULL;
+ }
- drvr_ext = NULL;
+ drvr_ext = NULL;
- if( pdev->usb_config->interf[ if_idx ].pif_drv )
- drvr_ext = ( PUMSS_DRVR_EXTENSION )pdev->usb_config->interf[ if_idx ].pif_drv->driver_ext;
- else
- TRAP();
+ if (pdev->usb_config->interf[if_idx].pif_drv)
+ drvr_ext = (PUMSS_DRVR_EXTENSION) pdev->usb_config->interf[if_idx].pif_drv->driver_ext;
+ else
+ TRAP();
- unlock_dev( pdev, FALSE );
+ unlock_dev(pdev, FALSE);
- if( drvr_ext == NULL )
- {
- return NULL;
- }
+ if (drvr_ext == NULL)
+ {
+ return NULL;
+ }
- return &drvr_ext->class_driver_info;
+ return &drvr_ext->class_driver_info;
}
VOID
-umss_worker(
-IN PVOID reference
-)
+umss_worker(IN PVOID reference)
{
PUMSS_WORKER_PACKET worker_packet;
- PUSB_DEV pdev;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_worker(): entering...\n" ) );
- worker_packet = ( PUMSS_WORKER_PACKET )reference;
- worker_packet->completion( worker_packet->context );
- if( worker_packet->dev_mgr && worker_packet->pdev )
- {
- pdev = ( PUSB_DEV ) worker_packet->pdev;
- usb_unlock_dev( pdev );
- pdev = NULL;
- }
- usb_free_mem( worker_packet );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_worker(): exit\n" ) );
+ PUSB_DEV pdev;
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): entering...\n"));
+ worker_packet = (PUMSS_WORKER_PACKET) reference;
+ worker_packet->completion(worker_packet->context);
+ if (worker_packet->dev_mgr && worker_packet->pdev)
+ {
+ pdev = (PUSB_DEV) worker_packet->pdev;
+ usb_unlock_dev(pdev);
+ pdev = NULL;
+ }
+ usb_free_mem(worker_packet);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): exit\n"));
}
-BOOL
-umss_schedule_workitem(
-PVOID context,
-UMSS_WORKER_ROUTINE completion,
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle
-)
/*++
Routine Description:
Wrapper for handling worker thread callbacks, it is importent to
- lock the dev from being deleted by calling usb_query_and_lock_dev
- and in umss_worker, call the usb_unlock_dev to release the ref
- count. One exception is that the umss_if_disconnect call this
- function to delete the device object that is still held by some
- others, and deferred deletion is required.
+ lock the dev from being deleted by calling usb_query_and_lock_dev
+ and in umss_worker, call the usb_unlock_dev to release the ref
+ count. One exception is that the umss_if_disconnect call this
+ function to delete the device object that is still held by some
+ others, and deferred deletion is required.
- Arguments:
+Arguments:
Routine - Routine to be called when this work-item is processed
Context - Value to be passed to worker routine
FALSE if work item not queued
--*/
-
+BOOL
+umss_schedule_workitem(PVOID context,
+ UMSS_WORKER_ROUTINE completion, PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
BOOL ret_val = TRUE;
PWORK_QUEUE_ITEM workitem;
PUMSS_WORKER_PACKET worker_packet;
- worker_packet = usb_alloc_mem( NonPagedPool, sizeof( WORK_QUEUE_ITEM ) + sizeof( UMSS_WORKER_PACKET ) );
- RtlZeroMemory( worker_packet, sizeof( WORK_QUEUE_ITEM ) + sizeof( UMSS_WORKER_PACKET ) );
+ worker_packet = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET));
+ RtlZeroMemory(worker_packet, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET));
- if ( worker_packet )
+ if (worker_packet)
{
- workitem = ( PWORK_QUEUE_ITEM )&worker_packet[ 1 ];
- worker_packet->completion = completion;
+ workitem = (PWORK_QUEUE_ITEM) & worker_packet[1];
+ worker_packet->completion = completion;
worker_packet->context = context;
- if( dev_mgr != NULL && dev_handle != 0 )
- {
- PUSB_DEV pdev;
- // lock the device until the workitem is executed.
- if( usb_query_and_lock_dev( dev_mgr, dev_handle, &pdev ) == STATUS_SUCCESS )
- {
- worker_packet->dev_mgr = dev_mgr;
- worker_packet->pdev = pdev;
- }
- else
- {
- usb_free_mem( worker_packet );
- return FALSE;
- }
- }
+ if (dev_mgr != NULL && dev_handle != 0)
+ {
+ PUSB_DEV pdev;
+ // lock the device until the workitem is executed.
+ if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) == STATUS_SUCCESS)
+ {
+ worker_packet->dev_mgr = dev_mgr;
+ worker_packet->pdev = pdev;
+ }
+ else
+ {
+ usb_free_mem(worker_packet);
+ return FALSE;
+ }
+ }
// Initialize the work-item
- ExInitializeWorkItem(
- workitem,
- umss_worker,
- worker_packet
- );
+ ExInitializeWorkItem(workitem, umss_worker, worker_packet);
// Schedule the work-item
- ExQueueWorkItem(
- workitem,
- DelayedWorkQueue
- );
+ ExQueueWorkItem(workitem, DelayedWorkQueue);
- usb_dbg_print( DBGLVL_MINIMUM,( "umss_schedule_workitem(): work-item queued\n" ) );
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): work-item queued\n"));
}
else
{
- usb_dbg_print( DBGLVL_MINIMUM,("umss_schedule_workitem(): Failed to allocate work-item\n"));
+ usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): Failed to allocate work-item\n"));
ret_val = FALSE;
}
- return ret_val;
+ return ret_val;
}
NTSTATUS
-umss_process_srb(
-PDEVICE_OBJECT dev_obj,
-PIRP irp
-)
+umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp)
{
- NTSTATUS status;
- PUSB_DEV pdev;
- PIO_STACK_LOCATION cur_stack;
- PUMSS_DEVICE_EXTENSION pdev_ext;
- PSCSI_REQUEST_BLOCK srb;
-
- if( dev_obj == NULL || irp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- pdev = NULL;
- cur_stack = IoGetCurrentIrpStackLocation( irp );
- srb = cur_stack->Parameters.Scsi.Srb;
-
- if( srb == NULL || srb->DataTransferLength > 65536 )
- {
- status = STATUS_INVALID_PARAMETER;
- goto ERROR_OUT;
- }
-
- irp->IoStatus.Status = STATUS_SUCCESS;
- irp->IoStatus.Information = 0;
-
- pdev_ext = ( PUMSS_DEVICE_EXTENSION )dev_obj->DeviceExtension;
- if( ( status = usb_query_and_lock_dev( pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev ) ) != STATUS_SUCCESS )
- {
- PSENSE_DATA sense_buf;
- srb->SrbStatus = SRB_STATUS_NO_DEVICE;
-
- //
- // let's build the srb status for class driver
- //
-
- srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- RtlZeroMemory( srb->SenseInfoBuffer, srb->SenseInfoBufferLength );
- if( !( srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE ) )
- {
- sense_buf = ( PSENSE_DATA )srb->SenseInfoBuffer;
- sense_buf->ErrorCode = 0x70;
- sense_buf->Valid = 1;
- sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
- sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
- sense_buf->AdditionalSenseLength = 10;
- }
- goto ERROR_OUT;
- }
-
- switch( srb->Function )
- {
- case SRB_FUNCTION_EXECUTE_SCSI:
- {
- IO_PACKET io_packet;
- RtlZeroMemory( &io_packet, sizeof( io_packet ) );
-
- io_packet.flags |= IOP_FLAG_SRB_TRANSFER;
- if( srb->SrbFlags & SRB_FLAGS_DATA_IN )
- io_packet.flags |= IOP_FLAG_DIR_IN;
- if( !( srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE ) )
- io_packet.flags |= IOP_FLAG_REQ_SENSE;
-
- io_packet.cdb_length = srb->CdbLength;
- RtlCopyMemory( io_packet.cdb, srb->Cdb, sizeof( io_packet.cdb ) );
- io_packet.lun = 0;
-
- if( srb->SrbFlags & SRB_FLAGS_NO_DATA_TRANSFER )
- {
- io_packet.data_buffer = NULL;
- io_packet.data_length = 0;
- }
- else
- {
- if( ( irp->Flags & ( IRP_READ_OPERATION | IRP_WRITE_OPERATION ) ) && !( irp->Flags & IRP_PAGING_IO ) )
- {
- //
- // since these operations does not allign the buffer on page boundary
- // and some unknown traps in window NT, we have to copy to a buffer
- // we allocated
- io_packet.data_buffer = usb_alloc_mem( NonPagedPool, srb->DataTransferLength );
- if( irp->Flags & IRP_WRITE_OPERATION )
- {
- PULONG dest_buf, src_buf;
- ULONG i;
-
- dest_buf = ( PULONG )io_packet.data_buffer;
- src_buf = ( PULONG )srb->DataBuffer;
-
- if( src_buf && dest_buf )
- {
- for( i = 0; i < ( srb->DataTransferLength >> 2 ); i++ )
- {
- dest_buf[ i ] = src_buf[ i ];
- }
- }
- }
- }
- else
- io_packet.data_buffer = srb->DataBuffer;
-
- io_packet.data_length = srb->DataTransferLength;
- }
-
- if( io_packet.flags & IOP_FLAG_REQ_SENSE )
- {
- io_packet.sense_data = srb->SenseInfoBuffer;
- io_packet.sense_data_length = srb->SenseInfoBufferLength;
- }
-
- io_packet.pirp = irp;
-
- // do some conversions
- if( pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I )
- {
- if( umss_tsc_to_sff( &io_packet ) == FALSE )
- {
- status = STATUS_DEVICE_PROTOCOL_ERROR;
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_process_srb(): error converting to sff proto, 0x%x\n",
- status ) );
- srb->SrbStatus = SRB_STATUS_ERROR;
- break;
- }
- }
-
- if( pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY )
- {
- //
- // currently we support only transparent scsi command set
- //
- if( pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SCSI_TCS || \
- pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I )
- status = umss_bulkonly_startio( pdev_ext, &io_packet );
- else
- status = STATUS_DEVICE_PROTOCOL_ERROR;
- }
- else if( pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
- || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI )
- {
- status = umss_cbi_startio( pdev_ext, &io_packet );
- }
- else
- {
- status = STATUS_DEVICE_PROTOCOL_ERROR;
- }
-
- if( status != STATUS_PENDING && status != STATUS_SUCCESS )
- {
- // error occured
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_process_srb(): error sending request, 0x%x\n",
- status ) );
- srb->SrbStatus = SRB_STATUS_ERROR;
- }
- break;
- }
- case SRB_FUNCTION_CLAIM_DEVICE:
- {
- srb->DataBuffer = ( PVOID )dev_obj;
- }
- case SRB_FUNCTION_SHUTDOWN:
- case SRB_FUNCTION_FLUSH:
- case SRB_FUNCTION_RESET_BUS:
- case SRB_FUNCTION_FLUSH_QUEUE:
- case SRB_FUNCTION_RELEASE_QUEUE:
- case SRB_FUNCTION_RELEASE_DEVICE:
- default:
- {
- // for usb flash disk, they are luxurious
-
- usb_dbg_print( DBGLVL_MAXIMUM, ( "umss_process_srb(): current srb->Function=0x%x\n",
- srb->Function ) );
-
- status = STATUS_SUCCESS;
- srb->SrbStatus = SRB_STATUS_SUCCESS;
- break;
- }
- }
-
- usb_unlock_dev( pdev );
- pdev = NULL;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ PIO_STACK_LOCATION cur_stack;
+ PUMSS_DEVICE_EXTENSION pdev_ext;
+ PSCSI_REQUEST_BLOCK srb;
+
+ if (dev_obj == NULL || irp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ pdev = NULL;
+ cur_stack = IoGetCurrentIrpStackLocation(irp);
+ srb = cur_stack->Parameters.Scsi.Srb;
+
+ if (srb == NULL || srb->DataTransferLength > 65536)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ goto ERROR_OUT;
+ }
+
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ irp->IoStatus.Information = 0;
+
+ pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
+ if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS)
+ {
+ PSENSE_DATA sense_buf;
+ srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+
+ //
+ // let's build the srb status for class driver
+ //
+ srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
+ if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
+ {
+ sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
+ sense_buf->ErrorCode = 0x70;
+ sense_buf->Valid = 1;
+ sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
+ sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
+ sense_buf->AdditionalSenseLength = 10;
+ }
+ goto ERROR_OUT;
+ }
+
+ switch (srb->Function)
+ {
+ case SRB_FUNCTION_EXECUTE_SCSI:
+ {
+ IO_PACKET io_packet;
+ RtlZeroMemory(&io_packet, sizeof(io_packet));
+
+ io_packet.flags |= IOP_FLAG_SRB_TRANSFER;
+ if (srb->SrbFlags & SRB_FLAGS_DATA_IN)
+ io_packet.flags |= IOP_FLAG_DIR_IN;
+ if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
+ io_packet.flags |= IOP_FLAG_REQ_SENSE;
+
+ io_packet.cdb_length = srb->CdbLength;
+ RtlCopyMemory(io_packet.cdb, srb->Cdb, sizeof(io_packet.cdb));
+ io_packet.lun = 0;
+
+ if (srb->SrbFlags & SRB_FLAGS_NO_DATA_TRANSFER)
+ {
+ io_packet.data_buffer = NULL;
+ io_packet.data_length = 0;
+ }
+ else
+ {
+ if ((irp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION))
+ && !(irp->Flags & IRP_PAGING_IO))
+ {
+ //
+ // since these operations does not allign the buffer on page boundary
+ // and some unknown traps in window NT, we have to copy to a buffer
+ // we allocated
+ io_packet.data_buffer = usb_alloc_mem(NonPagedPool, srb->DataTransferLength);
+ if (irp->Flags & IRP_WRITE_OPERATION)
+ {
+ PULONG dest_buf, src_buf;
+ ULONG i;
+
+ dest_buf = (PULONG) io_packet.data_buffer;
+ src_buf = (PULONG) srb->DataBuffer;
+
+ if (src_buf && dest_buf)
+ {
+ for(i = 0; i < (srb->DataTransferLength >> 2); i++)
+ {
+ dest_buf[i] = src_buf[i];
+ }
+ }
+ }
+ }
+ else
+ io_packet.data_buffer = srb->DataBuffer;
+
+ io_packet.data_length = srb->DataTransferLength;
+ }
+
+ if (io_packet.flags & IOP_FLAG_REQ_SENSE)
+ {
+ io_packet.sense_data = srb->SenseInfoBuffer;
+ io_packet.sense_data_length = srb->SenseInfoBufferLength;
+ }
+
+ io_packet.pirp = irp;
+
+ // do some conversions
+ if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
+ {
+ if (umss_tsc_to_sff(&io_packet) == FALSE)
+ {
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+
+ usb_dbg_print(DBGLVL_MAXIMUM,
+ ("umss_process_srb(): error converting to sff proto, 0x%x\n", status));
+ srb->SrbStatus = SRB_STATUS_ERROR;
+ break;
+ }
+ }
+
+ if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY)
+ {
+ //
+ // currently we support only transparent scsi command set
+ //
+ if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SCSI_TCS ||
+ pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
+ status = umss_bulkonly_startio(pdev_ext, &io_packet);
+ else
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+ else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
+ || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
+ {
+ status = umss_cbi_startio(pdev_ext, &io_packet);
+ }
+ else
+ {
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+
+ if (status != STATUS_PENDING && status != STATUS_SUCCESS)
+ {
+ // error occured
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): error sending request, 0x%x\n", status));
+ srb->SrbStatus = SRB_STATUS_ERROR;
+ }
+ break;
+ }
+ case SRB_FUNCTION_CLAIM_DEVICE:
+ {
+ srb->DataBuffer = (PVOID) dev_obj;
+ }
+ case SRB_FUNCTION_SHUTDOWN:
+ case SRB_FUNCTION_FLUSH:
+ case SRB_FUNCTION_RESET_BUS:
+ case SRB_FUNCTION_FLUSH_QUEUE:
+ case SRB_FUNCTION_RELEASE_QUEUE:
+ case SRB_FUNCTION_RELEASE_DEVICE:
+ default:
+ {
+ // for usb flash disk, they are luxurious
+
+ usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): current srb->Function=0x%x\n",
+ srb->Function));
+
+ status = STATUS_SUCCESS;
+ srb->SrbStatus = SRB_STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ usb_unlock_dev(pdev);
+ pdev = NULL;
ERROR_OUT:
-
- irp->IoStatus.Status = status;
- if( status != STATUS_PENDING )
- {
- IoStartNextPacket( dev_obj, FALSE );
- IoCompleteRequest( irp, IO_NO_INCREMENT );
- }
- //
- // UMSS_COMPLETE_START_IO( dev_obj, status, irp );
- //
- return status;
+ irp->IoStatus.Status = status;
+ if (status != STATUS_PENDING)
+ {
+ IoStartNextPacket(dev_obj, FALSE);
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ }
+
+ //
+ // UMSS_COMPLETE_START_IO( dev_obj, status, irp );
+ //
+ return status;
}
BOOL
-umss_tsc_to_sff(
-PIO_PACKET io_packet
-)
+umss_tsc_to_sff(PIO_PACKET io_packet)
{
- if( io_packet == NULL )
- return FALSE;
-
- io_packet->cdb_length = 12;
- if( io_packet->cdb[ 0 ] == SCSIOP_MODE_SENSE )
- {
- io_packet->cdb[ 0 ] = 0x5a; // mode sense( 10 )
- io_packet->cdb[ 8 ] = io_packet->cdb[ 4 ];
- io_packet->cdb[ 4 ] = 0;
- if( io_packet->cdb[ 8 ] < 8 )
- io_packet->cdb[ 8 ] = 8;
-
- io_packet->data_length = 8;
- return TRUE;
- }
- if( io_packet->cdb[ 0 ] == SCSIOP_REASSIGN_BLOCKS || \
- io_packet->cdb[ 0 ] == SCSIOP_RESERVE_UNIT || \
- io_packet->cdb[ 0 ] == SCSIOP_RELEASE_UNIT )
- return FALSE;
-
- return TRUE;
+ if (io_packet == NULL)
+ return FALSE;
+
+ io_packet->cdb_length = 12;
+ if (io_packet->cdb[0] == SCSIOP_MODE_SENSE)
+ {
+ io_packet->cdb[0] = 0x5a; // mode sense( 10 )
+ io_packet->cdb[8] = io_packet->cdb[4];
+ io_packet->cdb[4] = 0;
+ if (io_packet->cdb[8] < 8)
+ io_packet->cdb[8] = 8;
+
+ io_packet->data_length = 8;
+ return TRUE;
+ }
+ if (io_packet->cdb[0] == SCSIOP_REASSIGN_BLOCKS ||
+ io_packet->cdb[0] == SCSIOP_RESERVE_UNIT || io_packet->cdb[0] == SCSIOP_RELEASE_UNIT)
+ return FALSE;
+
+ return TRUE;
}
+
VOID
-umss_fix_sff_result(
-PIO_PACKET io_packet,
-SCSI_REQUEST_BLOCK *srb )
+umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK *srb)
{
- PBYTE buf;
- if( io_packet->cdb[ 0 ] != 0x5a )
- return;
- // the following is not right since it has to be 0x3f, return all pages
- // if( io_packet->cdb[ 2 ] != 0 )
- // return;
- srb->DataTransferLength = 4;
- buf = io_packet->data_buffer;
- // convert the mode param to scsi II
- buf[ 0 ] = buf[ 1 ];
- buf[ 1 ] = buf[ 2 ];
- buf[ 2 ] = buf[ 3 ];
- buf[ 3 ] = 0;
- return;
+ PBYTE buf;
+ if (io_packet->cdb[0] != 0x5a)
+ return;
+ // the following is not right since it has to be 0x3f, return all pages
+ // if( io_packet->cdb[ 2 ] != 0 )
+ // return;
+ srb->DataTransferLength = 4;
+ buf = io_packet->data_buffer;
+ // convert the mode param to scsi II
+ buf[0] = buf[1];
+ buf[1] = buf[2];
+ buf[2] = buf[3];
+ buf[3] = 0;
+ return;
}
#include "hub.h"
#include "debug.h"
-LONG g_alloc_cnt = 0;
-ULONG cpu_clock_freq = 0;
+LONG g_alloc_cnt = 0;
+ULONG cpu_clock_freq = 0;
-NTSTATUS
-usb_get_descriptor(
-PUSB_DEV pdev,
-PURB purb
-);
+NTSTATUS usb_get_descriptor(PUSB_DEV pdev, PURB purb);
-VOID
-usb_set_interface_completion(
-PURB purb,
-PVOID context
-);
+VOID usb_set_interface_completion(PURB purb, PVOID context);
-NTSTATUS
-usb_set_interface(
-PURB purb
-);
+NTSTATUS usb_set_interface(PURB purb);
PVOID
-usb_alloc_mem(
-POOL_TYPE pool_type,
-LONG size
-)
+usb_alloc_mem(POOL_TYPE pool_type, LONG size)
{
- PVOID ret;
- g_alloc_cnt++;
- ret = ExAllocatePool( pool_type, size );
- usb_dbg_print( DBGLVL_MAXIMUM, ( "usb_alloc_mem(): alloced=0x%x\n", g_alloc_cnt ) );
- return ret;
+ PVOID ret;
+ g_alloc_cnt++;
+ ret = ExAllocatePool(pool_type, size);
+ usb_dbg_print(DBGLVL_MAXIMUM, ("usb_alloc_mem(): alloced=0x%x\n", g_alloc_cnt));
+ return ret;
}
VOID
-usb_free_mem(
-PVOID pbuf
-)
+usb_free_mem(PVOID pbuf)
{
- g_alloc_cnt--;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "usb_free_mem(): alloced=0x%x\n", g_alloc_cnt ) );
- ExFreePool( pbuf);
+ g_alloc_cnt--;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("usb_free_mem(): alloced=0x%x\n", g_alloc_cnt));
+ ExFreePool(pbuf);
}
-VOID
-usb_config_dev_completion(
-PURB purb,
-PVOID context
-);
+VOID usb_config_dev_completion(PURB purb, PVOID context);
-LONG
-usb_calc_bus_time(
-LONG speed,
-LONG input_dir,
-LONG is_iso,
-LONG byte_count
-)
//shamelessly pasted from linux's usb.c
+LONG
+usb_calc_bus_time(LONG speed, LONG input_dir, LONG is_iso, LONG byte_count)
{
- LONG tmp;
-
- switch( speed & 0x3 ) /* no isoc. here */
- {
- case USB_SPEED_LOW:
- {
- if (input_dir)
- {
- tmp = (67667L * (31L + 10L * bit_time (byte_count))) / 1000L;
- return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
- }
- else
- {
- tmp = (66700L * (31L + 10L * bit_time (byte_count))) / 1000L;
- return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
- }
- break;
- }
- /* for full-speed: */
- case USB_SPEED_FULL:
- {
- if (!is_iso) /* Input or Output */
- {
- tmp = (8354L * (31L + 10L * bit_time (byte_count))) / 1000L;
- return (9107L + BW_HOST_DELAY + tmp);
- } /* end not Isoc */
-
- /* for isoc: */
-
- tmp = (8354L * (31L + 10L * bit_time (byte_count))) / 1000L;
- return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
- }
- case USB_SPEED_HIGH:
- {
- if( !is_iso )
- {
- tmp = ( 999 + 926520 + 2083 * ( ( LONG )( ( 19 + 7 * 8 * byte_count ) / 6 ) ) ) / 1000;
- }
- else
- {
- tmp = ( 999 + 633232 + 2083 * ( ( LONG )( ( 19 + 7 * 8 * byte_count ) / 6 ) ) ) / 1000;
- }
- return tmp + USB2_HOST_DELAY;
- }
- default:
- {
- break;
- }
- }
- return 125001;
+ LONG tmp;
+
+ switch (speed & 0x3) /* no isoc. here */
+ {
+ case USB_SPEED_LOW:
+ {
+ if (input_dir)
+ {
+ tmp = (67667L * (31L + 10L * bit_time(byte_count))) / 1000L;
+ return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+ }
+ else
+ {
+ tmp = (66700L * (31L + 10L * bit_time(byte_count))) / 1000L;
+ return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+ }
+ break;
+ }
+ /* for full-speed: */
+ case USB_SPEED_FULL:
+ {
+ if (!is_iso) /* Input or Output */
+ {
+ tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L;
+ return (9107L + BW_HOST_DELAY + tmp);
+ } /* end not Isoc */
+
+ /* for isoc: */
+
+ tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L;
+ return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
+ }
+ case USB_SPEED_HIGH:
+ {
+ if (!is_iso)
+ {
+ tmp = (999 + 926520 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000;
+ }
+ else
+ {
+ tmp = (999 + 633232 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000;
+ }
+ return tmp + USB2_HOST_DELAY;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return 125001;
}
-NTSTATUS
-usb_query_and_lock_dev(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE dev_handle,
-PUSB_DEV* ppdev
-)
//
// if the dev is not in the list, return value is not success and the pointer is nulled
// if the dev is in the list but zomb, return value is error code and the pointer is the dev( no ref_count guarded )
// if the dev is alive and in the list, return is success and the pointer is the dev.
// one must be aware of what his doing before he uses the ppdev
//
+NTSTATUS
+usb_query_and_lock_dev(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, PUSB_DEV * ppdev)
{
- int i;
- PLIST_ENTRY pthis, pnext;
- PUSB_DEV pdev;
- BOOL valid_dev;
+ int i;
+ PLIST_ENTRY pthis, pnext;
+ PUSB_DEV pdev;
+ BOOL valid_dev;
- USE_NON_PENDING_IRQL;
+ USE_NON_PENDING_IRQL;
- *ppdev = NULL;
+ *ppdev = NULL;
- if( dev_mgr == NULL || dev_handle == 0 )
- return STATUS_INVALID_PARAMETER;
+ if (dev_mgr == NULL || dev_handle == 0)
+ return STATUS_INVALID_PARAMETER;
- i = dev_id_from_handle( dev_handle );
+ i = dev_id_from_handle(dev_handle);
- KeAcquireSpinLock( &dev_mgr->dev_list_lock, &old_irql );
- ListFirst( &dev_mgr->dev_list, pthis );
+ KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
+ ListFirst(&dev_mgr->dev_list, pthis);
- while( pthis )
- {
- pdev = ( PUSB_DEV ) pthis;
- if( pdev->dev_id != ( ULONG )i )
- {
- ListNext( &dev_mgr->dev_list, pthis, pnext );
- pthis = pnext;
- continue;
- }
- else
- break;
- }
- if( pthis == NULL )
- {
- //no such device
- KeReleaseSpinLock( &dev_mgr->dev_list_lock, old_irql );
- return STATUS_INVALID_PARAMETER;
- }
+ while (pthis)
+ {
+ pdev = (PUSB_DEV) pthis;
+ if (pdev->dev_id != (ULONG) i)
+ {
+ ListNext(&dev_mgr->dev_list, pthis, pnext);
+ pthis = pnext;
+ continue;
+ }
+ else
+ break;
+ }
+ if (pthis == NULL)
+ {
+ //no such device
+ KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
+ return STATUS_INVALID_PARAMETER;
+ }
- valid_dev = TRUE;
+ valid_dev = TRUE;
- lock_dev( pdev, TRUE );
+ lock_dev(pdev, TRUE);
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- valid_dev = FALSE;
- }
- else
- pdev->ref_count ++; //guard the dev by increasing the ref count
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ valid_dev = FALSE;
+ }
+ else
+ pdev->ref_count++; //guard the dev by increasing the ref count
- unlock_dev( pdev, TRUE );
+ unlock_dev(pdev, TRUE);
- KeReleaseSpinLock( &dev_mgr->dev_list_lock, old_irql );
+ KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
- *ppdev = pdev;
+ *ppdev = pdev;
- if( !valid_dev )
- return STATUS_DEVICE_DOES_NOT_EXIST;
+ if (!valid_dev)
+ return STATUS_DEVICE_DOES_NOT_EXIST;
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS
-usb_unlock_dev(
-PUSB_DEV dev
-)
+usb_unlock_dev(PUSB_DEV dev)
{
- USE_BASIC_NON_PENDING_IRQL;
+ USE_BASIC_NON_PENDING_IRQL;
- if( dev == NULL )
- return STATUS_INVALID_PARAMETER;
+ if (dev == NULL)
+ return STATUS_INVALID_PARAMETER;
- lock_dev( dev, FALSE );
- dev->ref_count --;
- if( dev->ref_count < 0 )
- dev->ref_count = 0;
- unlock_dev( dev, FALSE );
- return STATUS_SUCCESS;
+ lock_dev(dev, FALSE);
+ dev->ref_count--;
+ if (dev->ref_count < 0)
+ dev->ref_count = 0;
+ unlock_dev(dev, FALSE);
+ return STATUS_SUCCESS;
}
NTSTATUS
-usb_reset_pipe_ex(
-PUSB_DEV_MANAGER dev_mgr,
-DEV_HANDLE endp_handle, //endp handle to reset
-PURBCOMPLETION reset_completion, //note: this reset completion has no right to delete the urb, that is only for reference
-PVOID param
-)
+usb_reset_pipe_ex(PUSB_DEV_MANAGER dev_mgr,
+ DEV_HANDLE endp_handle, //endp handle to reset
+ PURBCOMPLETION reset_completion, //note: this reset completion has no right to delete the urb, that is only for reference
+ PVOID param)
{
- NTSTATUS status;
- PUSB_DEV pdev;
- LONG if_idx, endp_idx;
- PUSB_ENDPOINT pendp;
- USE_BASIC_NON_PENDING_IRQL;
-
- if( dev_mgr == NULL )
- return STATUS_INVALID_PARAMETER;
-
- status = usb_query_and_lock_dev( dev_mgr, ( endp_handle & 0xffff0000 ), &pdev );
- if( status != STATUS_SUCCESS )
- return STATUS_UNSUCCESSFUL;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT;
- }
-
- if_idx = if_idx_from_handle( endp_handle );
- endp_idx = endp_idx_from_handle( endp_handle );
-
- if( default_endp_handle( endp_handle ) )
- {
- status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT;
- }
-
- if( dev_state( pdev ) < USB_DEV_STATE_CONFIGURED )
- {
- status = STATUS_DEVICE_NOT_READY;
- goto LBL_OUT;
- }
-
- pendp = &pdev->usb_config->interf[ if_idx ].endp[ endp_idx ];
- unlock_dev( pdev, FALSE )
- status = usb_reset_pipe( pdev, pendp, reset_completion, param );
- usb_unlock_dev( pdev );
- return status;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ LONG if_idx, endp_idx;
+ PUSB_ENDPOINT pendp;
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (dev_mgr == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ status = usb_query_and_lock_dev(dev_mgr, (endp_handle & 0xffff0000), &pdev);
+ if (status != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT;
+ }
+
+ if_idx = if_idx_from_handle(endp_handle);
+ endp_idx = endp_idx_from_handle(endp_handle);
+
+ if (default_endp_handle(endp_handle))
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT;
+ }
+
+ if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
+ {
+ status = STATUS_DEVICE_NOT_READY;
+ goto LBL_OUT;
+ }
+
+ pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
+ unlock_dev(pdev, FALSE) status = usb_reset_pipe(pdev, pendp, reset_completion, param);
+ usb_unlock_dev(pdev);
+ return status;
LBL_OUT:
- unlock_dev( pdev, FALSE );
- usb_unlock_dev( pdev );
+ unlock_dev(pdev, FALSE);
+ usb_unlock_dev(pdev);
- return status;
+ return status;
}
-NTSTATUS
-usb_reset_pipe(
-PUSB_DEV pdev,
-PUSB_ENDPOINT pendp,
-PURBCOMPLETION client_reset_pipe_completion,
-PVOID param
-)
// caller must guarantee the pdev exist before the routine exit
+NTSTATUS
+usb_reset_pipe(PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURBCOMPLETION client_reset_pipe_completion, PVOID param)
{
- PHCD hcd;
- PURB purb;
- BYTE endp_addr;
- NTSTATUS status;
- DEV_HANDLE dev_handle;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( pdev == NULL || pendp == NULL )
- return STATUS_INVALID_PARAMETER;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- hcd = pdev->hcd;
- endp_addr = pendp->pusb_endp_desc->bEndpointAddress;
- dev_handle = usb_make_handle( pdev->dev_id, 0, 0 );
- unlock_dev( pdev, FALSE );
-
- purb = ( PURB )usb_alloc_mem( NonPagedPool, sizeof( URB ) + sizeof( PIRP ) );
-
- if( purb == NULL )
- return STATUS_NO_MEMORY;
-
- UsbBuildResetPipeRequest( purb,
- dev_handle,
- endp_addr,
- usb_reset_pipe_completion,
- pendp,
- ( LONG )client_reset_pipe_completion );
-
- *( ( PULONG )&purb[ 1 ] ) = ( ULONG )param;
-
- if( ( status = hcd->hcd_submit_urb( hcd, pdev, &pdev->default_endp, purb ) ) != STATUS_PENDING )
- {
- usb_free_mem( purb );
- purb = NULL;
- }
- return status;
+ PHCD hcd;
+ PURB purb;
+ BYTE endp_addr;
+ NTSTATUS status;
+ DEV_HANDLE dev_handle;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (pdev == NULL || pendp == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_DOES_NOT_EXIST;
+ }
+
+ hcd = pdev->hcd;
+ endp_addr = pendp->pusb_endp_desc->bEndpointAddress;
+ dev_handle = usb_make_handle(pdev->dev_id, 0, 0);
+ unlock_dev(pdev, FALSE);
+
+ purb = (PURB) usb_alloc_mem(NonPagedPool, sizeof(URB) + sizeof(PIRP));
+
+ if (purb == NULL)
+ return STATUS_NO_MEMORY;
+
+ UsbBuildResetPipeRequest(purb,
+ dev_handle,
+ endp_addr,
+ usb_reset_pipe_completion,
+ pendp,
+ (LONG)client_reset_pipe_completion);
+
+ *((PULONG)&purb[1]) = (ULONG)param;
+
+ if ((status = hcd->hcd_submit_urb(hcd, pdev, &pdev->default_endp, purb)) != STATUS_PENDING)
+ {
+ usb_free_mem(purb);
+ purb = NULL;
+ }
+ return status;
}
VOID
-usb_reset_pipe_completion(
-PURB purb,
-PVOID context
-)
+usb_reset_pipe_completion(PURB purb, PVOID context)
{
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
- USE_BASIC_NON_PENDING_IRQL;
+ USE_BASIC_NON_PENDING_IRQL;
- if( purb == NULL || context == NULL )
- return;
+ if (purb == NULL || context == NULL)
+ return;
- pdev = purb->pdev;
- pendp = ( PUSB_ENDPOINT )context;
+ pdev = purb->pdev;
+ pendp = (PUSB_ENDPOINT) context;
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- goto LBL_OUT;
- }
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ goto LBL_OUT;
+ }
- if( usb_error( purb->status ) )
- {
- goto LBL_OUT;
- }
- //clear stall
- pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
+ if (usb_error(purb->status))
+ {
+ goto LBL_OUT;
+ }
+ //clear stall
+ pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
- //reset toggle endp_type
- if( ( pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) == USB_ENDPOINT_XFER_BULK || \
- ( pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) == USB_ENDPOINT_XFER_INT )
- {
- pendp->flags &= ~USB_ENDP_FLAG_DATATOGGLE;
- }
+ //reset toggle endp_type
+ if ((pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK ||
+ (pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ {
+ pendp->flags &= ~USB_ENDP_FLAG_DATATOGGLE;
+ }
LBL_OUT:
- unlock_dev( pdev, TRUE );
+ unlock_dev(pdev, TRUE);
- if( purb->reference )
- ( ( PURBCOMPLETION )purb->reference )( purb, ( PVOID )( *( ( PULONG )&purb[ 1 ] ) ) );
+ if (purb->reference)
+ ((PURBCOMPLETION) purb->reference) (purb, (PVOID) (*((PULONG) & purb[1])));
- usb_free_mem( purb );
- purb = NULL;
- return;
+ usb_free_mem(purb);
+ purb = NULL;
+ return;
}
void
-usb_reset_pipe_from_dispatch_completion(
-PURB purb,
-PVOID param
-)
+usb_reset_pipe_from_dispatch_completion(PURB purb, PVOID param)
{
-
- PURB pclient_urb;
- if( purb == NULL || param == NULL )
- TRAP();
- pclient_urb = ( PURB )param;
- pclient_urb->status = purb->status;
-
- if( pclient_urb->completion )
- {
- pclient_urb->completion( pclient_urb, pclient_urb->context );
- }
- // the urb can not be freed here because it is owned by the reset
- // pipe completion
- return;
+ PURB pclient_urb;
+ if (purb == NULL || param == NULL)
+ TRAP();
+ pclient_urb = (PURB) param;
+ pclient_urb->status = purb->status;
+
+ if (pclient_urb->completion)
+ {
+ pclient_urb->completion(pclient_urb, pclient_urb->context);
+ }
+ // the urb can not be freed here because it is owned by the reset
+ // pipe completion
+ return;
}
+//used to check descriptor validity
BOOL
-is_header_match(
-PBYTE pbuf,
-ULONG type
-) //used to check descriptor validity
+is_header_match(PBYTE pbuf, ULONG type)
{
- BOOL ret;
- PUSB_DESC_HEADER phdr;
- phdr = ( PUSB_DESC_HEADER )pbuf;
-
- switch( type )
- {
- case USB_DT_DEVICE:
- {
- ret = ( phdr->bLength == sizeof( USB_DEVICE_DESC )
- && phdr->bDescriptorType == USB_DT_DEVICE );
- break;
- }
- case USB_DT_CONFIG:
- {
- ret = ( phdr->bLength == sizeof( USB_CONFIGURATION_DESC )
- && phdr->bDescriptorType == USB_DT_CONFIG );
- break;
- }
- case USB_DT_INTERFACE:
- {
- ret = ( phdr->bLength == sizeof( USB_INTERFACE_DESC )
- && phdr->bDescriptorType == USB_DT_INTERFACE );
- break;
- }
- case USB_DT_ENDPOINT:
- {
- ret = ( phdr->bLength == sizeof( USB_ENDPOINT_DESC )
- && phdr->bDescriptorType == USB_DT_ENDPOINT );
- break;
- }
- default:
- ret = FALSE;
- }
- return ret;
+ BOOL ret;
+ PUSB_DESC_HEADER phdr;
+ phdr = (PUSB_DESC_HEADER) pbuf;
+
+ switch (type)
+ {
+ case USB_DT_DEVICE:
+ {
+ ret = (phdr->bLength == sizeof(USB_DEVICE_DESC) && phdr->bDescriptorType == USB_DT_DEVICE);
+ break;
+ }
+ case USB_DT_CONFIG:
+ {
+ ret = (phdr->bLength == sizeof(USB_CONFIGURATION_DESC) && phdr->bDescriptorType == USB_DT_CONFIG);
+ break;
+ }
+ case USB_DT_INTERFACE:
+ {
+ ret = (phdr->bLength == sizeof(USB_INTERFACE_DESC) && phdr->bDescriptorType == USB_DT_INTERFACE);
+ break;
+ }
+ case USB_DT_ENDPOINT:
+ {
+ ret = (phdr->bLength == sizeof(USB_ENDPOINT_DESC) && phdr->bDescriptorType == USB_DT_ENDPOINT);
+ break;
+ }
+ default:
+ ret = FALSE;
+ }
+ return ret;
}
BOOL
-usb_skip_endp_desc(
-PBYTE* pbUF,
-LONG n
-)
+usb_skip_endp_desc(PBYTE * pbUF, LONG n)
{
- if( is_header_match( *pbUF, USB_DT_ENDPOINT ) )
- {
- ( *pbUF ) += sizeof( USB_ENDPOINT_DESC ) * n ;
- return TRUE;
- }
- return FALSE;
+ if (is_header_match(*pbUF, USB_DT_ENDPOINT))
+ {
+ (*pbUF) += sizeof(USB_ENDPOINT_DESC) * n;
+ return TRUE;
+ }
+ return FALSE;
}
BOOL
-usb_skip_if_desc(
-PBYTE* pBUF
-)
+usb_skip_if_desc(PBYTE * pBUF)
{
BOOL ret;
- PUSB_INTERFACE_DESC pif_desc = ( PUSB_INTERFACE_DESC )*pBUF;
- LONG endp_count;
- ret = is_header_match( ( PBYTE )*pBUF, USB_DT_INTERFACE );
- if( ret == TRUE )
- {
- endp_count = pif_desc->bNumEndpoints;
- if( endp_count < MAX_ENDPS_PER_IF )
- {
- pif_desc ++;
- ret = usb_skip_endp_desc( ( PBYTE* )&pif_desc, endp_count );
- if( ret )
- *( pBUF ) = ( PBYTE )pif_desc;
- }
- else
- ret = FALSE;
- }
- return ret;
+ PUSB_INTERFACE_DESC pif_desc = (PUSB_INTERFACE_DESC) * pBUF;
+ LONG endp_count;
+ ret = is_header_match((PBYTE) * pBUF, USB_DT_INTERFACE);
+ if (ret == TRUE)
+ {
+ endp_count = pif_desc->bNumEndpoints;
+ if (endp_count < MAX_ENDPS_PER_IF)
+ {
+ pif_desc++;
+ ret = usb_skip_endp_desc((PBYTE *) & pif_desc, endp_count);
+ if (ret)
+ *(pBUF) = (PBYTE) pif_desc;
+ }
+ else
+ ret = FALSE;
+ }
+ return ret;
}
BOOL
-usb_skip_if_and_altif(
-PUCHAR* pdesc_BUF
-)
+usb_skip_if_and_altif(PUCHAR * pdesc_BUF)
{
- BOOL ret;
- PUSB_INTERFACE_DESC pif_desc1 = ( PUSB_INTERFACE_DESC )*pdesc_BUF;
- ret = is_header_match( *pdesc_BUF, USB_DT_INTERFACE );
- if( ret == TRUE )
- {
- if( pif_desc1->bAlternateSetting == 0 )
- ret = usb_skip_if_desc( ( PUCHAR* )&pif_desc1 );
- else
- //no default interface
- ret = FALSE;
-
- while( ret && pif_desc1->bAlternateSetting != 0 )
- ret = usb_skip_if_desc( ( PUCHAR* )&pif_desc1 );
- }
- if( ret )
- *pdesc_BUF = ( PUCHAR )pif_desc1;
-
- return ret;
+ BOOL ret;
+ PUSB_INTERFACE_DESC pif_desc1 = (PUSB_INTERFACE_DESC) * pdesc_BUF;
+ ret = is_header_match(*pdesc_BUF, USB_DT_INTERFACE);
+ if (ret == TRUE)
+ {
+ if (pif_desc1->bAlternateSetting == 0)
+ ret = usb_skip_if_desc((PUCHAR *) & pif_desc1);
+ else
+ //no default interface
+ ret = FALSE;
+
+ while (ret && pif_desc1->bAlternateSetting != 0)
+ ret = usb_skip_if_desc((PUCHAR *) & pif_desc1);
+ }
+ if (ret)
+ *pdesc_BUF = (PUCHAR) pif_desc1;
+
+ return ret;
}
+
BOOL
-usb_skip_one_config(
-PUCHAR* pconfig_desc_BUF
-)
+usb_skip_one_config(PUCHAR *pconfig_desc_BUF)
{
- LONG if_count, i;
- BOOL ret;
- PUSB_CONFIGURATION_DESC pcfg_DESC = ( PUSB_CONFIGURATION_DESC )*pconfig_desc_BUF;
- PUSB_INTERFACE_DESC pif_desc2 = ( PUSB_INTERFACE_DESC )&pcfg_DESC[ 1 ];
-
- ret = is_header_match( ( PUCHAR )pcfg_DESC, USB_DT_CONFIG );
- if( ret )
- *pconfig_desc_BUF = &( ( BYTE* )pcfg_DESC )[ pcfg_DESC->wTotalLength ];
- return ret;
-
- ret = is_header_match( ( PUCHAR )pcfg_DESC, USB_DT_CONFIG )
- && is_header_match( ( PUCHAR ) pif_desc2, USB_DT_INTERFACE );
-
- if( ret )
- {
- if_count = pcfg_DESC->bNumInterfaces;
- if( if_count < MAX_INTERFACES_PER_CONFIG )
- {
- for( i = 0; i < if_count; i++ )
- {
- ret = usb_skip_if_and_altif( ( PUCHAR* ) &pif_desc2 );
- if( ret == FALSE )
- break;
- }
- if( ret )
- *pconfig_desc_BUF = ( PUCHAR )pif_desc2;
- }
- }
- return ret;
+ LONG if_count, i;
+ BOOL ret;
+ PUSB_CONFIGURATION_DESC pcfg_DESC = (PUSB_CONFIGURATION_DESC) * pconfig_desc_BUF;
+ PUSB_INTERFACE_DESC pif_desc2 = (PUSB_INTERFACE_DESC) & pcfg_DESC[1];
+
+ ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG);
+ if (ret)
+ *pconfig_desc_BUF = &((BYTE *) pcfg_DESC)[pcfg_DESC->wTotalLength];
+ return ret;
+
+ ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG)
+ && is_header_match((PUCHAR) pif_desc2, USB_DT_INTERFACE);
+
+ if (ret)
+ {
+ if_count = pcfg_DESC->bNumInterfaces;
+ if (if_count < MAX_INTERFACES_PER_CONFIG)
+ {
+ for(i = 0; i < if_count; i++)
+ {
+ ret = usb_skip_if_and_altif((PUCHAR *) & pif_desc2);
+ if (ret == FALSE)
+ break;
+ }
+ if (ret)
+ *pconfig_desc_BUF = (PUCHAR) pif_desc2;
+ }
+ }
+ return ret;
}
PUSB_CONFIGURATION_DESC
-usb_find_config_desc_by_idx(
-PUCHAR pbuf,
-LONG idx,
-LONG cfg_count
-)
+usb_find_config_desc_by_idx(PUCHAR pbuf, LONG idx, LONG cfg_count)
{
- LONG i;
- BOOL ret;
- PUSB_CONFIGURATION_DESC pcfg_desc = ( PUSB_CONFIGURATION_DESC )pbuf;
- if( pcfg_desc == NULL )
- return NULL;
-
- if( cfg_count > MAX_CONFIGS_PER_DEV )
- return NULL;
-
- if( idx > cfg_count )
- return NULL;
-
- if( idx == 0 )
- return pcfg_desc;
-
- for( i = 0; i < idx - 1; i++ )
- {
- ret = usb_skip_one_config( ( PBYTE* )&pcfg_desc );
- if( ret == FALSE )
- return NULL;
- }
- return pcfg_desc;
+ LONG i;
+ BOOL ret;
+ PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
+ if (pcfg_desc == NULL)
+ return NULL;
+
+ if (cfg_count > MAX_CONFIGS_PER_DEV)
+ return NULL;
+
+ if (idx > cfg_count)
+ return NULL;
+
+ if (idx == 0)
+ return pcfg_desc;
+
+ for(i = 0; i < idx - 1; i++)
+ {
+ ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
+ if (ret == FALSE)
+ return NULL;
+ }
+ return pcfg_desc;
}
PUSB_CONFIGURATION_DESC
-usb_find_config_desc_by_val(
-PBYTE pbuf,
-LONG val,
-LONG cfg_count
-)
+usb_find_config_desc_by_val(PBYTE pbuf, LONG val, LONG cfg_count)
{
- LONG i;
- BOOL ret;
- PUSB_CONFIGURATION_DESC pcfg_desc = ( PUSB_CONFIGURATION_DESC )pbuf;
- if( pcfg_desc == NULL )
- return NULL;
-
- if( cfg_count > MAX_CONFIGS_PER_DEV )
- return NULL;
-
- for( i = 0; i < cfg_count; i++ )
- {
- if( pcfg_desc->bConfigurationValue == val )
- return pcfg_desc;
-
- ret = usb_skip_one_config( ( PBYTE* )&pcfg_desc );
- if( ret == FALSE )
- return NULL;
- }
-
- return NULL;
+ LONG i;
+ BOOL ret;
+ PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
+ if (pcfg_desc == NULL)
+ return NULL;
+
+ if (cfg_count > MAX_CONFIGS_PER_DEV)
+ return NULL;
+
+ for(i = 0; i < cfg_count; i++)
+ {
+ if (pcfg_desc->bConfigurationValue == val)
+ return pcfg_desc;
+
+ ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
+ if (ret == FALSE)
+ return NULL;
+ }
+
+ return NULL;
}
#define if_from_handle( handle ) ( ( handle & 0xff00 ) >> 8 )
NTSTATUS
-usb_submit_config_urb(
-PURB purb
-)
+usb_submit_config_urb(PURB purb)
{
- PUSB_DEV pdev;
- PUSB_DEV_MANAGER dev_mgr;
- PUSB_ENDPOINT pendp;
- PURB purb1;
- PUSB_CTRL_SETUP_PACKET psetup;
- NTSTATUS status;
- PHCD hcd;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- pdev = purb->pdev;
- pendp = purb->pendp;
-
- lock_dev( pdev, FALSE );
-
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
-
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- status = STATUS_DEVICE_DOES_NOT_EXIST;
- goto LBL_OUT;
- }
-
- if( dev_state( pdev ) == USB_DEV_STATE_FIRST_CONFIG
- || dev_state( pdev ) == USB_DEV_STATE_RECONFIG )
- {
- //outstanding request of set configuration exists in process
- status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT;
- }
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- if( dev_state( pdev ) == USB_DEV_STATE_CONFIGURED
- && pdev->usb_config->pusb_config_desc->bConfigurationValue == ( BYTE )psetup->wValue )
- {
- //already the current config
- status = STATUS_SUCCESS;
- goto LBL_OUT;
- }
-
-
- if( dev_state( pdev ) == USB_DEV_STATE_CONFIGURED )
- {
- // not support re-configuration yet
- status = STATUS_NOT_SUPPORTED;
- goto LBL_OUT;
- }
-
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- purb1 = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb1 == NULL )
- {
- status = STATUS_NO_MEMORY;
- goto LBL_OUT;
- }
-
- UsbBuildSelectConfigurationRequest( purb1,
- usb_make_handle( pdev->dev_id, 0, 0 ) | 0xffff,
- psetup->wValue,
- usb_config_dev_completion,
- 0,
- ( ( ULONG )purb ) );
- purb1->pdev = pdev;
- purb1->pendp = pendp;
-
- //change the dev state
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_FIRST_CONFIG;
-
- unlock_dev( pdev, FALSE );
-
- status = hcd->hcd_submit_urb( hcd, pdev, pendp, purb1 );
- if( status != STATUS_PENDING )
- {
- usb_free_mem( purb1 );
- purb1 = NULL;
- }
- return status;
-
- LBL_OUT:
- unlock_dev( pdev, FALSE );
- return status;
+ PUSB_DEV pdev;
+ PUSB_DEV_MANAGER dev_mgr;
+ PUSB_ENDPOINT pendp;
+ PURB purb1;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ NTSTATUS status;
+ PHCD hcd;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+
+ lock_dev(pdev, FALSE);
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ status = STATUS_DEVICE_DOES_NOT_EXIST;
+ goto LBL_OUT;
+ }
+
+ if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG || dev_state(pdev) == USB_DEV_STATE_RECONFIG)
+ {
+ //outstanding request of set configuration exists in process
+ status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT;
+ }
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED
+ && pdev->usb_config->pusb_config_desc->bConfigurationValue == (BYTE) psetup->wValue)
+ {
+ //already the current config
+ status = STATUS_SUCCESS;
+ goto LBL_OUT;
+ }
+
+
+ if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED)
+ {
+ // not support re-configuration yet
+ status = STATUS_NOT_SUPPORTED;
+ goto LBL_OUT;
+ }
+
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb1 == NULL)
+ {
+ status = STATUS_NO_MEMORY;
+ goto LBL_OUT;
+ }
+
+ UsbBuildSelectConfigurationRequest(purb1,
+ usb_make_handle(pdev->dev_id, 0, 0) | 0xffff,
+ psetup->wValue, usb_config_dev_completion, 0, ((ULONG) purb));
+ purb1->pdev = pdev;
+ purb1->pendp = pendp;
+
+ //change the dev state
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_FIRST_CONFIG;
+
+ unlock_dev(pdev, FALSE);
+
+ status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb1);
+ if (status != STATUS_PENDING)
+ {
+ usb_free_mem(purb1);
+ purb1 = NULL;
+ }
+ return status;
+
+ LBL_OUT:
+ unlock_dev(pdev, FALSE);
+ return status;
}
NTSTATUS
-usb_submit_urb(
-PUSB_DEV_MANAGER dev_mgr,
-PURB purb
-)
+usb_submit_urb(PUSB_DEV_MANAGER dev_mgr, PURB purb)
{
- NTSTATUS status;
- PUSB_DEV pdev;
- LONG if_idx, endp_idx;
- DEV_HANDLE endp_handle;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_ENDPOINT pendp;
-
- PHCD hcd;
- USE_BASIC_NON_PENDING_IRQL;
-
- if( purb == NULL || dev_mgr == NULL)
- return STATUS_INVALID_PARAMETER;
-
- endp_handle = purb->endp_handle;
-
- if( endp_handle == 0 )
- return STATUS_INVALID_PARAMETER;
-
- status = usb_query_and_lock_dev( dev_mgr, endp_handle, &pdev );
- if( status != STATUS_SUCCESS )
- {
- return status;
- }
-
- if_idx = if_idx_from_handle( endp_handle );
- endp_idx = endp_idx_from_handle( endp_handle );
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- status = STATUS_DEVICE_DOES_NOT_EXIST;
- goto LBL_OUT;
- }
-
- if( dev_state( pdev ) < USB_DEV_STATE_ADDRESSED )
- {
- unlock_dev( pdev, FALSE );
- status = STATUS_DEVICE_NOT_READY;
- goto LBL_OUT;
- }
-
- dev_mgr = dev_mgr_from_dev( pdev );
- hcd = pdev->hcd;
-
- if( default_endp_handle( endp_handle ) )
- {
- //default endp
- pendp = &pdev->default_endp;
- }
- else if( if_idx >= MAX_INTERFACES_PER_CONFIG || endp_idx >= MAX_ENDPS_PER_IF )
- {
- status = STATUS_INVALID_PARAMETER;
- unlock_dev( pdev, FALSE );
- goto LBL_OUT;
- }
- else
- {
- if( dev_state( pdev ) < USB_DEV_STATE_CONFIGURED )
- {
- status = STATUS_DEVICE_NOT_READY;
- unlock_dev( pdev, FALSE );
- goto LBL_OUT;
- }
- pendp = &pdev->usb_config->interf[ if_idx ].endp[ endp_idx ];
-
- }
-
- purb->pdev = pdev;
- purb->pendp = pendp;
-
- //for default endpoint we have some special process
- if( default_endp_handle( endp_handle ) )
- {
- psetup = ( PUSB_CTRL_SETUP_PACKET ) purb->setup_packet;
- if( psetup->bmRequestType == 0
- && psetup->bRequest == USB_REQ_SET_CONFIGURATION )
- {
- unlock_dev( pdev, FALSE );
- status = usb_submit_config_urb( purb );
- goto LBL_OUT;
- }
- else if( psetup->bmRequestType == 1
- && psetup->bRequest == USB_REQ_SET_INTERFACE )
- {
- unlock_dev( pdev, FALSE );
- // status = STATUS_NOT_SUPPORTED;
- status = usb_set_interface( purb );
- goto LBL_OUT;
- }
- else if( psetup->bmRequestType == 0x80
- && psetup->bRequest == USB_REQ_GET_DESCRIPTOR )
- {
- if( ( psetup->wValue >> 8 ) == USB_DT_CONFIG
- || ( psetup->wValue >> 8 ) == USB_DT_DEVICE )
- {
- unlock_dev( pdev, FALSE );
- status = usb_get_descriptor( pdev, purb );
- goto LBL_OUT;
-
- //get the descriptor directly
- //status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
- //goto LBL_OUT;
- }
- }
- else if( psetup->bmRequestType == 0x02
- && psetup->bRequest == USB_REQ_CLEAR_FEATURE
- && psetup->wValue == 0 ) //reset pipe
- {
- ULONG endp_addr;
- BOOL found;
- endp_addr = psetup->wIndex;
- if( ( endp_addr & 0xf ) == 0 )
- {
- unlock_dev( pdev, FALSE );
- status = STATUS_INVALID_PARAMETER;
- goto LBL_OUT;
- }
-
- // search for the endp by the endp addr in the wIndex
- found = FALSE;
- for( if_idx = 0; if_idx < pdev->usb_config->if_count; if_idx++ )
- {
- for( endp_idx =0; endp_idx < pdev->usb_config->interf[ if_idx ].endp_count; endp_idx++ )
- {
- pendp = &pdev->usb_config->interf[ if_idx ].endp[ endp_idx ];
- if( pendp->pusb_endp_desc->bEndpointAddress == endp_addr )
- {
- found = TRUE;
- break;
- }
- }
- if( found == TRUE )
- break;
- }
- if( found )
- endp_handle = usb_make_handle( pdev->dev_id, if_idx, endp_idx );
- else
- {
- unlock_dev( pdev, FALSE );
- status = STATUS_INVALID_PARAMETER;
- goto LBL_OUT;
- }
- unlock_dev( pdev, FALSE );
- status = usb_reset_pipe_ex(
- dev_mgr,
- endp_handle,
- usb_reset_pipe_from_dispatch_completion,
- purb );
-
- goto LBL_OUT;
- }
- }
-
- unlock_dev( pdev, FALSE );
- status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
-
- LBL_OUT:
- usb_unlock_dev( pdev );
- return status;
+ NTSTATUS status;
+ PUSB_DEV pdev;
+ LONG if_idx, endp_idx;
+ DEV_HANDLE endp_handle;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_ENDPOINT pendp;
+
+ PHCD hcd;
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (purb == NULL || dev_mgr == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ endp_handle = purb->endp_handle;
+
+ if (endp_handle == 0)
+ return STATUS_INVALID_PARAMETER;
+
+ status = usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev);
+ if (status != STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ if_idx = if_idx_from_handle(endp_handle);
+ endp_idx = endp_idx_from_handle(endp_handle);
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ status = STATUS_DEVICE_DOES_NOT_EXIST;
+ goto LBL_OUT;
+ }
+
+ if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
+ {
+ unlock_dev(pdev, FALSE);
+ status = STATUS_DEVICE_NOT_READY;
+ goto LBL_OUT;
+ }
+
+ dev_mgr = dev_mgr_from_dev(pdev);
+ hcd = pdev->hcd;
+
+ if (default_endp_handle(endp_handle))
+ {
+ //default endp
+ pendp = &pdev->default_endp;
+ }
+ else if (if_idx >= MAX_INTERFACES_PER_CONFIG || endp_idx >= MAX_ENDPS_PER_IF)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ unlock_dev(pdev, FALSE);
+ goto LBL_OUT;
+ }
+ else
+ {
+ if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
+ {
+ status = STATUS_DEVICE_NOT_READY;
+ unlock_dev(pdev, FALSE);
+ goto LBL_OUT;
+ }
+ pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
+
+ }
+
+ purb->pdev = pdev;
+ purb->pendp = pendp;
+
+ //for default endpoint we have some special process
+ if (default_endp_handle(endp_handle))
+ {
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ if (psetup->bmRequestType == 0 && psetup->bRequest == USB_REQ_SET_CONFIGURATION)
+ {
+ unlock_dev(pdev, FALSE);
+ status = usb_submit_config_urb(purb);
+ goto LBL_OUT;
+ }
+ else if (psetup->bmRequestType == 1 && psetup->bRequest == USB_REQ_SET_INTERFACE)
+ {
+ unlock_dev(pdev, FALSE);
+ // status = STATUS_NOT_SUPPORTED;
+ status = usb_set_interface(purb);
+ goto LBL_OUT;
+ }
+ else if (psetup->bmRequestType == 0x80 && psetup->bRequest == USB_REQ_GET_DESCRIPTOR)
+ {
+ if ((psetup->wValue >> 8) == USB_DT_CONFIG || (psetup->wValue >> 8) == USB_DT_DEVICE)
+ {
+ unlock_dev(pdev, FALSE);
+ status = usb_get_descriptor(pdev, purb);
+ goto LBL_OUT;
+
+ //get the descriptor directly
+ //status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
+ //goto LBL_OUT;
+ }
+ }
+ else if (psetup->bmRequestType == 0x02 && psetup->bRequest == USB_REQ_CLEAR_FEATURE && psetup->wValue == 0) //reset pipe
+ {
+ ULONG endp_addr;
+ BOOL found;
+ endp_addr = psetup->wIndex;
+ if ((endp_addr & 0xf) == 0)
+ {
+ unlock_dev(pdev, FALSE);
+ status = STATUS_INVALID_PARAMETER;
+ goto LBL_OUT;
+ }
+
+ // search for the endp by the endp addr in the wIndex
+ found = FALSE;
+ for(if_idx = 0; if_idx < pdev->usb_config->if_count; if_idx++)
+ {
+ for(endp_idx = 0; endp_idx < pdev->usb_config->interf[if_idx].endp_count; endp_idx++)
+ {
+ pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
+ if (pendp->pusb_endp_desc->bEndpointAddress == endp_addr)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found == TRUE)
+ break;
+ }
+ if (found)
+ endp_handle = usb_make_handle(pdev->dev_id, if_idx, endp_idx);
+ else
+ {
+ unlock_dev(pdev, FALSE);
+ status = STATUS_INVALID_PARAMETER;
+ goto LBL_OUT;
+ }
+ unlock_dev(pdev, FALSE);
+ status = usb_reset_pipe_ex(dev_mgr, endp_handle, usb_reset_pipe_from_dispatch_completion, purb);
+
+ goto LBL_OUT;
+ }
+ }
+
+ unlock_dev(pdev, FALSE);
+ status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
+
+LBL_OUT:
+ usb_unlock_dev(pdev);
+ return status;
}
void
-usb_config_dev_completion(
-PURB purb,
-PVOID context
-)
+usb_config_dev_completion(PURB purb, PVOID context)
{
- PURB puser_urb;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- PUSB_CTRL_SETUP_PACKET psetup;
- ULONG config_val;
- NTSTATUS status;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( purb == NULL )
- {
- return;
- }
- pdev = purb->pdev;
- pendp = purb->pendp;
-
- if( pdev == NULL )
- return;
-
- if( purb->reference != 0 )
- puser_urb = ( PURB ) purb->reference;
- else
- puser_urb = NULL;
-
- lock_dev( pdev, TRUE );
-
- if( puser_urb )
- puser_urb->status = purb->status;
-
- if( purb->status != STATUS_SUCCESS )
- {
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- goto LBL_OUT;
- }
-
- if( dev_state( pdev ) == USB_DEV_STATE_FIRST_CONFIG )
- {
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_ADDRESSED;
- }
- else if( dev_state( pdev ) == USB_DEV_STATE_RECONFIG )
- {
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_CONFIGURED;
-
- }
- goto LBL_OUT;
- }
- // now let's construct usb_config
- if( !pdev->usb_config )
- {
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- config_val = psetup->wValue;
- status = dev_mgr_build_usb_config( pdev,
- &pdev->desc_buf[ sizeof( USB_DEVICE_DESC ) ],
- config_val,
- pdev->pusb_dev_desc->bNumConfigurations );
- if( status != STATUS_SUCCESS )
- {
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_ADDRESSED;
- goto LBL_OUT;
- }
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_CONFIGURED;
- //this usb dev represents physical dev
- if( pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_HUB
- && pdev->pusb_dev_desc->bDeviceSubClass == 0 )
- {
- pdev->flags &= ~USB_DEV_CLASS_MASK;
- pdev->flags |= USB_DEV_CLASS_HUB;
- }
- else if( pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_MASS_STORAGE
- && pdev->pusb_dev_desc->bDeviceSubClass == 0 )
- {
- pdev->flags &= ~USB_DEV_CLASS_MASK;
- pdev->flags |= USB_DEV_CLASS_MASSSTOR;
- }
- else
- {
- pdev->flags &= ~USB_DEV_CLASS_MASK;
- pdev->flags |= USB_DEV_CLASS_SCANNER;
- }
- }
- else
- {
- //not supported
- puser_urb->status = STATUS_NOT_SUPPORTED;
- pdev->flags &= ~USB_DEV_STATE_MASK;
- pdev->flags |= USB_DEV_STATE_CONFIGURED;
- }
- LBL_OUT:
- unlock_dev( pdev, TRUE );
- usb_free_mem( purb );
- if( puser_urb && puser_urb->completion )
- puser_urb->completion( puser_urb, puser_urb->context );
-
- return;
+ PURB puser_urb;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ ULONG config_val;
+ NTSTATUS status;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (purb == NULL)
+ {
+ return;
+ }
+ pdev = purb->pdev;
+ pendp = purb->pendp;
+
+ if (pdev == NULL)
+ return;
+
+ if (purb->reference != 0)
+ puser_urb = (PURB) purb->reference;
+ else
+ puser_urb = NULL;
+
+ lock_dev(pdev, TRUE);
+
+ if (puser_urb)
+ puser_urb->status = purb->status;
+
+ if (purb->status != STATUS_SUCCESS)
+ {
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ goto LBL_OUT;
+ }
+
+ if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG)
+ {
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_ADDRESSED;
+ }
+ else if (dev_state(pdev) == USB_DEV_STATE_RECONFIG)
+ {
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_CONFIGURED;
+
+ }
+ goto LBL_OUT;
+ }
+ // now let's construct usb_config
+ if (!pdev->usb_config)
+ {
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ config_val = psetup->wValue;
+ status = dev_mgr_build_usb_config(pdev,
+ &pdev->desc_buf[sizeof(USB_DEVICE_DESC)],
+ config_val, pdev->pusb_dev_desc->bNumConfigurations);
+ if (status != STATUS_SUCCESS)
+ {
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_ADDRESSED;
+ goto LBL_OUT;
+ }
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_CONFIGURED;
+ //this usb dev represents physical dev
+ if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_HUB && pdev->pusb_dev_desc->bDeviceSubClass == 0)
+ {
+ pdev->flags &= ~USB_DEV_CLASS_MASK;
+ pdev->flags |= USB_DEV_CLASS_HUB;
+ }
+ else if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_MASS_STORAGE
+ && pdev->pusb_dev_desc->bDeviceSubClass == 0)
+ {
+ pdev->flags &= ~USB_DEV_CLASS_MASK;
+ pdev->flags |= USB_DEV_CLASS_MASSSTOR;
+ }
+ else
+ {
+ pdev->flags &= ~USB_DEV_CLASS_MASK;
+ pdev->flags |= USB_DEV_CLASS_SCANNER;
+ }
+ }
+ else
+ {
+ //not supported
+ puser_urb->status = STATUS_NOT_SUPPORTED;
+ pdev->flags &= ~USB_DEV_STATE_MASK;
+ pdev->flags |= USB_DEV_STATE_CONFIGURED;
+ }
+
+LBL_OUT:
+ unlock_dev(pdev, TRUE);
+ usb_free_mem(purb);
+ if (puser_urb && puser_urb->completion)
+ puser_urb->completion(puser_urb, puser_urb->context);
+
+ return;
}
NTSTATUS
-usb_get_descriptor(
-PUSB_DEV pdev,
-PURB purb
-)
+usb_get_descriptor(PUSB_DEV pdev, PURB purb)
{
- PUSB_CTRL_SETUP_PACKET psetup;
- LONG idx, size, count, i;
- PBYTE buf;
- PUSB_CONFIGURATION_DESC pcfg_desc1;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( pdev == NULL || purb == NULL )
- return STATUS_INVALID_PARAMETER;
-
- if( purb->data_buffer == NULL || purb->data_length == 0 )
- {
- return purb->status = STATUS_INVALID_PARAMETER;
- }
-
- lock_dev( pdev, FALSE );
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- if( pdev->desc_buf == NULL )
- {
- purb->status = STATUS_DEVICE_NOT_READY;
- goto LBL_OUT;
- }
-
- if( ( psetup->wValue >> 8 ) == USB_DT_CONFIG )
- {
- idx = ( psetup->wValue & 0xff );
-
- count = pdev->pusb_dev_desc->bNumConfigurations;
-
- if( idx >= count )
- {
- purb->status = STATUS_INVALID_PARAMETER;
- goto LBL_OUT;
- }
- buf = &pdev->desc_buf[ sizeof( USB_DEVICE_DESC ) ];
- pcfg_desc1 = usb_find_config_desc_by_idx( buf, idx, count );
- if( pcfg_desc1 == NULL )
- {
- purb->status = STATUS_UNSUCCESSFUL;
- goto LBL_OUT;
- }
-
- size = pcfg_desc1->wTotalLength;
- size = size > purb->data_length ? purb->data_length : size;
- for( i = 0; i < size; i++ )
- {
- purb->data_buffer[ i ] = ( ( PBYTE )pcfg_desc1 )[ i ];
- }
- purb->status = STATUS_SUCCESS;
- goto LBL_OUT;
-
- }
- else if(( psetup->wValue >> 8 ) == USB_DT_DEVICE )
- {
- size = purb->data_length > sizeof( USB_DEVICE_DESC )
- ? sizeof( USB_DEVICE_DESC )
- : purb->data_length;
-
- for( i = 0; i < size; i ++ )
- {
- purb->data_buffer[ i ] = ( ( PBYTE )pdev->pusb_dev_desc )[ i ];
- }
- purb->status = STATUS_SUCCESS;
- }
+ PUSB_CTRL_SETUP_PACKET psetup;
+ LONG idx, size, count, i;
+ PBYTE buf;
+ PUSB_CONFIGURATION_DESC pcfg_desc1;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (pdev == NULL || purb == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (purb->data_buffer == NULL || purb->data_length == 0)
+ {
+ return purb->status = STATUS_INVALID_PARAMETER;
+ }
+
+ lock_dev(pdev, FALSE);
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ if (pdev->desc_buf == NULL)
+ {
+ purb->status = STATUS_DEVICE_NOT_READY;
+ goto LBL_OUT;
+ }
+
+ if ((psetup->wValue >> 8) == USB_DT_CONFIG)
+ {
+ idx = (psetup->wValue & 0xff);
+
+ count = pdev->pusb_dev_desc->bNumConfigurations;
+
+ if (idx >= count)
+ {
+ purb->status = STATUS_INVALID_PARAMETER;
+ goto LBL_OUT;
+ }
+ buf = &pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
+ pcfg_desc1 = usb_find_config_desc_by_idx(buf, idx, count);
+ if (pcfg_desc1 == NULL)
+ {
+ purb->status = STATUS_UNSUCCESSFUL;
+ goto LBL_OUT;
+ }
+
+ size = pcfg_desc1->wTotalLength;
+ size = size > purb->data_length ? purb->data_length : size;
+ for(i = 0; i < size; i++)
+ {
+ purb->data_buffer[i] = ((PBYTE) pcfg_desc1)[i];
+ }
+ purb->status = STATUS_SUCCESS;
+ goto LBL_OUT;
+
+ }
+ else if ((psetup->wValue >> 8) == USB_DT_DEVICE)
+ {
+ size = purb->data_length > sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : purb->data_length;
+
+ for(i = 0; i < size; i++)
+ {
+ purb->data_buffer[i] = ((PBYTE) pdev->pusb_dev_desc)[i];
+ }
+ purb->status = STATUS_SUCCESS;
+ }
+
LBL_OUT:
- unlock_dev( pdev, FALSE );
- return purb->status;
+ unlock_dev(pdev, FALSE);
+ return purb->status;
}
-LONG usb_count_list( PLIST_HEAD list_head )
+LONG
+usb_count_list(PLIST_HEAD list_head)
{
- LONG count;
- PLIST_ENTRY pthis, pnext;
-
- if( list_head == NULL )
- return 0;
-
- count = 0;
- ListFirst( list_head, pthis );
-
- while( pthis )
- {
- ListNext( list_head, pthis, pnext );
- pthis = pnext;
- count ++;
- }
- return count;
+ LONG count;
+ PLIST_ENTRY pthis, pnext;
+
+ if (list_head == NULL)
+ return 0;
+
+ count = 0;
+ ListFirst(list_head, pthis);
+
+ while (pthis)
+ {
+ ListNext(list_head, pthis, pnext);
+ pthis = pnext;
+ count++;
+ }
+ return count;
}
// checks if processor supports Time Stamp Counter
__inline BOOL
-usb_query_clicks(
-PLARGE_INTEGER clicks
-)
+usb_query_clicks(PLARGE_INTEGER clicks)
{
- BOOL ret_val;
- //so we have to use intel's cpu???
- ret_val = FALSE;
+ BOOL ret_val;
+ //so we have to use intel's cpu???
+ ret_val = FALSE;
#ifdef _MSC_VER
- __asm
- {
- push ebx;
- push eax;
- mov eax, 1; //read version
- cpuid;
- test edx, 0x10; //timer stamp
- jz LBL_OUT;
- // cpuid //serialization
- rdtsc;
- mov ebx, dword ptr [ clicks ];
- mov dword ptr [ ebx ], eax;
- mov dword ptr [ ebx + 4 ], edx;
- mov dword ptr [ ret_val ], TRUE;
+ __asm
+ {
+ push ebx;
+ push eax;
+ mov eax, 1; //read version
+ cpuid;
+ test edx, 0x10; //timer stamp
+ jz LBL_OUT;
+ // cpuid //serialization
+ rdtsc;
+ mov ebx, dword ptr[clicks];
+ mov dword ptr[ebx], eax;
+ mov dword ptr[ebx + 4], edx;
+ mov dword ptr[ret_val], TRUE;
LBL_OUT:
- pop eax;
- pop ebx;
- }
+ pop eax;
+ pop ebx;
+ }
#else
- ret_val = FALSE;
+ ret_val = FALSE;
#endif
- return ret_val;
+ return ret_val;
}
VOID
-usb_wait_ms_dpc(
-ULONG ms
-)
+usb_wait_ms_dpc(ULONG ms)
{
- LARGE_INTEGER start;
- LARGE_INTEGER ticker;
- LARGE_INTEGER freq;
- ULONG interval;
- ULONG expire_count;
-
- KeQueryPerformanceCounter( &freq );
-
- expire_count = 2000000;
- if( cpu_clock_freq )
- expire_count = ( cpu_clock_freq / 1000 ) * ms;
-
- if( usb_query_clicks( &start ) == FALSE )
- {
- ticker.QuadPart = 0;
- while( TRUE )
- {
- KeQuerySystemTime( &ticker );
- interval = ticker.LowPart - start.LowPart;
- if( interval >= ms * 10000 )
- break;
- }
- }
- else
- {
- ticker.QuadPart = 0;
- while( TRUE )
- {
- usb_query_clicks( &ticker );
- interval = ticker.LowPart - start.LowPart;
- if( interval >= expire_count )
- break;
- }
- }
+ LARGE_INTEGER start;
+ LARGE_INTEGER ticker;
+ LARGE_INTEGER freq;
+ ULONG interval;
+ ULONG expire_count;
+
+ KeQueryPerformanceCounter(&freq);
+
+ expire_count = 2000000;
+ if (cpu_clock_freq)
+ expire_count = (cpu_clock_freq / 1000) * ms;
+
+ if (usb_query_clicks(&start) == FALSE)
+ {
+ ticker.QuadPart = 0;
+ while (TRUE)
+ {
+ KeQuerySystemTime(&ticker);
+ interval = ticker.LowPart - start.LowPart;
+ if (interval >= ms * 10000)
+ break;
+ }
+ }
+ else
+ {
+ ticker.QuadPart = 0;
+ while (TRUE)
+ {
+ usb_query_clicks(&ticker);
+ interval = ticker.LowPart - start.LowPart;
+ if (interval >= expire_count)
+ break;
+ }
+ }
}
VOID
-usb_wait_us_dpc(
-ULONG us
-)
+usb_wait_us_dpc(ULONG us)
{
- LARGE_INTEGER start;
- LARGE_INTEGER ticker;
- LARGE_INTEGER freq;
- ULONG interval;
- ULONG expire_count;
-
- KeQueryPerformanceCounter( &freq );
-
- expire_count = 2000000;
- if( cpu_clock_freq )
- expire_count = ( cpu_clock_freq / 1000000 ) * us;
-
- if( usb_query_clicks( &start ) == FALSE )
- {
- ticker.QuadPart = 0;
- while( TRUE )
- {
- KeQuerySystemTime( &ticker );
- interval = ticker.LowPart - start.LowPart;
- if( interval >= us * 10 )
- break;
- }
- }
- else
- {
- ticker.QuadPart = 0;
- while( TRUE )
- {
- usb_query_clicks( &ticker );
- interval = ticker.LowPart - start.LowPart;
- if( interval >= expire_count )
- break;
- }
- }
+ LARGE_INTEGER start;
+ LARGE_INTEGER ticker;
+ LARGE_INTEGER freq;
+ ULONG interval;
+ ULONG expire_count;
+
+ KeQueryPerformanceCounter(&freq);
+
+ expire_count = 2000000;
+ if (cpu_clock_freq)
+ expire_count = (cpu_clock_freq / 1000000) * us;
+
+ if (usb_query_clicks(&start) == FALSE)
+ {
+ ticker.QuadPart = 0;
+ while (TRUE)
+ {
+ KeQuerySystemTime(&ticker);
+ interval = ticker.LowPart - start.LowPart;
+ if (interval >= us * 10)
+ break;
+ }
+ }
+ else
+ {
+ ticker.QuadPart = 0;
+ while (TRUE)
+ {
+ usb_query_clicks(&ticker);
+ interval = ticker.LowPart - start.LowPart;
+ if (interval >= expire_count)
+ break;
+ }
+ }
}
VOID
usb_cal_cpu_freq()
{
- LARGE_INTEGER tick1, tick2;
- LONG i;
- // interval.QuadPart = -40 * 1000 * 1000;
-
- if( cpu_clock_freq >= 100 * 1000 * 1000 ) // assume it is valid
- return;
-
- if( usb_query_clicks( &tick1 ) )
- {
- for( i = 0; i < 25; i++ )
- {
- usb_query_clicks( &tick1 );
- KeStallExecutionProcessor( 40 * 1000 );
- usb_query_clicks( &tick2 );
- cpu_clock_freq += ( ULONG )( tick2.QuadPart - tick1.QuadPart );
- }
- // cpu_clock_freq *= 1000;
- usb_dbg_print( DBGLVL_MAXIMUM, ( "usb_cal_cpu_freq(): cpu frequency = %d Hz\n", cpu_clock_freq ) );
- }
+ LARGE_INTEGER tick1, tick2;
+ LONG i;
+ // interval.QuadPart = -40 * 1000 * 1000;
+
+ if (cpu_clock_freq >= 100 * 1000 * 1000) // assume it is valid
+ return;
+
+ if (usb_query_clicks(&tick1))
+ {
+ for(i = 0; i < 25; i++)
+ {
+ usb_query_clicks(&tick1);
+ KeStallExecutionProcessor(40 * 1000);
+ usb_query_clicks(&tick2);
+ cpu_clock_freq += (ULONG) (tick2.QuadPart - tick1.QuadPart);
+ }
+ // cpu_clock_freq *= 1000;
+ usb_dbg_print(DBGLVL_MAXIMUM, ("usb_cal_cpu_freq(): cpu frequency = %d Hz\n", cpu_clock_freq));
+ }
}
NTSTATUS
-usb_set_interface(
-PURB purb
-)
+usb_set_interface(PURB purb)
{
- ULONG u;
- PURB purb1;
- PCTRL_REQ_STACK pstack;
- PUSB_DEV pdev;
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_ENDPOINT pendp;
- NTSTATUS status;
-
- PHCD hcd;
- USE_BASIC_NON_PENDING_IRQL;
-
- purb1 = purb;
- pdev = purb->pdev;
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
-
- lock_dev( pdev, FALSE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_NOT_CONNECTED;
- }
- if( dev_state( pdev ) < USB_DEV_STATE_CONFIGURED )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_NOT_READY;
- }
-
- hcd = pdev->hcd;
-
- if( psetup->wIndex >= pdev->usb_config->if_count )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_INVALID_PARAMETER;
- }
- if( psetup->wValue >= pdev->usb_config->interf[ psetup->wIndex ].altif_count + 1 )
- {
- unlock_dev( pdev, FALSE );
- return STATUS_INVALID_PARAMETER;
- }
- if( pdev->usb_config->interf[ psetup->wIndex ].pusb_if_desc->bAlternateSetting == psetup->wValue )
- {
- // already the current interface
- unlock_dev( pdev, FALSE );
- return STATUS_SUCCESS;
- }
- // check to see if the endp is busy
- for( u = 0; u < pdev->usb_config->interf[ psetup->wIndex ].endp_count; u++ )
- {
- // This check is not adquate. Since we do not have mechanism to block the new coming
- // request during this request. the caller must guarantee no active or pending
- // usb request on these endpoint.
- pendp = &pdev->usb_config->interf[ psetup->wIndex ].endp[ u ];
- if( usb_endp_busy_count( pendp ) )
- {
- // active urb on that endp
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_NOT_READY;
- }
- if( IsListEmpty( &pendp->urb_list ) )
- {
- // pending urb on that endp
- unlock_dev( pdev, FALSE );
- return STATUS_DEVICE_NOT_READY;
- }
- }
- unlock_dev( pdev, FALSE );
-
- if( purb1->ctrl_req_context.ctrl_stack_count == 0 )
- {
- // ok, we have one stack cell for our use
- if( purb1->completion != NULL )
- {
- purb1->ctrl_req_context.ctrl_stack_count = 1;
- purb1->ctrl_req_context.ctrl_cur_stack = 0;
- }
- else
- {
- // use urb's completion and context
- purb1->completion = usb_set_interface_completion;
- purb1->context = pdev;
- }
- }
- else
- {
- if( purb->ctrl_req_context.ctrl_cur_stack + 1 >= purb->ctrl_req_context.ctrl_stack_count )
- {
- // stack full, let's allocate one new urb, we need stack size one
- purb1 = usb_alloc_mem( NonPagedPool, sizeof( URB ) );
- if( purb1 == NULL )
- return STATUS_NO_MEMORY;
-
- RtlCopyMemory( purb1, purb, sizeof( URB ) );
-
- // we do not use stack
- RtlZeroMemory( purb1->ctrl_req_stack, sizeof( CTRL_REQ_STACK ) );
- purb1->context = pdev;
- purb1->completion = usb_set_interface_completion;
- purb1->ctrl_parent_urb = purb;
- purb1->ctrl_req_context.ctrl_req_flags = CTRL_PARENT_URB_VALID;
-
- goto LBL_SEND_URB;
- }
- else
- purb->ctrl_req_context.ctrl_cur_stack++;
- }
-
- u = purb1->ctrl_req_context.ctrl_cur_stack;
- RtlZeroMemory( &purb1->ctrl_req_stack[ u ], sizeof( CTRL_REQ_STACK ) );
- pstack = &purb1->ctrl_req_stack[ u ];
- pstack->context = pdev;
- pstack->urb_completion = usb_set_interface_completion;
+ ULONG u;
+ PURB purb1;
+ PCTRL_REQ_STACK pstack;
+ PUSB_DEV pdev;
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_ENDPOINT pendp;
+ NTSTATUS status;
+
+ PHCD hcd;
+ USE_BASIC_NON_PENDING_IRQL;
+
+ purb1 = purb;
+ pdev = purb->pdev;
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+
+ lock_dev(pdev, FALSE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_NOT_CONNECTED;
+ }
+ if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_NOT_READY;
+ }
+
+ hcd = pdev->hcd;
+
+ if (psetup->wIndex >= pdev->usb_config->if_count)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (psetup->wValue >= pdev->usb_config->interf[psetup->wIndex].altif_count + 1)
+ {
+ unlock_dev(pdev, FALSE);
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (pdev->usb_config->interf[psetup->wIndex].pusb_if_desc->bAlternateSetting == psetup->wValue)
+ {
+ // already the current interface
+ unlock_dev(pdev, FALSE);
+ return STATUS_SUCCESS;
+ }
+ // check to see if the endp is busy
+ for(u = 0; u < pdev->usb_config->interf[psetup->wIndex].endp_count; u++)
+ {
+ // This check is not adquate. Since we do not have mechanism to block the new coming
+ // request during this request. the caller must guarantee no active or pending
+ // usb request on these endpoint.
+ pendp = &pdev->usb_config->interf[psetup->wIndex].endp[u];
+ if (usb_endp_busy_count(pendp))
+ {
+ // active urb on that endp
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_NOT_READY;
+ }
+ if (IsListEmpty(&pendp->urb_list))
+ {
+ // pending urb on that endp
+ unlock_dev(pdev, FALSE);
+ return STATUS_DEVICE_NOT_READY;
+ }
+ }
+ unlock_dev(pdev, FALSE);
+
+ if (purb1->ctrl_req_context.ctrl_stack_count == 0)
+ {
+ // ok, we have one stack cell for our use
+ if (purb1->completion != NULL)
+ {
+ purb1->ctrl_req_context.ctrl_stack_count = 1;
+ purb1->ctrl_req_context.ctrl_cur_stack = 0;
+ }
+ else
+ {
+ // use urb's completion and context
+ purb1->completion = usb_set_interface_completion;
+ purb1->context = pdev;
+ }
+ }
+ else
+ {
+ if (purb->ctrl_req_context.ctrl_cur_stack + 1 >= purb->ctrl_req_context.ctrl_stack_count)
+ {
+ // stack full, let's allocate one new urb, we need stack size one
+ purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB));
+ if (purb1 == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlCopyMemory(purb1, purb, sizeof(URB));
+
+ // we do not use stack
+ RtlZeroMemory(purb1->ctrl_req_stack, sizeof(CTRL_REQ_STACK));
+ purb1->context = pdev;
+ purb1->completion = usb_set_interface_completion;
+ purb1->ctrl_parent_urb = purb;
+ purb1->ctrl_req_context.ctrl_req_flags = CTRL_PARENT_URB_VALID;
+
+ goto LBL_SEND_URB;
+ }
+ else
+ purb->ctrl_req_context.ctrl_cur_stack++;
+ }
+
+ u = purb1->ctrl_req_context.ctrl_cur_stack;
+ RtlZeroMemory(&purb1->ctrl_req_stack[u], sizeof(CTRL_REQ_STACK));
+ pstack = &purb1->ctrl_req_stack[u];
+ pstack->context = pdev;
+ pstack->urb_completion = usb_set_interface_completion;
LBL_SEND_URB:
- if( hcd == NULL )
- return STATUS_INVALID_PARAMETER;
+ if (hcd == NULL)
+ return STATUS_INVALID_PARAMETER;
- status = hcd->hcd_submit_urb( hcd, purb->pdev, purb->pendp, purb );
- return status;
+ status = hcd->hcd_submit_urb(hcd, purb->pdev, purb->pendp, purb);
+ return status;
}
#define usb_complete_and_free_ctrl_urb( pURB ) \
{\
- UCHAR i, j;\
- i = pURB->ctrl_req_context.ctrl_cur_stack;\
- j = pURB->ctrl_req_context.ctrl_stack_count;\
- usb_call_ctrl_completion( pURB );\
- if( i == 0xff || j == 0 )\
- usb_free_mem( pURB );\
+ UCHAR i, j;\
+ i = pURB->ctrl_req_context.ctrl_cur_stack;\
+ j = pURB->ctrl_req_context.ctrl_stack_count;\
+ usb_call_ctrl_completion( pURB );\
+ if( i == 0xff || j == 0 )\
+ usb_free_mem( pURB );\
}
VOID
-usb_set_interface_completion(
-PURB purb,
-PVOID context
-)
+usb_set_interface_completion(PURB purb, PVOID context)
{
- PUSB_CTRL_SETUP_PACKET psetup;
- PUSB_INTERFACE pif, palt_if;
- USB_INTERFACE temp_if;
- UCHAR if_idx, if_alt_idx;
- PUSB_DEV pdev;
- PUSB_ENDPOINT pendp;
- ULONG i;
- PLIST_ENTRY pthis, pnext;
-
- USE_BASIC_NON_PENDING_IRQL;
-
- if( purb == NULL )
- return;
-
- if( purb->status == STATUS_SUCCESS )
- {
- psetup = ( PUSB_CTRL_SETUP_PACKET )purb->setup_packet;
- if_idx = ( UCHAR )psetup->wIndex;
- if_alt_idx = ( UCHAR )psetup->wValue;
- pdev = purb->pdev;
- RtlZeroMemory( &temp_if, sizeof( USB_INTERFACE ) );
-
- lock_dev( pdev, TRUE );
- if( dev_state( pdev ) == USB_DEV_STATE_ZOMB )
- {
- unlock_dev( pdev, TRUE );
- purb->status = STATUS_DEVICE_NOT_CONNECTED;
- purb->data_length = 0;
- }
- else
- {
- // let's swap the interface
- pif = &pdev->usb_config->interf[ if_idx ];
- ListFirst( &pif->altif_list, pthis );
- pnext = pthis;
- do
- {
- palt_if = struct_ptr( pthis, USB_INTERFACE, altif_list );
- if( palt_if->pusb_if_desc->bAlternateSetting == if_alt_idx )
- {
- break;
- }
- palt_if = NULL;
- ListNext( &pif->altif_list, pthis, pnext );
- pthis = pnext;
-
- }while( pthis );
-
- if( palt_if != NULL )
- {
- RtlCopyMemory( &temp_if, palt_if, sizeof( USB_INTERFACE ) );
-
- palt_if->endp_count = pif->endp_count;
- RtlCopyMemory( palt_if->endp, pif->endp, sizeof( pif->endp ) );
- palt_if->pif_drv = pif->pif_drv;
- palt_if->pusb_if_desc = pif->pusb_if_desc;
- for( i = 0; i < palt_if->endp_count; i++ )
- {
- pendp = &palt_if->endp[ i ];
- InitializeListHead( &pendp->urb_list );
- pendp->flags = 0;
- }
-
- RtlCopyMemory( pif->endp, temp_if.endp, sizeof( temp_if.endp ) );
- pif->endp_count = temp_if.endp_count;
- pif->pusb_if_desc = temp_if.pusb_if_desc;
- for( i = 0; i < pif->endp_count; i++ )
- {
- pendp = &pif->endp[ i ];
- InitializeListHead( &pendp->urb_list );
- pendp->flags = 0;
- }
- }
- else
- {
- TRAP();
- purb->status = STATUS_UNSUCCESSFUL;
- }
- }
- unlock_dev( pdev, TRUE );
- }
-
- // for recursive reason, we have to store the parameter ahead
- usb_complete_and_free_ctrl_urb( purb );
+ PUSB_CTRL_SETUP_PACKET psetup;
+ PUSB_INTERFACE pif, palt_if;
+ USB_INTERFACE temp_if;
+ UCHAR if_idx, if_alt_idx;
+ PUSB_DEV pdev;
+ PUSB_ENDPOINT pendp;
+ ULONG i;
+ PLIST_ENTRY pthis, pnext;
+
+ USE_BASIC_NON_PENDING_IRQL;
+
+ if (purb == NULL)
+ return;
+
+ if (purb->status == STATUS_SUCCESS)
+ {
+ psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
+ if_idx = (UCHAR) psetup->wIndex;
+ if_alt_idx = (UCHAR) psetup->wValue;
+ pdev = purb->pdev;
+ RtlZeroMemory(&temp_if, sizeof(USB_INTERFACE));
+
+ lock_dev(pdev, TRUE);
+ if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
+ {
+ unlock_dev(pdev, TRUE);
+ purb->status = STATUS_DEVICE_NOT_CONNECTED;
+ purb->data_length = 0;
+ }
+ else
+ {
+ // let's swap the interface
+ pif = &pdev->usb_config->interf[if_idx];
+ ListFirst(&pif->altif_list, pthis);
+ pnext = pthis;
+ do
+ {
+ palt_if = struct_ptr(pthis, USB_INTERFACE, altif_list);
+ if (palt_if->pusb_if_desc->bAlternateSetting == if_alt_idx)
+ {
+ break;
+ }
+ palt_if = NULL;
+ ListNext(&pif->altif_list, pthis, pnext);
+ pthis = pnext;
+
+ } while (pthis);
+
+ if (palt_if != NULL)
+ {
+ RtlCopyMemory(&temp_if, palt_if, sizeof(USB_INTERFACE));
+
+ palt_if->endp_count = pif->endp_count;
+ RtlCopyMemory(palt_if->endp, pif->endp, sizeof(pif->endp));
+ palt_if->pif_drv = pif->pif_drv;
+ palt_if->pusb_if_desc = pif->pusb_if_desc;
+ for(i = 0; i < palt_if->endp_count; i++)
+ {
+ pendp = &palt_if->endp[i];
+ InitializeListHead(&pendp->urb_list);
+ pendp->flags = 0;
+ }
+
+ RtlCopyMemory(pif->endp, temp_if.endp, sizeof(temp_if.endp));
+ pif->endp_count = temp_if.endp_count;
+ pif->pusb_if_desc = temp_if.pusb_if_desc;
+ for(i = 0; i < pif->endp_count; i++)
+ {
+ pendp = &pif->endp[i];
+ InitializeListHead(&pendp->urb_list);
+ pendp->flags = 0;
+ }
+ }
+ else
+ {
+ TRAP();
+ purb->status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ unlock_dev(pdev, TRUE);
+ }
+
+ // for recursive reason, we have to store the parameter ahead
+ usb_complete_and_free_ctrl_urb(purb);
}
-VOID
-usb_call_ctrl_completion(
-PURB purb
-)
// can only be called when current completion finished and called only in
// urb completion. And this func may be called recursively, if this routine
// is called, the urb must be treated as released.
+VOID
+usb_call_ctrl_completion(PURB purb)
{
- PURB parent_urb;
- PCTRL_REQ_STACK pstack;
- ULONG i;
-
-
- if( purb == NULL )
- return;
-
- if( purb->ctrl_req_context.ctrl_stack_count != 0 )
- {
- i = purb->ctrl_req_context.ctrl_cur_stack;
- if( i > 0 && i < 0x10 )
- {
- i --;
- purb->ctrl_req_context.ctrl_cur_stack = ( UCHAR )i;
- pstack = &purb->ctrl_req_stack[ i ];
- if( pstack->urb_completion )
- {
- pstack->urb_completion( purb, pstack->context );
- }
- else
- TRAP();
- }
- else if( i == 0 )
- {
- i = purb->ctrl_req_context.ctrl_cur_stack = 0xff;
- if( purb->completion )
- {
- purb->completion( purb, purb->context );
- }
- else
- TRAP();
- }
- else if( i == 0xff )
- {
- // only parent urb's completion, if parent urb exists, can be called
- if( purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID )
- {
- parent_urb = purb->ctrl_parent_urb;
- if( parent_urb )
- {
- pstack = &parent_urb->ctrl_req_stack[ parent_urb->ctrl_req_context.ctrl_cur_stack ];
- pstack->urb_completion( parent_urb, pstack->context );
- }
- else
- TRAP();
- }
- }
- else
- TRAP();
- }
- else if( purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID )
- {
- // this is the case when the child urb won't use the stack
- parent_urb = purb->ctrl_parent_urb;
- if( parent_urb )
- {
- // pstack = &parent_urb->ctrl_req_stack[ parent_urb->ctrl_req_context.ctrl_cur_stack ];
- // pstack->urb_completion( parent_urb, pstack->context );
- usb_call_ctrl_completion( parent_urb );
- }
- else
- TRAP();
- }
- else
- return;
+ PURB parent_urb;
+ PCTRL_REQ_STACK pstack;
+ ULONG i;
+
+
+ if (purb == NULL)
+ return;
+
+ if (purb->ctrl_req_context.ctrl_stack_count != 0)
+ {
+ i = purb->ctrl_req_context.ctrl_cur_stack;
+ if (i > 0 && i < 0x10)
+ {
+ i--;
+ purb->ctrl_req_context.ctrl_cur_stack = (UCHAR) i;
+ pstack = &purb->ctrl_req_stack[i];
+ if (pstack->urb_completion)
+ {
+ pstack->urb_completion(purb, pstack->context);
+ }
+ else
+ TRAP();
+ }
+ else if (i == 0)
+ {
+ i = purb->ctrl_req_context.ctrl_cur_stack = 0xff;
+ if (purb->completion)
+ {
+ purb->completion(purb, purb->context);
+ }
+ else
+ TRAP();
+ }
+ else if (i == 0xff)
+ {
+ // only parent urb's completion, if parent urb exists, can be called
+ if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID)
+ {
+ parent_urb = purb->ctrl_parent_urb;
+ if (parent_urb)
+ {
+ pstack = &parent_urb->ctrl_req_stack[parent_urb->ctrl_req_context.ctrl_cur_stack];
+ pstack->urb_completion(parent_urb, pstack->context);
+ }
+ else
+ TRAP();
+ }
+ }
+ else
+ TRAP();
+ }
+ else if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID)
+ {
+ // this is the case when the child urb won't use the stack
+ parent_urb = purb->ctrl_parent_urb;
+ if (parent_urb)
+ {
+ // pstack = &parent_urb->ctrl_req_stack[ parent_urb->ctrl_req_context.ctrl_cur_stack ];
+ // pstack->urb_completion( parent_urb, pstack->context );
+ usb_call_ctrl_completion(parent_urb);
+ }
+ else
+ TRAP();
+ }
+ else
+ return;
}
-