mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[USBDRV]
- Terminate the NT4 USB driver svn path=/trunk/; revision=55569
This commit is contained in:
parent
98d609d403
commit
65beefbcd8
38 changed files with 0 additions and 31393 deletions
|
@ -1,2 +0,0 @@
|
|||
|
||||
add_subdirectory(usbdrv)
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<directory name="usbdrv">
|
||||
<xi:include href="usbdrv/usbdrv.rbuild" />
|
||||
</directory>
|
||||
</group>
|
|
@ -1,35 +0,0 @@
|
|||
|
||||
add_definitions(
|
||||
-DINCLUDE_EHCI
|
||||
-D_MULTI_UHCI
|
||||
-D_MULTI_EHCI
|
||||
-D_X86)
|
||||
|
||||
list(APPEND SOURCE
|
||||
ehci.c
|
||||
ohci.c
|
||||
uhci.c
|
||||
roothub.c
|
||||
hub.c
|
||||
td.c
|
||||
usb.c
|
||||
umss.c
|
||||
bulkonly.c
|
||||
cbi.c
|
||||
devmgr.c
|
||||
dmgrdisp.c
|
||||
compdrv.c
|
||||
etd.c
|
||||
gendrv.c
|
||||
mouse.c
|
||||
keyboard.c
|
||||
usbdriver.rc)
|
||||
|
||||
add_library(usbdrv SHARED ${SOURCE})
|
||||
|
||||
set_module_type(usbdrv kernelmodedriver)
|
||||
add_importlibs(usbdrv ntoskrnl hal)
|
||||
|
||||
add_pch(usbdrv usbdriver.h)
|
||||
|
||||
add_cd_file(TARGET usbdrv DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
|
@ -1,797 +0,0 @@
|
|||
/**
|
||||
* bulkonly.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
#include <ntddscsi.h>
|
||||
|
||||
#define OLYMPUS_CSW( pdev_EXT, staTUS ) \
|
||||
( ( ( pdev_EXT )->flags & UMSS_DEV_FLAG_OLYMPUS_DEV ) ? ( ( staTUS ) == CSW_OLYMPUS_SIGNATURE ) : FALSE )
|
||||
|
||||
BOOLEAN umss_clear_pass_through_length(PIO_PACKET io_packet);
|
||||
|
||||
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_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext);
|
||||
|
||||
VOID umss_sync_submit_urb_completion(PURB purb, PVOID context);
|
||||
|
||||
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_transfer_data_complete(PURB purb, PVOID reference);
|
||||
|
||||
VOID umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference);
|
||||
|
||||
VOID umss_bulkonly_reset_recovery(IN PVOID reference);
|
||||
|
||||
VOID umss_bulkonly_get_status_complete(IN PURB purb, IN PVOID context);
|
||||
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Handler for all I/O requests using bulk-only protocol.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceExtension - Device extension for our FDO.
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE
|
||||
|
||||
--*/
|
||||
NTSTATUS
|
||||
umss_bulkonly_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext, IN PIO_PACKET io_packet)
|
||||
{
|
||||
PCOMMAND_BLOCK_WRAPPER cbw;
|
||||
NTSTATUS status;
|
||||
|
||||
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));
|
||||
|
||||
// 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->bCBWLun = io_packet->lun;
|
||||
cbw->bCBWLength = io_packet->cdb_length;
|
||||
RtlCopyMemory(cbw->CBWCB, io_packet->cdb, sizeof(cbw->CBWCB));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
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;
|
||||
}
|
||||
|
||||
VOID
|
||||
umss_bulkonly_send_cbw_completion(IN PURB purb, IN 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);
|
||||
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Device failed CBW without stalling, so complete with error
|
||||
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);
|
||||
}
|
||||
|
||||
usb_free_mem(purb);
|
||||
|
||||
purb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
VOID
|
||||
umss_sync_submit_urb_completion(PURB purb, PVOID context)
|
||||
{
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Worker function used to execute a reset recovery after a stall.
|
||||
|
||||
Arguments:
|
||||
|
||||
Reference - Our device extension.
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE
|
||||
|
||||
--*/
|
||||
VOID
|
||||
umss_bulkonly_reset_recovery(IN PVOID reference)
|
||||
{
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext;
|
||||
URB urb;
|
||||
NTSTATUS status;
|
||||
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:
|
||||
// 1. Send device a mass storage reset command on the default endpoint.
|
||||
// 2. Reset the bulk-in endpoint.
|
||||
// 3. Reset the bulk-out endpoint.
|
||||
// 4. Complete the original I/O request with error.
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
// Send mass storage reset command to device
|
||||
status = umss_sync_submit_urb(pdev_ext, &urb);
|
||||
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
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);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
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);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM,
|
||||
("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n"));
|
||||
}
|
||||
}
|
||||
umss_complete_request(pdev_ext, status);
|
||||
}
|
||||
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Schedules a bulk data transfer to/from the device.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceExtension - Our FDO's device extension.
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE
|
||||
|
||||
--*/
|
||||
VOID
|
||||
umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
PVOID data_buf;
|
||||
ULONG data_buf_length;
|
||||
NTSTATUS status;
|
||||
UCHAR trans_dir = USB_DIR_IN; // FIXME: Initialize this properly!
|
||||
|
||||
// Steps for data phase
|
||||
// 1. Get data buffer fragment (either SGD list, flat buffer, or none).
|
||||
// 2. Schedule data transfer if neccessary.
|
||||
// 3. Repeat 1-2 until all data transferred, or endpoint stalls.
|
||||
// 4. Move to status phase.
|
||||
|
||||
// Get next data buffer element, if any
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*++
|
||||
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;
|
||||
|
||||
status = purb->status;
|
||||
|
||||
dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
|
||||
|
||||
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);
|
||||
|
||||
// Device failed data phase
|
||||
// Check if we need to clear stalled pipe
|
||||
if (usb_halted(status))
|
||||
{
|
||||
PULONG buf;
|
||||
buf = usb_alloc_mem(NonPagedPool, 32);
|
||||
if (!buf) return;
|
||||
|
||||
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"));
|
||||
TRAP();
|
||||
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 );
|
||||
}
|
||||
|
||||
usb_free_mem(purb);
|
||||
purb = NULL;
|
||||
|
||||
return; // STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference)
|
||||
{
|
||||
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"));
|
||||
|
||||
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;
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
VOID
|
||||
umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Completion handler for bulk data transfer request.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - Previous device object.
|
||||
Irp - Irp used for sending command.
|
||||
Reference - Our FDO.
|
||||
|
||||
Return Value:
|
||||
|
||||
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;
|
||||
|
||||
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)))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((status != STATUS_SUCCESS) && (usb_halted(status)) && (pdev_ext->retry))
|
||||
{
|
||||
// Device stalled CSW transfer, retry once before failing
|
||||
PULONG buf;
|
||||
pdev_ext->retry = FALSE;
|
||||
|
||||
buf = usb_alloc_mem(NonPagedPool, 32);
|
||||
if (!buf) return;
|
||||
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Queries Bulk-Only device for maximum LUN number
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceExtension - Our device extension.
|
||||
|
||||
Return Value:
|
||||
|
||||
Maximum LUN number for device, or 0 if error occurred.
|
||||
|
||||
--*/
|
||||
CHAR
|
||||
umss_bulkonly_get_maxlun(IN PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
PURB purb = NULL;
|
||||
UCHAR max_lun;
|
||||
NTSTATUS status;
|
||||
|
||||
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"));
|
||||
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);
|
||||
|
||||
// Send get max lun command to device
|
||||
status = umss_sync_submit_urb(pdev_ext, purb);
|
||||
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = NULL;
|
||||
*buf_length = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
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;
|
||||
|
||||
pdev_ext->retry = TRUE;
|
||||
|
||||
cbw = usb_alloc_mem(NonPagedPool, sizeof(COMMAND_BLOCK_WRAPPER));
|
||||
if (!cbw) return STATUS_NO_MEMORY;
|
||||
|
||||
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->dCBWDataTransferLength = pdev_ext->io_packet.sense_data_length;
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
umss_clear_pass_through_length(PIO_PACKET io_packet)
|
||||
{
|
||||
//
|
||||
// clear the respective data length to meet request of scsi pass through requirement.
|
||||
//
|
||||
|
||||
BOOLEAN 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;
|
||||
}
|
|
@ -1,302 +0,0 @@
|
|||
/**
|
||||
* cbi.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
VOID umss_cbi_send_adsc_complete(PURB purb, PVOID context);
|
||||
VOID umss_cbi_transfer_data(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_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)
|
||||
{
|
||||
PURB purb;
|
||||
NTSTATUS status;
|
||||
|
||||
UNREFERENCED_PARAMETER(dir);
|
||||
|
||||
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
|
||||
if (!purb) return STATUS_NO_MEMORY;
|
||||
|
||||
// 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)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
return status;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
umss_cbi_send_adsc_complete(PURB purb, PVOID context)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext;
|
||||
PIO_PACKET io_packet;
|
||||
|
||||
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
|
||||
io_packet = &pdev_ext->io_packet;
|
||||
|
||||
status = purb->status;
|
||||
|
||||
dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
|
||||
|
||||
if (!usb_success(status))
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
}
|
||||
else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
|
||||
{
|
||||
// Device supports interrupt pipe, so get status
|
||||
umss_cbi_get_status(pdev_ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Device does not report status, so complete request
|
||||
umss_complete_request(pdev_ext, STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
usb_free_mem(purb);
|
||||
purb = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
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));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
VOID
|
||||
umss_cbi_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
PVOID buffer = NULL;
|
||||
ULONG buffer_length;
|
||||
|
||||
// Get next data buffer element, if any.
|
||||
buffer = umss_get_buffer(pdev_ext, &buffer_length);
|
||||
if (NULL == buffer)
|
||||
{
|
||||
//Done with data phase, so move to status phase if (supported)
|
||||
|
||||
if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
|
||||
{
|
||||
// Device supports interrupt pipe, so get status
|
||||
umss_cbi_get_status(pdev_ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No interrupt pipe, so just complete the request
|
||||
umss_complete_request(pdev_ext, STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
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))
|
||||
{
|
||||
// Device failed Data Transfer
|
||||
// Check if we need to clear stalled pipe
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Transfer succeeded
|
||||
// umss_cbi_transfer_data( pdev_ext );
|
||||
umss_complete_request(pdev_ext, STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
umss_cbi_get_status(PUMSS_DEVICE_EXTENSION pdev_ext)
|
||||
{
|
||||
PURB purb;
|
||||
NTSTATUS status;
|
||||
|
||||
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
|
||||
if (purb == NULL)
|
||||
return;
|
||||
|
||||
// Build a URB for our interrupt transfer
|
||||
UsbBuildInterruptOrBulkTransferRequest(purb,
|
||||
usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx,
|
||||
pdev_ext->int_endp_idx), (PUCHAR) & pdev_ext->idb,
|
||||
sizeof(INTERRUPT_DATA_BLOCK), umss_cbi_get_status_complete,
|
||||
pdev_ext, 0);
|
||||
|
||||
// Call USB driver stack
|
||||
status = usb_submit_urb(pdev_ext->dev_mgr, purb);
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
usb_free_mem(purb);
|
||||
purb = NULL;
|
||||
return;
|
||||
}
|
||||
dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
umss_cbi_get_status_complete(PURB purb, PVOID context)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext;
|
||||
PINTERRUPT_DATA_BLOCK idb;
|
||||
|
||||
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
|
||||
|
||||
status = purb->status;
|
||||
dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp);
|
||||
|
||||
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 (!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"));
|
||||
TRAP();
|
||||
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)))
|
||||
{
|
||||
umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
umss_complete_request(pdev_ext, STATUS_SUCCESS);
|
||||
}
|
||||
}
|
|
@ -1,511 +0,0 @@
|
|||
/**
|
||||
* compdrv.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//this driver is part of the dev manager responsible to manage if device
|
||||
#include "usbdriver.h"
|
||||
|
||||
VOID compdev_set_cfg_completion(PURB purb, PVOID context);
|
||||
VOID compdev_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN compdev_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle);
|
||||
BOOLEAN compdev_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN compdev_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
compdev_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dev_mgr);
|
||||
UNREFERENCED_PARAMETER(pdriver);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
compdev_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
|
||||
{
|
||||
PURB purb;
|
||||
PUSB_CTRL_SETUP_PACKET psetup;
|
||||
NTSTATUS status;
|
||||
PUCHAR buf;
|
||||
LONG credit, i, j;
|
||||
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)
|
||||
{
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
DEV_HANDLE dev_handle;
|
||||
|
||||
UNREFERENCED_PARAMETER(param);
|
||||
UNREFERENCED_PARAMETER(context);
|
||||
UNREFERENCED_PARAMETER(event);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
compdev_post_event_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
|
||||
{
|
||||
PUSB_EVENT pevent;
|
||||
BOOLEAN bret;
|
||||
PUSB_DEV pdev;
|
||||
USE_BASIC_NON_PENDING_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)
|
||||
{
|
||||
DEV_HANDLE dev_handle;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PUSB_DRIVER pdriver;
|
||||
NTSTATUS status;
|
||||
PUSB_DEV pdev;
|
||||
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, 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)
|
||||
{
|
||||
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;
|
||||
|
||||
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 interfaces 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;
|
||||
}
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): got %d interfaces\n",
|
||||
(LONG)pconfig_desc->bNumInterfaces));
|
||||
|
||||
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
|
||||
DEV_CONNECT_DATA param;
|
||||
|
||||
if (pcand->disp_tbl.dev_connect)
|
||||
{
|
||||
param.dev_mgr = dev_mgr;
|
||||
param.pdriver = pcand;
|
||||
param.dev_handle = 0;
|
||||
param.if_desc = pif_desc;
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
// note:
|
||||
// dev_mgr_set_driver seems to be dangeous since compdev, gendrv and hub and
|
||||
// umss use it to set the driver while there may exist race condition when the
|
||||
// dev_mgr_disconnect_dev is called. If the driver is set and the
|
||||
// disconnect_dev cut in immediately, the stop or disconnect may not function
|
||||
// well. Now hub and compdev's set dev_mgr_set_driver are ok.
|
||||
//
|
||||
// another danger comes from umss's dev irp processing. This may confuse the device
|
||||
// when the disk is being read or written, and at the same time dmgrdisp's dispatch
|
||||
// route irp request to the device a control request.
|
|
@ -1,71 +0,0 @@
|
|||
#ifndef _UHCIDBG_H_
|
||||
#define _UHCIDBG_H_
|
||||
|
||||
#define DBGLVL_OFF 0 // if gDebugLevel set to this, there is NO debug output
|
||||
#define DBGLVL_MINIMUM 1 // minimum verbosity
|
||||
#define DBGLVL_DEFAULT 2 // default verbosity level if no registry override
|
||||
#define DBGLVL_MEDIUM 3 // medium verbosity
|
||||
#define DBGLVL_HIGH 4 // highest 'safe' level (without severely affecting timing )
|
||||
#define DBGLVL_MAXIMUM 5 // maximum level, may be dangerous
|
||||
#define DBGLVL_ULTRA 6 // ultra, prints hell lots of stuff from ISR/allocs/etc
|
||||
|
||||
#ifndef DBGSTR_PREFIX
|
||||
#define DBGSTR_PREFIX "wood_uhci: "
|
||||
#endif
|
||||
|
||||
#define DEBUG_UHCI TRUE
|
||||
#define DEBUG_HUB TRUE
|
||||
#define DEBUG_DEV_MGR TRUE
|
||||
|
||||
#define DPRINT DbgPrint
|
||||
|
||||
|
||||
#define UHCI_DBGOUTSIZE 512
|
||||
|
||||
#define hcd_dbg_print_cond( ilev, cond, _x_) \
|
||||
if( debug_level && ( ilev <= debug_level ) && ( cond )) { \
|
||||
DPRINT( DBGSTR_PREFIX ); \
|
||||
DPRINT _x_ ; \
|
||||
}
|
||||
|
||||
#define hcd_dbg_print( ilev, _x_) hcd_dbg_print_cond( ilev, TRUE, _x_ )
|
||||
|
||||
extern ULONG debug_level;
|
||||
|
||||
#if DBG
|
||||
|
||||
#define uhci_dbg_print_cond( ilev, cond, _x_ ) hcd_dbg_print_cond( ilev, cond, _x_ )
|
||||
#define uhci_dbg_print( ilev, _x_) hcd_dbg_print_cond( ilev, TRUE, _x_ )
|
||||
|
||||
#define uhci_trap_cond( ilev, cond ) if ( debug_level && ( ilev <= debug_level ) && (cond) ) TRAP()
|
||||
#define uhci_trap( ilev ) uhci_trap_cond( ilev, TRUE )
|
||||
|
||||
|
||||
#define uhci_assert( cond ) ASSERT( cond )
|
||||
#define dbg_count_list( _x_ ) usb_count_list( _x_ )
|
||||
|
||||
#define TRAP() DbgBreakPoint()
|
||||
|
||||
#else // if not DBG
|
||||
|
||||
// dummy definitions that go away in the retail build
|
||||
|
||||
#define uhci_dbg_print_cond( ilev, cond, _x_ )
|
||||
#define uhci_dbg_print( ilev, _x_)
|
||||
#define uhci_trap_cont( ilev, cond )
|
||||
#define uhci_trap( ilev )
|
||||
#define uhci_assert( cond )
|
||||
#define TRAP()
|
||||
#define dbg_count_list( _x_ ) 0
|
||||
|
||||
#endif //DBG
|
||||
|
||||
#define usb_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ )
|
||||
#define ehci_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ )
|
||||
#define ohci_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ )
|
||||
#define ehci_dbg_print_cond( ilev, cond, _x_ ) uhci_dbg_print_cond( ilev, cond, _x_ )
|
||||
|
||||
#define DO_NOTHING
|
||||
|
||||
LONG usb_count_list( struct _LIST_ENTRY* list_head );
|
||||
#endif // included
|
File diff suppressed because it is too large
Load diff
|
@ -1,281 +0,0 @@
|
|||
#ifndef __DEVMGR_H__
|
||||
#define __DEVMGR_H__
|
||||
|
||||
typedef struct _DEV_CONNECT_DATA
|
||||
{
|
||||
DEV_HANDLE dev_handle;
|
||||
struct _USB_DRIVER *pdriver;
|
||||
struct _USB_DEV_MANAGER *dev_mgr;
|
||||
PUSB_INTERFACE_DESC if_desc;
|
||||
|
||||
} DEV_CONNECT_DATA, *PDEV_CONNECT_DATA;
|
||||
|
||||
typedef BOOLEAN ( *PDEV_CONNECT_EX )( PDEV_CONNECT_DATA init_param, DEV_HANDLE dev_handle );
|
||||
typedef BOOLEAN ( *PDEV_CONNECT )( struct _USB_DEV_MANAGER *dev_mgr, DEV_HANDLE dev_handle );
|
||||
typedef BOOLEAN ( *PDRVR_INIT )( struct _USB_DEV_MANAGER *dev_mgr, struct _USB_DRIVER *pdriver );
|
||||
|
||||
typedef struct _PNP_DISPATCH
|
||||
{
|
||||
ULONG version;
|
||||
PDEV_CONNECT_EX dev_connect;
|
||||
PDEV_CONNECT dev_reserved; //currently we do not use this entry
|
||||
PDEV_CONNECT dev_stop;
|
||||
PDEV_CONNECT dev_disconnect;
|
||||
|
||||
}PNP_DISPATCH, *PPNP_DISPATCH;
|
||||
|
||||
#define USB_DRIVER_FLAG_IF_CAPABLE 0x80000000
|
||||
#define USB_DRIVER_FLAG_DEV_CAPABLE 0x40000000
|
||||
|
||||
typedef struct _USB_DRIVER_DESCRIPTION
|
||||
{
|
||||
// Device Info
|
||||
DWORD flags;
|
||||
WORD vendor_id; // USB Vendor ID
|
||||
WORD product_id; // USB Product ID.
|
||||
WORD release_num; // Release Number of Device
|
||||
|
||||
// Interface Info
|
||||
BYTE config_val; // Configuration Value
|
||||
BYTE if_num; // Interface Number
|
||||
BYTE if_class; // Interface Class
|
||||
BYTE if_sub_class; // Interface SubClass
|
||||
BYTE if_protocol; // Interface Protocol
|
||||
|
||||
// Driver Info
|
||||
const char *driver_name; // Driver name for Name Registry
|
||||
BYTE dev_class; // Device Class (from SampleStorageDeviceID.h)
|
||||
BYTE dev_sub_class; // Device Subclass
|
||||
BYTE dev_protocol; // Protocol Info.
|
||||
|
||||
} USB_DRIVER_DESCRIPTION,*PUSB_DRIVER_DESCRIPTION;
|
||||
|
||||
#define RH_DRIVER_IDX 0
|
||||
#define HUB_DRIVER_IDX 1
|
||||
#define UMSS_DRIVER_IDX 2
|
||||
#define COMP_DRIVER_IDX 3
|
||||
#define GEN_DRIVER_IDX 4
|
||||
#define GEN_IF_DRIVER_IDX 5
|
||||
#define MOUSE_DRIVER_IDX 6
|
||||
#define KEYBOARD_DRIVER_IDX 7
|
||||
#define DEVMGR_MAX_DRIVERS 8
|
||||
|
||||
typedef struct _USB_DRIVER
|
||||
{
|
||||
USB_DRIVER_DESCRIPTION driver_desc;
|
||||
PNP_DISPATCH disp_tbl;
|
||||
|
||||
PBYTE driver_ext;
|
||||
LONG driver_ext_size;
|
||||
|
||||
PDRVR_INIT driver_init;
|
||||
PDRVR_INIT driver_destroy;
|
||||
|
||||
} USB_DRIVER, *PUSB_DRIVER;
|
||||
|
||||
extern USB_DRIVER g_driver_list[ DEVMGR_MAX_DRIVERS ];
|
||||
|
||||
#define MAX_HCDS 8
|
||||
#define dev_mgr_from_hcd( hCD ) ( ( hCD )->hcd_get_dev_mgr( hCD ) )
|
||||
#define dev_mgr_from_dev( pdEV ) ( dev_mgr_from_hcd( pdEV->hcd ) )
|
||||
|
||||
typedef struct _USB_DEV_MANAGER
|
||||
{
|
||||
//BYTE dev_addr_map[ MAX_DEVS / 8 ]; //one bit per dev
|
||||
struct _HCD *hcd_array[ MAX_HCDS ];
|
||||
unsigned char hcd_count;
|
||||
|
||||
KSPIN_LOCK dev_list_lock;
|
||||
LIST_HEAD dev_list;
|
||||
|
||||
//PDEVICE_EXTENSION pdev_ext;
|
||||
|
||||
PVOID pthread;
|
||||
BOOLEAN term_flag;
|
||||
KEVENT wake_up_event;
|
||||
|
||||
KSPIN_LOCK event_list_lock;
|
||||
LIST_HEAD event_list;
|
||||
USB_EVENT_POOL event_pool;
|
||||
|
||||
KEVENT drivers_inited;
|
||||
KTIMER dev_mgr_timer;
|
||||
KDPC dev_mgr_timer_dpc;
|
||||
KSPIN_LOCK timer_svc_list_lock;
|
||||
LIST_HEAD timer_svc_list;
|
||||
TIMER_SVC_POOL timer_svc_pool;
|
||||
LONG timer_click;
|
||||
IRP_LIST irp_list;
|
||||
|
||||
PUSB_DRIVER driver_list;
|
||||
LONG hub_count;
|
||||
LIST_HEAD hub_list; //for reference only
|
||||
|
||||
//statistics
|
||||
LONG conn_count; //will also be used to assign device id
|
||||
PDRIVER_OBJECT usb_driver_obj; //this driver object
|
||||
LONG open_count; //increment when IRP_MJ_CREATE arrives
|
||||
//and decrement when IRP_MJ_CLOSE arrives
|
||||
|
||||
} USB_DEV_MANAGER, *PUSB_DEV_MANAGER;
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_post_event(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_EVENT event
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_init(
|
||||
PUSB_DEV dev, //always null. we do not use this param
|
||||
ULONG event,
|
||||
ULONG dev_mgr
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr
|
||||
);
|
||||
|
||||
VOID NTAPI
|
||||
dev_mgr_thread(
|
||||
PVOID dev_mgr
|
||||
);
|
||||
|
||||
VOID NTAPI
|
||||
dev_mgr_timer_dpc_callback(
|
||||
PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_request_timer_svc(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DEV pdev,
|
||||
ULONG context,
|
||||
ULONG due_time,
|
||||
TIMER_SVC_HANDLER handler
|
||||
);
|
||||
|
||||
BYTE
|
||||
dev_mgr_alloc_addr(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PHCD hcd
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_free_addr(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DEV pdev,
|
||||
BYTE addr
|
||||
);
|
||||
|
||||
PUSB_DEV
|
||||
dev_mgr_alloc_device(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PHCD hcd
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_free_device(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DEV pdev
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_disconnect_dev(
|
||||
PUSB_DEV pdev
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_strobe(
|
||||
PUSB_DEV_MANAGER dev_mgr
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
dev_mgr_build_usb_config(
|
||||
PUSB_DEV pdev,
|
||||
PBYTE pbuf,
|
||||
ULONG config_val,
|
||||
LONG config_count
|
||||
);
|
||||
|
||||
UCHAR
|
||||
dev_mgr_register_hcd(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PHCD hcd
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_deregister_hcd(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
UCHAR hcd_id
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
dev_mgr_dispatch(
|
||||
IN PUSB_DEV_MANAGER dev_mgr,
|
||||
IN PIRP irp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
dev_mgr_register_irp(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PIRP pirp,
|
||||
PURB purb
|
||||
);
|
||||
|
||||
PURB
|
||||
dev_mgr_remove_irp(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PIRP pirp
|
||||
);
|
||||
|
||||
LONG
|
||||
dev_mgr_score_driver_for_if(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver,
|
||||
PUSB_INTERFACE_DESC pif_desc
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
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
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
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
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_release_hcd(
|
||||
PUSB_DEV_MANAGER dev_mgr
|
||||
);
|
||||
|
||||
VOID
|
||||
dev_mgr_start_hcd(
|
||||
PUSB_DEV_MANAGER dev_mgr
|
||||
);
|
||||
|
||||
BOOLEAN dev_mgr_start_config_dev(PUSB_DEV pdev);
|
||||
BOOLEAN 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_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);
|
||||
NTSTATUS dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg);
|
||||
BOOLEAN dev_mgr_start_select_driver(PUSB_DEV pdev);
|
||||
VOID NTAPI dev_mgr_cancel_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp);
|
||||
|
||||
#endif
|
|
@ -1,535 +0,0 @@
|
|||
/**
|
||||
* dmgrdisp.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
VOID
|
||||
disp_urb_completion(PURB purb, PVOID context)
|
||||
{
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
ULONG ctrl_code;
|
||||
NTSTATUS status;
|
||||
PDEVEXT_HEADER dev_hdr;
|
||||
|
||||
UNREFERENCED_PARAMETER(context);
|
||||
|
||||
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)
|
||||
{
|
||||
PUSB_CTRL_SETUP_PACKET psetup;
|
||||
PURB purb2;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
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;
|
||||
}
|
||||
|
||||
//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_NON_PENDING_IRQL;
|
||||
|
||||
ASSERT(irp);
|
||||
if (dev_mgr == 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 = 0;
|
||||
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;
|
||||
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:
|
||||
{
|
||||
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;
|
||||
|
||||
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 )
|
||||
//input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the
|
||||
//dev count, output_buffer_length must be no less than sizeof( long ).
|
||||
|
||||
#define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
//input_buffer is a dword value to indicate the count of elements in the array
|
||||
//input_buffer_length is sizeof( long ), output_buffer is to receive a
|
||||
//structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array.
|
||||
|
||||
#define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
//input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is
|
||||
//no less than sizeof( input_buffer ), output_buffer is a buffer to receive the
|
||||
//requested dev's desc, and output_buffer_length specifies the length of the
|
||||
//buffer
|
||||
|
||||
#define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
|
||||
#define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
|
||||
// input_buffer is a URB, and input_buffer_length is equal to or greater than
|
||||
// sizeof( URB ); the output_buffer is a buffer to receive data from or send data
|
||||
// to device. only the following urb fields can be accessed, others must be zeroed.
|
||||
// DEV_HANDLE endp_handle;
|
||||
// UCHAR setup_packet[8]; //for control pipe
|
||||
// the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined
|
||||
// by the current URB, for example, a request string from device will use XXX_RD,
|
||||
// and a write to the bulk endpoint will use XXX_WR
|
||||
|
||||
#define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// input_buffer is a URB, and input_buffer_length is equal to or greater than
|
||||
// sizeof( URB ); the output_buffer is null and no output_buffer_length,
|
||||
// only the following fields in urb can be accessed, others must be zeroed.
|
||||
// DEV_HANDLE endp_handle;
|
||||
// UCHAR setup_packet[8]; //for control pipe
|
||||
*/
|
File diff suppressed because it is too large
Load diff
|
@ -1,808 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2002 by David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __EHCI_H__
|
||||
#define __EHCI_H__
|
||||
|
||||
#define EHCI_QH_SIZE sizeof( EHCI_QH )
|
||||
#define EHCI_ITD_SIZE sizeof( EHCI_ITD )
|
||||
#define EHCI_SITD_SIZE sizeof( EHCI_SITD )
|
||||
#define EHCI_FSTN_SIZE sizeof( EHCI_FSTN )
|
||||
#define EHCI_QTD_SIZE sizeof( EHCI_QTD )
|
||||
|
||||
#define INIT_LIST_FLAG_TYPE 0x0f
|
||||
#define INIT_LIST_FLAG_ITD 0x00
|
||||
#define INIT_LIST_FLAG_QH 0x01
|
||||
#define INIT_LIST_FLAG_SITD 0x02
|
||||
#define INIT_LIST_FLAG_FSTN 0x03
|
||||
#define INIT_LIST_FLAG_QTD 0x04
|
||||
|
||||
#define EHCI_MAX_SIZE_TRANSFER 0x100000 // 1 MB per transfer
|
||||
#define EHCI_MAX_ELEMS_POOL 1024
|
||||
#define EHCI_MAX_LISTS_POOL 0x08
|
||||
#define EHCI_MAX_QHS_LIST 256 // 4 pages
|
||||
#define EHCI_MAX_ITDS_LIST ( PAGE_SIZE / EHCI_ITD_SIZE * 2 ) // 2 pages
|
||||
#define EHCI_MAX_SITDS_LIST ( PAGE_SIZE / EHCI_SITD_SIZE )// 1 page
|
||||
#define EHCI_MAX_FSTNS_LIST ( PAGE_SIZE / EHCI_FSTN_SIZE )// 1 page
|
||||
#define EHCI_MAX_QTDS_LIST 256 // 4 pages
|
||||
|
||||
#define EHCI_PTR_TERM 0x01
|
||||
#define EHCI_NAK_RL_COUNT 0x04
|
||||
|
||||
#define EHCI_QTD_MAX_TRANS_SIZE 20480
|
||||
#define PHYS_PART_TYPE_MASK 0x01f
|
||||
#define PHYS_PART_ADDR_MASK ( ~PHYS_PART_TYPE_MASK )
|
||||
|
||||
typedef struct _EHCI_ELEM_LINKS
|
||||
{
|
||||
LIST_ENTRY elem_link; // link for one urb request
|
||||
LIST_ENTRY sched_link; // to shadow link of schedule
|
||||
struct _EHCI_ELEM_POOL* pool_link;
|
||||
struct _EHCI_ELEM_LIST* list_link; // opaque to client, which list this td belongs to
|
||||
PVOID phys_part; // point to EHCI_XXX, the lower 5 bits is used to indicate the type of the element
|
||||
PURB purb;
|
||||
|
||||
} EHCI_ELEM_LINKS, *PEHCI_ELEM_LINKS;
|
||||
|
||||
typedef struct _INIT_ELEM_LIST_CONTEXT
|
||||
{
|
||||
PADAPTER_OBJECT padapter;
|
||||
struct _EHCI_ELEM_POOL *pool;
|
||||
|
||||
} INIT_ELEM_LIST_CONTEXT, *PINIT_ELEM_LIST_CONTEXT;
|
||||
|
||||
typedef VOID ( *PDESTROY_ELEM_LIST )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef PLIST_ENTRY ( *PGET_LIST_HEAD )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PGET_TOTAL_COUNT )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PGET_ELEM_SIZE )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PGET_LINK_OFFSET )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PADD_REF )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PRELEASE_REF )( struct _EHCI_ELEM_LIST* plist );
|
||||
typedef LONG ( *PGET_REF )( struct _EHCI_ELEM_LIST* plist );
|
||||
|
||||
typedef struct _EHCI_ELEM_LIST
|
||||
{
|
||||
PDESTROY_ELEM_LIST destroy_list;
|
||||
PGET_LIST_HEAD get_list_head;
|
||||
PGET_TOTAL_COUNT get_total_count;
|
||||
PGET_ELEM_SIZE get_elem_size;
|
||||
PGET_LINK_OFFSET get_link_offset;
|
||||
PADD_REF add_ref;
|
||||
PRELEASE_REF release_ref;
|
||||
PGET_REF get_ref;
|
||||
|
||||
// private area
|
||||
LONG flags; // contails element's type info
|
||||
LONG total_count;
|
||||
LONG elem_size;
|
||||
LIST_HEAD free_list; // chains of all the elements
|
||||
struct _EHCI_ELEM_POOL *parent_pool;
|
||||
LONG reference;
|
||||
|
||||
// used to represent the physical memory
|
||||
PPHYSICAL_ADDRESS phys_addrs; // array of non-contigous memory
|
||||
PBYTE *phys_bufs;
|
||||
PEHCI_ELEM_LINKS elem_head_buf;
|
||||
PADAPTER_OBJECT padapter;
|
||||
|
||||
} EHCI_ELEM_LIST, *PEHCI_ELEM_LIST;
|
||||
|
||||
BOOLEAN elem_pool_init_pool( struct _EHCI_ELEM_POOL* pool, LONG flags, PVOID context);
|
||||
VOID elem_pool_destroy_pool ( struct _EHCI_ELEM_POOL* pool );
|
||||
PEHCI_ELEM_LINKS elem_pool_alloc_elem ( struct _EHCI_ELEM_POOL* pool );
|
||||
VOID elem_pool_free_elem ( PEHCI_ELEM_LINKS elem_link );
|
||||
LONG elem_pool_get_total_count ( struct _EHCI_ELEM_POOL* pool );
|
||||
BOOLEAN elem_pool_is_empty ( struct _EHCI_ELEM_POOL* pool );
|
||||
LONG elem_pool_get_free_count ( struct _EHCI_ELEM_POOL* pool );
|
||||
LONG elem_pool_get_link_offset ( struct _EHCI_ELEM_POOL* pool );
|
||||
PEHCI_ELEM_LINKS elem_pool_alloc_elems ( struct _EHCI_ELEM_POOL* pool, LONG count );
|
||||
BOOLEAN elem_pool_free_elems( PEHCI_ELEM_LINKS elem_chains );
|
||||
LONG elem_pool_get_type( struct _EHCI_ELEM_POOL* pool );
|
||||
|
||||
// the following are private functions
|
||||
BOOLEAN elem_pool_expand_pool( struct _EHCI_ELEM_POOL* pool, LONG elem_count );
|
||||
BOOLEAN elem_pool_collect_garbage( struct _EHCI_ELEM_POOL* pool );
|
||||
|
||||
// lock operations
|
||||
BOOLEAN elem_pool_lock( struct _EHCI_ELEM_POOL* pool, BOOLEAN at_dpc );
|
||||
BOOLEAN elem_pool_unlock( struct _EHCI_ELEM_POOL* pool, BOOLEAN at_dpc );
|
||||
|
||||
// helper
|
||||
LONG get_elem_phys_part_size( ULONG type );
|
||||
|
||||
typedef struct _EHCI_ELEM_POOL
|
||||
{
|
||||
LONG flags;
|
||||
LONG free_count; // free count of all the lists currently allocated
|
||||
LONG link_offset; // a cache for elem_list->get_link_offset
|
||||
LONG list_count; // lists currently allocated
|
||||
PEHCI_ELEM_LIST elem_lists[ EHCI_MAX_LISTS_POOL ];
|
||||
|
||||
} EHCI_ELEM_POOL, *PEHCI_ELEM_POOL;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define QTD_NEXT(dma) cpu_to_le32((u32)dma)
|
||||
|
||||
/*
|
||||
* EHCI Specification 0.95 Section 3.5
|
||||
* QTD: describe data transfer components (buffer, direction, ...)
|
||||
* See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
|
||||
*
|
||||
* These are associated only with "QH" (Queue Head) structures,
|
||||
* used with control, bulk, and interrupt transfers.
|
||||
*/
|
||||
#define QTD_TOGGLE (1 << 31) /* data toggle */
|
||||
#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
|
||||
#define QTD_IOC (1 << 15) /* interrupt on complete */
|
||||
#define QTD_CERR(tok) (((tok)>>10) & 0x3)
|
||||
#define QTD_PID(tok) (((tok)>>8) & 0x3)
|
||||
#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */
|
||||
#define QTD_STS_HALT (1 << 6) /* halted on error */
|
||||
#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */
|
||||
#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */
|
||||
#define QTD_STS_XACT (1 << 3) /* device gave illegal response */
|
||||
#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
|
||||
#define QTD_STS_STS (1 << 1) /* split transaction state */
|
||||
#define QTD_STS_PING (1 << 0) /* issue PING? */
|
||||
#define QTD_ANY_ERROR ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_XACT | QTD_STS_MMF | QTD_STS_BABBLE )
|
||||
|
||||
#define QTD_PID_SETUP 0x02
|
||||
#define QTD_PID_IN 0x01
|
||||
#define QTD_PID_OUT 0x00
|
||||
|
||||
#pragma pack( push, usb_align, 1 )
|
||||
|
||||
typedef struct _EHCI_QTD_CONTENT
|
||||
{
|
||||
// DWORD 0
|
||||
ULONG terminal : 1;
|
||||
ULONG reserved : 4;
|
||||
ULONG next_qtd : 27;
|
||||
|
||||
// DWORD 1
|
||||
ULONG alt_terminal : 1;
|
||||
ULONG reserved1 : 4;
|
||||
ULONG alt_qtd : 27;
|
||||
|
||||
// DWORD 2
|
||||
ULONG status : 8;
|
||||
ULONG pid : 2;
|
||||
ULONG err_count : 2;
|
||||
ULONG cur_page : 3;
|
||||
ULONG ioc : 1;
|
||||
ULONG bytes_to_transfer : 15;
|
||||
ULONG data_toggle : 1;
|
||||
|
||||
// DWORD 3
|
||||
ULONG cur_offset : 12;
|
||||
ULONG page0 : 20;
|
||||
|
||||
// DWORD 4-
|
||||
ULONG pages[ 4 ];
|
||||
|
||||
} EHCI_QTD_CONTENT, *PEHCI_QTD_CONTENT;
|
||||
|
||||
typedef struct _EHCI_QTD
|
||||
{
|
||||
/* first part defined by EHCI spec */
|
||||
ULONG hw_next; /* see EHCI 3.5.1 */
|
||||
ULONG hw_alt_next; /* see EHCI 3.5.2 */
|
||||
ULONG hw_token; /* see EHCI 3.5.3 */
|
||||
ULONG hw_buf [5]; /* see EHCI 3.5.4 */
|
||||
|
||||
/* the rest is HCD-private */
|
||||
PEHCI_ELEM_LINKS elem_head_link;
|
||||
ULONG phys_addr; /* qtd address */
|
||||
USHORT bytes_to_transfer; /* the bytes_to_transfer in hw_token will drop to zero when completed*/
|
||||
USHORT reserved2;
|
||||
ULONG reserved[ 5 ];
|
||||
|
||||
} EHCI_QTD, *PEHCI_QTD; //__attribute__ ((aligned (32)));
|
||||
|
||||
#define QTD_MASK cpu_to_le32 (~0x1f) /* mask NakCnt+T in qh->hw_alt_next */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* type tag from {qh,itd,sitd,fstn}->hw_next */
|
||||
#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
|
||||
|
||||
/* values for that type tag */
|
||||
#define Q_TYPE_ITD (0 << 1)
|
||||
#define Q_TYPE_QH (1 << 1)
|
||||
#define Q_TYPE_SITD (2 << 1)
|
||||
#define Q_TYPE_FSTN (3 << 1)
|
||||
|
||||
/* next async queue entry, or pointer to interrupt/periodic QH */
|
||||
#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
|
||||
|
||||
/* for periodic/async schedules and qtd lists, mark end of list */
|
||||
#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* EHCI Specification 0.95 Section 3.6
|
||||
* QH: describes control/bulk/interrupt endpoints
|
||||
* See Fig 3-7 "Queue Head Structure Layout".
|
||||
*
|
||||
* These appear in both the async and (for interrupt) periodic schedules.
|
||||
*/
|
||||
|
||||
#define QH_HEAD 0x00008000
|
||||
#define QH_STATE_LINKED 1 /* HC sees this */
|
||||
#define QH_STATE_UNLINK 2 /* HC may still see this */
|
||||
#define QH_STATE_IDLE 3 /* HC doesn't see this */
|
||||
#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */
|
||||
#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
|
||||
#define NO_FRAME ((unsigned short)~0) /* pick new start */
|
||||
|
||||
typedef struct _EHCI_QH_CONTENT
|
||||
{
|
||||
// DWORD 0
|
||||
ULONG terminal : 1;
|
||||
ULONG ptr_type : 2;
|
||||
ULONG reserved : 2;
|
||||
ULONG next_link : 27;
|
||||
|
||||
// DWORD 1
|
||||
ULONG dev_addr : 7;
|
||||
ULONG inactive : 1;
|
||||
ULONG endp_addr : 4;
|
||||
ULONG endp_spd : 2;
|
||||
ULONG data_toggle : 1;
|
||||
ULONG is_async_head : 1;
|
||||
ULONG max_packet_size : 11;
|
||||
ULONG is_ctrl_endp : 1;
|
||||
ULONG reload_counter : 4;
|
||||
|
||||
// DWORD 2
|
||||
ULONG s_mask : 8;
|
||||
ULONG c_mask : 8;
|
||||
ULONG hub_addr : 7;
|
||||
ULONG port_idx : 7;
|
||||
ULONG mult : 2;
|
||||
|
||||
// DWORD 3
|
||||
ULONG cur_qtd_ptr;
|
||||
|
||||
// overlay
|
||||
EHCI_QTD_CONTENT cur_qtd;
|
||||
|
||||
} EHCI_QH_CONTENT, *PEHCI_QH_CONTENT;
|
||||
|
||||
typedef struct _EHCI_QH
|
||||
{
|
||||
/* first part defined by EHCI spec */
|
||||
ULONG hw_next; /* see EHCI 3.6.1 */
|
||||
ULONG hw_info1; /* see EHCI 3.6.2 */
|
||||
ULONG hw_info2; /* see EHCI 3.6.2 */
|
||||
ULONG hw_current; /* qtd list - see EHCI 3.6.4 */
|
||||
|
||||
/* qtd overlay (hardware parts of a struct ehci_qtd) */
|
||||
ULONG hw_qtd_next;
|
||||
ULONG hw_alt_next;
|
||||
ULONG hw_token;
|
||||
ULONG hw_buf [5];
|
||||
|
||||
/* the rest is HCD-private */
|
||||
PEHCI_ELEM_LINKS elem_head_link;
|
||||
ULONG phys_addr; /* address of qh */
|
||||
ULONG reserved[ 2 ];
|
||||
|
||||
} EHCI_QH, *PEHCI_QH; // __attribute__ ((aligned (32)));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* EHCI Specification 0.95 Section 3.3
|
||||
* Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
|
||||
*
|
||||
* Schedule records for high speed iso xfers
|
||||
*/
|
||||
|
||||
#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
|
||||
#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */
|
||||
#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */
|
||||
#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */
|
||||
#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff)
|
||||
#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */
|
||||
|
||||
#define ITD_STS_ACTIVE 8
|
||||
#define ITD_STS_BUFERR 4
|
||||
#define ITD_STS_BABBLE 2
|
||||
#define ITD_STS_XACTERR 1
|
||||
|
||||
#define ITD_ANY_ERROR ( ITD_STS_BUFERR | ITD_STS_BABBLE | ITD_STS_XACTERR )
|
||||
|
||||
typedef struct _EHCI_ITD_STATUS_SLOT
|
||||
{
|
||||
ULONG offset : 12;
|
||||
ULONG page_sel : 3;
|
||||
ULONG ioc : 1;
|
||||
ULONG trans_length : 12;
|
||||
ULONG status : 4;
|
||||
|
||||
} EHCI_ITD_STATUS_SLOT, *PEHCI_ITD_STATUS_SLOT;
|
||||
|
||||
typedef struct _EHCI_ITD_CONTENT
|
||||
{
|
||||
// DWORD 0;
|
||||
ULONG terminal : 1;
|
||||
ULONG ptr_type : 2;
|
||||
ULONG reserved : 2;
|
||||
ULONG next_link : 27;
|
||||
// DWORD 1-8;
|
||||
EHCI_ITD_STATUS_SLOT status_slot[ 8 ];
|
||||
// DWORD 9;
|
||||
ULONG dev_addr : 7;
|
||||
ULONG reserved1 : 1;
|
||||
ULONG endp_num : 4;
|
||||
ULONG page0 : 20;
|
||||
// DWORD 10;
|
||||
ULONG max_packet_size : 11;
|
||||
ULONG io_dir : 1;
|
||||
ULONG page1 : 20;
|
||||
// DWORD 11;
|
||||
ULONG mult : 2;
|
||||
ULONG reserved2 : 10;
|
||||
ULONG page2 : 20;
|
||||
// DWORD 12-;
|
||||
ULONG pages[ 4 ];
|
||||
|
||||
} EHCI_ITD_CONTENT, *PEHCI_ITD_CONTENT;
|
||||
|
||||
typedef struct _EHCI_ITD {
|
||||
|
||||
/* first part defined by EHCI spec */
|
||||
ULONG hw_next; /* see EHCI 3.3.1 */
|
||||
ULONG hw_transaction [8]; /* see EHCI 3.3.2 */
|
||||
ULONG hw_bufp [7]; /* see EHCI 3.3.3 */
|
||||
|
||||
/* the rest is EHCI-private */
|
||||
PEHCI_ELEM_LINKS elem_head_link;
|
||||
ULONG phys_addr; /* for this itd */
|
||||
ULONG buf_phys_addr; /* buffer address */
|
||||
ULONG reserved[ 5 ];
|
||||
|
||||
} EHCI_ITD, *PEHCI_ITD; // __attribute__ ((aligned (32)));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* EHCI Specification 0.95 Section 3.4
|
||||
* siTD, aka split-transaction isochronous Transfer Descriptor
|
||||
* ... describe low/full speed iso xfers through TT in hubs
|
||||
* see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
|
||||
*/
|
||||
#define SITD_STS_ACTIVE 0x80
|
||||
#define SITD_STS_ERR 0x40 // error from device
|
||||
#define SITD_STS_DBE 0x20 // data buffer error
|
||||
#define SITD_STS_BABBLE 0x10 // data more than expected
|
||||
#define SITD_STS_XACTERR 0x08 // general error on hc
|
||||
#define SITD_STS_MISSFRM 0x04 // missd micro frames
|
||||
#define SITD_STS_SC 0x02 // state is whether start-split( 0 ) or complete-split( 1 )
|
||||
#define SITD_STS_RESERVED 0x01
|
||||
#define SITD_ANY_ERROR ( SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE | SITD_STS_XACTERR | SITD_STS_MISSFRM )
|
||||
|
||||
typedef struct _EHCI_SITD_CONTENT
|
||||
{
|
||||
// DWORD 0;
|
||||
ULONG terminal : 1;
|
||||
ULONG ptr_type : 2;
|
||||
ULONG reserved : 2;
|
||||
ULONG next_link : 27;
|
||||
// DWORD 1;
|
||||
ULONG dev_addr : 7;
|
||||
ULONG reserved1 : 1;
|
||||
ULONG endp_num : 4;
|
||||
ULONG reserved2 : 4;
|
||||
ULONG hub_addr : 7;
|
||||
ULONG reserved3 : 1;
|
||||
ULONG port_idx : 7;
|
||||
ULONG io_dir : 1;
|
||||
// DWORD 2;
|
||||
ULONG s_mask : 8;
|
||||
ULONG c_mask : 8;
|
||||
ULONG reserved4 : 16;
|
||||
// DWORD 3:
|
||||
ULONG status : 8;
|
||||
ULONG c_prog_mask : 8;
|
||||
ULONG bytes_to_transfer : 10;
|
||||
ULONG reserved5 : 4;
|
||||
ULONG page_sel : 1;
|
||||
ULONG ioc : 1;
|
||||
// DWORD 4;
|
||||
ULONG cur_offset : 12;
|
||||
ULONG page0 : 20;
|
||||
// DWORD 5;
|
||||
ULONG trans_count : 3;
|
||||
ULONG trans_pos : 2;
|
||||
ULONG reserved6 : 7;
|
||||
ULONG page1 : 20;
|
||||
// DWORD 6;
|
||||
ULONG back_terminal : 1;
|
||||
ULONG reserved7 : 4;
|
||||
ULONG back_ptr : 27;
|
||||
|
||||
} EHCI_SITD_CONTENT, *PEHCI_SITD_CONTENT;
|
||||
|
||||
typedef struct _EHCI_SITD
|
||||
{
|
||||
/* first part defined by EHCI spec */
|
||||
ULONG hw_next;
|
||||
/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
|
||||
|
||||
ULONG hw_fullspeed_ep; /* see EHCI table 3-9 */
|
||||
ULONG hw_uframe; /* see EHCI table 3-10 */
|
||||
ULONG hw_tx_results1; /* see EHCI table 3-11 */
|
||||
ULONG hw_tx_results2; /* see EHCI table 3-12 */
|
||||
ULONG hw_tx_results3; /* see EHCI table 3-12 */
|
||||
ULONG hw_backpointer; /* see EHCI table 3-13 */
|
||||
|
||||
/* the rest is HCD-private */
|
||||
PEHCI_ELEM_LINKS elem_head_link;
|
||||
ULONG phys_addr;
|
||||
ULONG buf_phys_addr; /* buffer address */
|
||||
|
||||
USHORT usecs; /* start bandwidth */
|
||||
USHORT c_usecs; /* completion bandwidth */
|
||||
ULONG reserved[ 5 ];
|
||||
|
||||
} EHCI_SITD, *PEHCI_SITD; // __attribute__ ((aligned (32)));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* EHCI Specification 0.96 Section 3.7
|
||||
* Periodic Frame Span Traversal Node (FSTN)
|
||||
*
|
||||
* Manages split interrupt transactions (using TT) that span frame boundaries
|
||||
* into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN
|
||||
* makes the HC jump (back) to a QH to scan for fs/ls QH completions until
|
||||
* it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
|
||||
*/
|
||||
typedef struct _EHCI_FSTN
|
||||
{
|
||||
ULONG hw_next; /* any periodic q entry */
|
||||
ULONG hw_prev; /* qh or EHCI_LIST_END */
|
||||
|
||||
/* the rest is HCD-private */
|
||||
PEHCI_ELEM_LINKS elem_head_link;
|
||||
ULONG phys_addr;
|
||||
ULONG reserved[ 4 ];
|
||||
|
||||
} EHCI_FSTN, *PEHCI_FSTN; // __attribute__ ((aligned (32)));
|
||||
|
||||
|
||||
/* NOTE: urb->transfer_flags expected to not use this bit !!! */
|
||||
#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
|
||||
|
||||
/* Section 2.2 Host Controller Capability Registers */
|
||||
#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */
|
||||
#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */
|
||||
#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
|
||||
#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */
|
||||
#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */
|
||||
#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */
|
||||
#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
|
||||
|
||||
#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */
|
||||
#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */
|
||||
#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */
|
||||
#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */
|
||||
#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
|
||||
#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */
|
||||
|
||||
/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
|
||||
#define CMD_PARK (1<<11) /* enable "park" on async qh */
|
||||
#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */
|
||||
#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */
|
||||
#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */
|
||||
#define CMD_ASE (1<<5) /* async schedule enable */
|
||||
#define CMD_PSE (1<<4) /* periodic schedule enable */
|
||||
/* 3:2 is periodic frame list size */
|
||||
#define CMD_RESET (1<<1) /* reset HC not bus */
|
||||
#define CMD_RUN (1<<0) /* start/stop HC */
|
||||
|
||||
/* these STS_* flags are also intr_enable bits (USBINTR) */
|
||||
#define STS_IAA (1<<5) /* Interrupted on async advance */
|
||||
#define STS_FATAL (1<<4) /* such as some PCI access errors */
|
||||
#define STS_FLR (1<<3) /* frame list rolled over */
|
||||
#define STS_PCD (1<<2) /* port change detect */
|
||||
#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
|
||||
#define STS_INT (1<<0) /* "normal" completion (short, ...) */
|
||||
|
||||
#define STS_ASS (1<<15) /* Async Schedule Status */
|
||||
#define STS_PSS (1<<14) /* Periodic Schedule Status */
|
||||
#define STS_RECL (1<<13) /* Reclamation */
|
||||
#define STS_HALT (1<<12) /* Not running (any reason) */
|
||||
|
||||
/* 31:23 reserved */
|
||||
#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */
|
||||
#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
|
||||
#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
|
||||
/* 19:16 for port testing */
|
||||
/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */
|
||||
#define PORT_OWNER (1<<13) /* true: companion hc owns this port */
|
||||
#define PORT_POWER (1<<12) /* true: has power (see PPC) */
|
||||
#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */
|
||||
/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
|
||||
/* 9 reserved */
|
||||
#define PORT_PR (1<<8) /* reset port */
|
||||
#define PORT_SUSP (1<<7) /* suspend port */
|
||||
#define PORT_RESUME (1<<6) /* resume it */
|
||||
#define PORT_OCC (1<<5) /* over current change */
|
||||
#define PORT_OC (1<<4) /* over current active */
|
||||
#define PORT_PEC (1<<3) /* port enable change */
|
||||
#define PORT_PE (1<<2) /* port enable */
|
||||
#define PORT_CSC (1<<1) /* connect status change */
|
||||
#define PORT_CCS (1<<0) /* device connected */
|
||||
|
||||
#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
|
||||
|
||||
typedef struct _EHCI_HCS_CONTENT
|
||||
{
|
||||
ULONG port_count : 4;
|
||||
ULONG port_power_control : 1;
|
||||
ULONG reserved : 2;
|
||||
ULONG port_rout_rules : 1;
|
||||
ULONG port_per_chc : 4;
|
||||
ULONG chc_count : 4;
|
||||
ULONG port_indicator : 1;
|
||||
ULONG reserved2 : 3;
|
||||
ULONG dbg_port_num : 4;
|
||||
ULONG reserved3 : 8;
|
||||
|
||||
} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT;
|
||||
|
||||
typedef struct _EHCI_HCC_CONTENT
|
||||
{
|
||||
ULONG cur_addr_bits : 1; /* 0: 32 bit addressing 1: 64 bit addressing */
|
||||
ULONG var_frame_list : 1; /* 0: 1024 frames, 1: support other number of frames */
|
||||
ULONG park_mode : 1;
|
||||
ULONG reserved : 1;
|
||||
ULONG iso_sched_threshold : 4;
|
||||
ULONG eecp_capable : 8;
|
||||
ULONG reserved2 : 16;
|
||||
|
||||
} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
|
||||
|
||||
typedef struct _EHCI_CAPS {
|
||||
UCHAR length; /* CAPLENGTH - size of this struct */
|
||||
UCHAR reserved; /* offset 0x1 */
|
||||
USHORT hci_version; /* HCIVERSION - offset 0x2 */
|
||||
ULONG hcs_params; /* HCSPARAMS - offset 0x4 */
|
||||
|
||||
ULONG hcc_params; /* HCCPARAMS - offset 0x8 */
|
||||
UCHAR portroute [8]; /* nibbles for routing - offset 0xC */
|
||||
|
||||
} EHCI_CAPS, *PEHCI_CAPS;
|
||||
|
||||
/* Section 2.3 Host Controller Operational Registers */
|
||||
|
||||
#define EHCI_USBCMD 0x00
|
||||
#define EHCI_USBSTS 0x04
|
||||
#define EHCI_USBINTR 0x08
|
||||
#define EHCI_FRINDEX 0x0c
|
||||
#define EHCI_CTRLDSSEGMENT 0x10
|
||||
#define EHCI_PERIODICLISTBASE 0x14
|
||||
#define EHCI_ASYNCLISTBASE 0x18
|
||||
#define EHCI_CONFIGFLAG 0x40
|
||||
#define EHCI_PORTSC 0x44
|
||||
|
||||
#define EHCI_USBINTR_INTE 0x01
|
||||
#define EHCI_USBINTR_ERR 0x02
|
||||
#define EHCI_USBINTR_PC 0x04
|
||||
#define EHCI_USBINTR_FLROVR 0x08
|
||||
#define EHCI_USBINTR_HSERR 0x10
|
||||
#define EHCI_USBINTR_ASYNC 0x20
|
||||
|
||||
typedef struct _EHCI_USBCMD_CONTENT
|
||||
{
|
||||
ULONG run_stop : 1;
|
||||
ULONG hcreset : 1;
|
||||
ULONG frame_list_size : 2;
|
||||
ULONG periodic_enable : 1;
|
||||
ULONG async_enable : 1;
|
||||
ULONG door_bell : 1;
|
||||
ULONG light_reset : 1;
|
||||
ULONG async_park_count : 2;
|
||||
ULONG reserved : 1;
|
||||
ULONG async_park_enable : 1;
|
||||
ULONG reserved1 : 4;
|
||||
ULONG int_threshold : 8;
|
||||
ULONG reserved2 : 8;
|
||||
|
||||
} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
|
||||
|
||||
typedef struct _EHCI_USBSTS_CONTENT
|
||||
{
|
||||
ULONG ioc : 1;
|
||||
ULONG trasac_error : 1;
|
||||
ULONG port_change : 1;
|
||||
ULONG fl_rollover : 1;
|
||||
ULONG host_system_error : 1;
|
||||
ULONG async_advance : 1;
|
||||
ULONG reserved : 6;
|
||||
ULONG hc_halted : 1;
|
||||
ULONG reclaimation : 1;
|
||||
ULONG periodic_status : 1;
|
||||
ULONG async_status : 1;
|
||||
ULONG reserved1 : 16;
|
||||
|
||||
} EHCI_USBSTS_CONTENT, *PEHCI_USBSTS_CONTENT;
|
||||
|
||||
typedef struct _EHCI_RHPORTSC_CONTENT
|
||||
{
|
||||
ULONG cur_connect : 1;
|
||||
ULONG cur_connect_change : 1;
|
||||
ULONG port_enable : 1;
|
||||
ULONG port_enable_change : 1;
|
||||
ULONG over_current : 1;
|
||||
ULONG over_current_change : 1;
|
||||
ULONG force_port_resume : 1;
|
||||
ULONG suspend : 1;
|
||||
ULONG port_reset : 1;
|
||||
ULONG reserved : 1;
|
||||
ULONG line_status : 2;
|
||||
ULONG port_power : 1;
|
||||
ULONG port_owner : 1;
|
||||
ULONG port_indicator : 2;
|
||||
ULONG port_test : 4;
|
||||
ULONG we_connect : 1;
|
||||
ULONG we_disconnect : 1;
|
||||
ULONG we_over_current : 1;
|
||||
ULONG reserved1 : 9;
|
||||
|
||||
} EHCI_RHPORTSC_CONTENT, *PEHCI_RHPORTSC_CONTENT;
|
||||
|
||||
typedef struct _EHCI_REGS {
|
||||
|
||||
ULONG command;
|
||||
ULONG status;
|
||||
ULONG intr_enable;
|
||||
ULONG frame_index; /* current microframe number */
|
||||
ULONG segment; /* address bits 63:32 if needed */
|
||||
ULONG frame_list; /* points to periodic list */
|
||||
ULONG async_next; /* address of next async queue head */
|
||||
ULONG reserved [9];
|
||||
ULONG configured_flag;
|
||||
ULONG port_status [0]; /* up to N_PORTS */
|
||||
|
||||
} EHCI_REGS, *PEHCI_REGS;
|
||||
|
||||
#pragma pack( pop, usb_align )
|
||||
|
||||
/* ehci_hcd->lock guards shared data against other CPUs:
|
||||
* ehci_hcd: async, reclaim, periodic (and shadow), ...
|
||||
* hcd_dev: ep[]
|
||||
* ehci_qh: qh_next, qtd_list
|
||||
* ehci_qtd: qtd_list
|
||||
*
|
||||
* Also, hold this lock when talking to HC registers or
|
||||
* when updating hw_* fields in shared qh/qtd/... structures.
|
||||
*/
|
||||
|
||||
#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */
|
||||
|
||||
#define EHCI_DEVICE_NAME "\\Device\\EHCI"
|
||||
|
||||
#define EHCI_DOS_DEVICE_NAME "\\DosDevices\\EHCI"
|
||||
|
||||
#define EHCI_ITD_POOL_IDX INIT_LIST_FLAG_ITD
|
||||
#define EHCI_QH_POOL_IDX INIT_LIST_FLAG_QH
|
||||
#define EHCI_SITD_POOL_IDX INIT_LIST_FLAG_SITD
|
||||
#define EHCI_FSTN_POOL_IDX INIT_LIST_FLAG_FSTN
|
||||
#define EHCI_QTD_POOL_IDX INIT_LIST_FLAG_QTD
|
||||
|
||||
#define EHCI_DEFAULT_FRAMES UHCI_MAX_FRAMES
|
||||
#define EHCI_MAX_SYNC_BUS_TIME 50000 // stands for 100000 ns, only to get wrapped within one word
|
||||
|
||||
#define EHCI_SCHED_INT8_INDEX 0
|
||||
#define EHCI_SCHED_INT4_INDEX 1
|
||||
#define EHCI_SCHED_INT2_INDEX 2
|
||||
#define EHCI_SCHED_FSTN_INDEX 3
|
||||
#define EHCI_SCHED_INT1_INDEX 4
|
||||
|
||||
#define qtd_pool ( &ehci->elem_pools[ EHCI_QTD_POOL_IDX ] )
|
||||
#define qh_pool ( &ehci->elem_pools[ EHCI_QH_POOL_IDX ] )
|
||||
#define fstn_pool ( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] )
|
||||
#define itd_pool ( &ehci->elem_pools[ EHCI_ITD_POOL_IDX ] )
|
||||
#define sitd_pool ( &ehci->elem_pools[ EHCI_SITD_POOL_IDX ] )
|
||||
|
||||
|
||||
typedef struct _EHCI_DEV
|
||||
{
|
||||
HCD hcd_interf;
|
||||
|
||||
EHCI_CAPS ehci_caps;
|
||||
|
||||
PHYSICAL_ADDRESS ehci_reg_base; // io space
|
||||
BOOLEAN port_mapped;
|
||||
PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base
|
||||
|
||||
ULONG frame_count;
|
||||
PHYSICAL_ADDRESS frame_list_phys_addr;
|
||||
|
||||
KSPIN_LOCK frame_list_lock; // run at DIRQL
|
||||
PULONG frame_list; // periodic schedule
|
||||
|
||||
PFRAME_LIST_CPU_ENTRY frame_list_cpu; // periodic schedule shadow
|
||||
|
||||
LIST_HEAD urb_list; // active urb-list
|
||||
|
||||
LIST_HEAD async_list_cpu;
|
||||
LIST_HEAD periodic_list_cpu[ 8 ]; // each slot for one periodic
|
||||
PEHCI_QH skel_async_qh;
|
||||
|
||||
|
||||
//
|
||||
// pools for device specific data
|
||||
//
|
||||
EHCI_ELEM_POOL elem_pools[ 5 ];
|
||||
|
||||
//
|
||||
//for iso and int bandwidth claim, bandwidth schedule
|
||||
//
|
||||
KSPIN_LOCK pending_endp_list_lock; //lock to access the following two
|
||||
LIST_HEAD pending_endp_list;
|
||||
UHCI_PENDING_ENDP_POOL pending_endp_pool;
|
||||
PUSHORT frame_bw; //unit uFrame
|
||||
USHORT min_bw; //the bottle-neck of the bandwidths across frame-list
|
||||
|
||||
KTIMER reset_timer; //used to reset the host controller
|
||||
struct _EHCI_DEVICE_EXTENSION *pdev_ext;
|
||||
PUSB_DEV root_hub; //root hub
|
||||
|
||||
} EHCI_DEV, *PEHCI_DEV;
|
||||
|
||||
typedef UHCI_PORT EHCI_MEMORY;
|
||||
|
||||
typedef struct _EHCI_DEVICE_EXTENSION
|
||||
{
|
||||
//struct _USB_DEV_MANAGER *pdev_mgr;
|
||||
DEVEXT_HEADER dev_ext_hdr;
|
||||
PDEVICE_OBJECT pdev_obj;
|
||||
PDRIVER_OBJECT pdrvr_obj;
|
||||
PEHCI_DEV ehci;
|
||||
|
||||
//device resources
|
||||
PADAPTER_OBJECT padapter;
|
||||
ULONG map_regs;
|
||||
PCM_RESOURCE_LIST res_list;
|
||||
ULONG pci_addr; // bus number | slot number | funciton number
|
||||
UHCI_INTERRUPT res_interrupt;
|
||||
union
|
||||
{
|
||||
UHCI_PORT res_port;
|
||||
EHCI_MEMORY res_memory;
|
||||
};
|
||||
|
||||
PKINTERRUPT ehci_int;
|
||||
KDPC ehci_dpc;
|
||||
|
||||
} EHCI_DEVICE_EXTENSION, *PEHCI_DEVICE_EXTENSION;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#endif /* __EHCI_H__ */
|
|
@ -1,643 +0,0 @@
|
|||
/**
|
||||
* etd.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <usbdriver.h>
|
||||
#include "ehci.h"
|
||||
|
||||
#define init_elem( ptr, type, ehci_elem_type ) \
|
||||
{\
|
||||
PEHCI_ELEM_LINKS tmp;\
|
||||
ptr = ( type* )( plist->phys_bufs[ i ] + sizeof( type ) * j );\
|
||||
ptr->hw_next = ehci_elem_type << 1;\
|
||||
if( ehci_elem_type == INIT_LIST_FLAG_QTD )\
|
||||
ptr->hw_next = 0;\
|
||||
tmp = ptr->elem_head_link = &plist->elem_head_buf[ i * elms_per_page + j ];\
|
||||
InitializeListHead( &tmp->elem_link );\
|
||||
InitializeListHead( &tmp->sched_link );\
|
||||
InsertTailList( &plist->free_list, &tmp->elem_link );\
|
||||
tmp->list_link = plist;\
|
||||
tmp->pool_link = pinit_ctx->pool;\
|
||||
tmp->phys_part = ( PVOID )( ( ULONG )ptr | ( ehci_elem_type << 1 ) );\
|
||||
if( ehci_elem_type != INIT_LIST_FLAG_QTD )\
|
||||
ptr->phys_addr = ( plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ) | ( ehci_elem_type << 1 );\
|
||||
else \
|
||||
ptr->phys_addr = plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ;\
|
||||
}
|
||||
|
||||
// get the actual max list count of the pool, two limit, max_elem_pool and max_lists_pool
|
||||
#define get_max_lists_count( pOOL, max_liSTS ) \
|
||||
{\
|
||||
LONG ii1=0;\
|
||||
switch( elem_pool_get_type( pOOL ) )\
|
||||
{\
|
||||
case INIT_LIST_FLAG_QTD:\
|
||||
ii1 = EHCI_MAX_QTDS_LIST;\
|
||||
break;\
|
||||
case INIT_LIST_FLAG_FSTN:\
|
||||
ii1 = EHCI_MAX_QHS_LIST;\
|
||||
break;\
|
||||
case INIT_LIST_FLAG_SITD:\
|
||||
ii1 = EHCI_MAX_ITDS_LIST;\
|
||||
break;\
|
||||
case INIT_LIST_FLAG_QH: \
|
||||
ii1 = EHCI_MAX_SITDS_LIST;\
|
||||
break;\
|
||||
case INIT_LIST_FLAG_ITD: \
|
||||
ii1 = EHCI_MAX_FSTNS_LIST;\
|
||||
break;\
|
||||
}\
|
||||
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);
|
||||
|
||||
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_elem_size(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_release_ref(PEHCI_ELEM_LIST plist);
|
||||
|
||||
LONG elem_list_get_ref(PEHCI_ELEM_LIST plist);
|
||||
|
||||
BOOLEAN
|
||||
elem_pool_lock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pool);
|
||||
UNREFERENCED_PARAMETER(at_dpc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
elem_pool_unlock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pool);
|
||||
UNREFERENCED_PARAMETER(at_dpc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
|
||||
UNREFERENCED_PARAMETER(count);
|
||||
|
||||
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);
|
||||
|
||||
RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
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));
|
||||
}
|
||||
|
||||
PLIST_ENTRY
|
||||
elem_list_get_list_head(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
if (plist == NULL)
|
||||
return NULL;
|
||||
return &plist->free_list;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_get_total_count(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
if (plist == NULL)
|
||||
return 0;
|
||||
return plist->total_count;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_get_elem_size(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
if (plist == NULL)
|
||||
return 0;
|
||||
return plist->elem_size;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_get_link_offset(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
if (plist == NULL)
|
||||
return 0;
|
||||
|
||||
return get_elem_phys_part_size(plist->flags & 0xf);
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_add_ref(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
plist->reference++;
|
||||
return plist->reference;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_release_ref(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
plist->reference--;
|
||||
return plist->reference;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_list_get_ref(PEHCI_ELEM_LIST plist)
|
||||
{
|
||||
return plist->reference;
|
||||
}
|
||||
|
||||
//
|
||||
// pool methods
|
||||
//
|
||||
|
||||
BOOLEAN
|
||||
elem_pool_init_pool(PEHCI_ELEM_POOL pool, LONG flags, PVOID context)
|
||||
{
|
||||
INIT_ELEM_LIST_CONTEXT init_ctx;
|
||||
|
||||
if (pool == NULL || context == NULL)
|
||||
return FALSE;
|
||||
|
||||
RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL));
|
||||
|
||||
init_ctx.pool = pool;
|
||||
init_ctx.padapter = context;
|
||||
|
||||
pool->elem_lists[0] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST));
|
||||
|
||||
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;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_pool_get_link_offset(PEHCI_ELEM_POOL elem_pool)
|
||||
{
|
||||
return elem_pool->link_offset;
|
||||
}
|
||||
|
||||
LONG
|
||||
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;
|
||||
}
|
||||
|
||||
VOID
|
||||
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;
|
||||
}
|
||||
|
||||
PEHCI_ELEM_LINKS
|
||||
elem_pool_alloc_elem(PEHCI_ELEM_POOL pool)
|
||||
{
|
||||
LONG i;
|
||||
PEHCI_ELEM_LIST pel = NULL;
|
||||
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)
|
||||
{
|
||||
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, &elem_link->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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
elem_pool_is_empty(PEHCI_ELEM_POOL pool)
|
||||
{
|
||||
PEHCI_ELEM_LIST pel;
|
||||
|
||||
if (pool == NULL)
|
||||
return TRUE;
|
||||
pel = pool->elem_lists[0];
|
||||
return (BOOLEAN) (pool->list_count == 1 && pool->free_count == pel->get_total_count(pel));
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_pool_get_free_count(PEHCI_ELEM_POOL pool)
|
||||
{
|
||||
if (pool == NULL)
|
||||
return 0;
|
||||
return pool->free_count;
|
||||
}
|
||||
|
||||
PEHCI_ELEM_LINKS
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
LONG
|
||||
elem_pool_get_type(PEHCI_ELEM_POOL pool)
|
||||
{
|
||||
if (pool == NULL)
|
||||
return -1;
|
||||
return (pool->flags & 0xf);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
|
@ -1,148 +0,0 @@
|
|||
#ifndef __EVENTS_H
|
||||
#define __EVENTS_H
|
||||
|
||||
//event definitions
|
||||
|
||||
#define MAX_EVENTS 128
|
||||
#define MAX_TIMER_SVCS 24
|
||||
|
||||
#define USB_EVENT_FLAG_ACTIVE 0x80000000
|
||||
|
||||
#define USB_EVENT_FLAG_QUE_TYPE 0x000000FF
|
||||
#define USB_EVENT_FLAG_QUE_RESET 0x01
|
||||
#define USB_EVENT_FLAG_NOQUE 0x00
|
||||
|
||||
#define USB_EVENT_DEFAULT 0x00 //as a placeholder
|
||||
#define USB_EVENT_INIT_DEV_MGR 0x01
|
||||
#define USB_EVENT_HUB_POLL 0x02
|
||||
#define USB_EVENT_WAIT_RESET_PORT 0x03
|
||||
#define USB_EVENT_CLEAR_TT_BUFFER 0x04
|
||||
|
||||
typedef VOID ( *PROCESS_QUEUE )(
|
||||
PLIST_HEAD event_list,
|
||||
struct _USB_EVENT_POOL *event_pool,
|
||||
struct _USB_EVENT *usb_event,
|
||||
struct _USB_EVENT *out_event
|
||||
);
|
||||
|
||||
typedef VOID ( *PROCESS_EVENT )(
|
||||
PUSB_DEV dev,
|
||||
ULONG event,
|
||||
ULONG context,
|
||||
ULONG param
|
||||
);
|
||||
|
||||
typedef struct _USB_EVENT
|
||||
{
|
||||
LIST_ENTRY event_link;
|
||||
ULONG flags;
|
||||
ULONG event;
|
||||
PUSB_DEV pdev;
|
||||
ULONG context;
|
||||
ULONG param;
|
||||
struct _USB_EVENT *pnext; //vertical queue for serialized operation
|
||||
PROCESS_EVENT process_event;
|
||||
PROCESS_QUEUE process_queue;
|
||||
|
||||
} USB_EVENT, *PUSB_EVENT;
|
||||
|
||||
typedef struct _USB_EVENT_POOL
|
||||
{
|
||||
PUSB_EVENT event_array;
|
||||
LIST_HEAD free_que;
|
||||
LONG free_count;
|
||||
LONG total_count;
|
||||
KSPIN_LOCK pool_lock;
|
||||
|
||||
} USB_EVENT_POOL, *PUSB_EVENT_POOL;
|
||||
|
||||
BOOLEAN
|
||||
init_event_pool(
|
||||
PUSB_EVENT_POOL pool
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
free_event(
|
||||
PUSB_EVENT_POOL pool,
|
||||
PUSB_EVENT pevent
|
||||
); //add qhs till pnext == NULL
|
||||
|
||||
PUSB_EVENT
|
||||
alloc_event(
|
||||
PUSB_EVENT_POOL pool,
|
||||
LONG count
|
||||
); //null if failed
|
||||
|
||||
BOOLEAN
|
||||
destroy_event_pool(
|
||||
PUSB_EVENT_POOL pool
|
||||
);
|
||||
|
||||
VOID
|
||||
lock_event_pool(
|
||||
PUSB_EVENT_POOL pool
|
||||
);
|
||||
|
||||
VOID
|
||||
unlock_event_pool(
|
||||
PUSB_EVENT_POOL pool
|
||||
);
|
||||
|
||||
#define DEV_MGR_TIMER_INTERVAL_NS ( 10 * 1000 * 10 ) //unit 100 ns
|
||||
#define DEV_MGR_TIMER_INTERVAL_MS 10
|
||||
|
||||
typedef VOID ( *TIMER_SVC_HANDLER )(PUSB_DEV dev, PVOID context);
|
||||
|
||||
typedef struct _TIMER_SVC
|
||||
{
|
||||
LIST_ENTRY timer_svc_link;
|
||||
ULONG counter;
|
||||
ULONG threshold;
|
||||
ULONG context;
|
||||
PUSB_DEV pdev;
|
||||
TIMER_SVC_HANDLER func;
|
||||
|
||||
} TIMER_SVC, *PTIMER_SVC;
|
||||
|
||||
typedef struct _TIMER_SVC_POOL
|
||||
{
|
||||
PTIMER_SVC timer_svc_array;
|
||||
LIST_HEAD free_que;
|
||||
LONG free_count;
|
||||
LONG total_count;
|
||||
KSPIN_LOCK pool_lock;
|
||||
|
||||
} TIMER_SVC_POOL, *PTIMER_SVC_POOL;
|
||||
|
||||
BOOLEAN
|
||||
init_timer_svc_pool(
|
||||
PTIMER_SVC_POOL pool
|
||||
);
|
||||
BOOLEAN
|
||||
free_timer_svc(
|
||||
PTIMER_SVC_POOL pool,
|
||||
PTIMER_SVC ptimer
|
||||
);
|
||||
|
||||
PTIMER_SVC
|
||||
alloc_timer_svc(
|
||||
PTIMER_SVC_POOL pool,
|
||||
LONG count
|
||||
); //null if failed
|
||||
|
||||
BOOLEAN
|
||||
destroy_timer_svc_pool(
|
||||
PTIMER_SVC_POOL pool
|
||||
);
|
||||
|
||||
VOID
|
||||
lock_timer_svc_pool(
|
||||
PTIMER_SVC_POOL pool
|
||||
);
|
||||
|
||||
VOID
|
||||
unlock_timer_svc_pool(
|
||||
PTIMER_SVC_POOL pool
|
||||
);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,62 +0,0 @@
|
|||
#ifndef __GENDRV_H__
|
||||
#define __GENDRV_H__
|
||||
|
||||
#define GENDRV_MAX_EXT_DRVR 2
|
||||
#define GENDRV_DRVR_FLAG_IF_DRVR 0x01
|
||||
|
||||
#define GENDRV_MSG_ADDDEVICE 0x01
|
||||
#define GENDRV_MSG_STOPDEVICE 0x02
|
||||
#define GENDRV_MSG_DISCDEVICE 0x03
|
||||
|
||||
typedef struct _GENDRV_EXT_DRVR_ENTRY
|
||||
{
|
||||
LIST_ENTRY drvr_link; // used for dynamic load/unload driver
|
||||
ULONG drvr_key; // used to find the driver loaded, the key
|
||||
// is ( vendor_id << 16 )|( product_id ) or
|
||||
// ( class_id << 16 ) | ( sub_class_id << 8 ) | ( protocol_id ))
|
||||
PDRIVER_OBJECT pext_drvr; // the external driver count
|
||||
ULONG ref_count; // number of devices attached
|
||||
LIST_HEAD dev_list; // link the devices by deviceExtension->dev_obj_link
|
||||
|
||||
} GENDRV_EXT_DRVR_ENTRY, *PGENDRV_EXT_DRVR_ENTRY;
|
||||
|
||||
typedef struct _GENDRV_DRVR_EXTENSION
|
||||
{
|
||||
FAST_MUTEX drvr_ext_mutex;
|
||||
ULONG ext_drvr_count; // loaded driver count
|
||||
LIST_HEAD ext_drvr_list;
|
||||
GENDRV_EXT_DRVR_ENTRY ext_drvr_array[ GENDRV_MAX_EXT_DRVR ];
|
||||
|
||||
}GENDRV_DRVR_EXTENSION, *PGENDRV_DRVR_EXTENSION;
|
||||
|
||||
typedef struct _GENDRV_IF_CTX
|
||||
{
|
||||
UCHAR if_idx; // valid for if device
|
||||
PUSB_INTERFACE_DESC pif_desc;
|
||||
|
||||
} GENDRV_IF_CTX, *PGENDRV_IF_IDX;
|
||||
|
||||
typedef struct _GENDRV_DEVICE_EXTENSION
|
||||
{
|
||||
//this structure is the device extension for dev_obj
|
||||
//created for the device.
|
||||
DEVEXT_HEADER dev_ext_hdr;
|
||||
ULONG flags;
|
||||
LIST_ENTRY dev_obj_link; // this link is used by the driver object to track the existing dev_objs
|
||||
PGENDRV_EXT_DRVR_ENTRY ext_drvr_entry;
|
||||
|
||||
PDEVICE_OBJECT pdo; // Our device object
|
||||
DEV_HANDLE dev_handle; // handle to the usb_dev under
|
||||
PUCHAR desc_buf;
|
||||
UCHAR dev_id; // used to build symbolic link
|
||||
GENDRV_IF_CTX if_ctx;
|
||||
|
||||
KEVENT sync_event;
|
||||
KSPIN_LOCK dev_lock;
|
||||
|
||||
PUSB_DRIVER pdriver;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
|
||||
} GENDRV_DEVICE_EXTENSION, *PGENDRV_DEVICE_EXTENSION;
|
||||
|
||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||
#ifndef __HCD_H__
|
||||
#define __HCD_H__
|
||||
|
||||
#define HCD_TYPE_MASK 0xf0
|
||||
#define HCD_TYPE_UHCI 0x10
|
||||
#define HCD_TYPE_OHCI 0x20
|
||||
#define HCD_TYPE_EHCI 0x30
|
||||
|
||||
#define hcd_type( hCD ) ( ( ( hCD )->flags ) & HCD_TYPE_MASK )
|
||||
#define usb2( hCD ) ( hcd_type( hCD ) == HCD_TYPE_EHCI )
|
||||
|
||||
#define HCD_ID_MASK 0xf
|
||||
|
||||
#define HCD_DISP_READ_PORT_COUNT 1 // the param is a pointer to UCHAR
|
||||
#define HCD_DISP_READ_RH_DEV_CHANGE 2 // the param is a buffer to hold conn change on all the port
|
||||
// must have the rh dev_lock acquired
|
||||
|
||||
struct _HCD;
|
||||
struct _USB_DEV_MANAGER;
|
||||
struct _USB_DEV;
|
||||
struct _USB_ENDPOINT;
|
||||
struct _URB;
|
||||
|
||||
typedef VOID ( *PHCD_SET_DEV_MGR )( struct _HCD* hcd, struct _USB_DEV_MANAGER *dev_mgr );
|
||||
typedef struct _USB_DEV_MANAGER* ( *PHCD_GET_DEV_MGR )( struct _HCD* hcd );
|
||||
typedef ULONG ( *PHCD_GET_TYPE )( struct _HCD* hcd );
|
||||
typedef VOID ( *PHCD_SET_ID )( struct _HCD* hcd, UCHAR id );
|
||||
typedef UCHAR ( *PHCD_GET_ID )( struct _HCD* hcd );
|
||||
typedef UCHAR ( *PHCD_ALLOC_ADDR )( struct _HCD* hcd );
|
||||
typedef VOID ( *PHCD_FREE_ADDR )( struct _HCD* hcd, UCHAR addr );
|
||||
typedef NTSTATUS ( *PHCD_SUBMIT_URB )( struct _HCD* hcd, struct _USB_DEV *pdev, struct _USB_ENDPOINT *pendp, struct _URB *purb );
|
||||
typedef VOID ( *PHCD_GENERIC_URB_COMPLETION )( struct _URB *purb, PVOID context ); //we can get te hcd from purb
|
||||
typedef struct _USB_DEV* ( *PHCD_GET_ROOT_HUB )( struct _HCD* hcd );
|
||||
typedef VOID ( *PHCD_SET_ROOT_HUB )( struct _HCD* hcd, struct _USB_DEV *root_hub );
|
||||
typedef BOOLEAN ( *PHCD_REMOVE_DEVICE )( struct _HCD* hcd, struct _USB_DEV *pdev );
|
||||
typedef BOOLEAN ( *PHCD_RH_RESET_PORT )( struct _HCD* hcd, UCHAR port_idx ); //must have the rh dev_lock acquired
|
||||
typedef BOOLEAN ( *PHCD_RELEASE )( struct _HCD* hcd ); //must have the rh dev_lock acquired
|
||||
typedef NTSTATUS( *PHCD_CANCEL_URB)( struct _HCD* hcd, struct _USB_DEV *pdev, struct _USB_ENDPOINT* pendp, struct _URB *purb );
|
||||
typedef BOOLEAN ( *PHCD_START )( struct _HCD* hcd ); //must have the rh dev_lock acquired
|
||||
typedef NTSTATUS ( *PHCD_DISPATCH )( struct _HCD* hcd, LONG disp_code, PVOID param ); // locking depends on type of code
|
||||
|
||||
typedef struct _HCD
|
||||
{
|
||||
PHCD_SET_DEV_MGR hcd_set_dev_mgr;
|
||||
PHCD_GET_DEV_MGR hcd_get_dev_mgr;
|
||||
PHCD_GET_TYPE hcd_get_type;
|
||||
PHCD_SET_ID hcd_set_id;
|
||||
PHCD_GET_ID hcd_get_id;
|
||||
PHCD_ALLOC_ADDR hcd_alloc_addr;
|
||||
PHCD_FREE_ADDR hcd_free_addr;
|
||||
PHCD_SUBMIT_URB hcd_submit_urb;
|
||||
PHCD_GENERIC_URB_COMPLETION hcd_generic_urb_completion;
|
||||
PHCD_GET_ROOT_HUB hcd_get_root_hub;
|
||||
PHCD_SET_ROOT_HUB hcd_set_root_hub;
|
||||
PHCD_REMOVE_DEVICE hcd_remove_device;
|
||||
PHCD_RH_RESET_PORT hcd_rh_reset_port;
|
||||
PHCD_RELEASE hcd_release;
|
||||
PHCD_CANCEL_URB hcd_cancel_urb;
|
||||
PHCD_START hcd_start;
|
||||
PHCD_DISPATCH hcd_dispatch;
|
||||
|
||||
//interfaces for all the host controller
|
||||
ULONG flags; //hcd types | hcd id
|
||||
ULONG conn_count; //statics for connection activities
|
||||
struct _USB_DEV_MANAGER *dev_mgr; //pointer manager
|
||||
UCHAR dev_addr_map[ 128 / 8 ]; //bitmap for the device addrs
|
||||
struct _DEVICE_EXTENSION *pdev_ext;
|
||||
|
||||
} HCD, *PHCD;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,346 +0,0 @@
|
|||
|
||||
#ifndef __HUB_H__
|
||||
#define __HUB_H__
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
|
||||
/* wPortStatus bits */
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
|
||||
/* usb 2.0 features */
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400
|
||||
#define USB_PORT_STAT_PORT_TEST 0x0800
|
||||
#define USB_PORT_STAT_PORT_INDICATOR 0x1000
|
||||
|
||||
/* wPortChange bits */
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
|
||||
/* wHubCharacteristics (masks) */
|
||||
#define HUB_CHAR_LPSM 0x0003
|
||||
#define HUB_CHAR_COMPOUND 0x0004
|
||||
#define HUB_CHAR_OCPM 0x0018
|
||||
|
||||
/*
|
||||
*Hub Status & Hub Change bit masks
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
#define HUB_DESCRIPTOR_MAX_SIZE 39 /* enough for 127 ports on a hub */
|
||||
|
||||
#define MAX_HUB_PORTS 8
|
||||
#define USB_HUB_INTERVAL 0xff
|
||||
|
||||
#define USB_PORT_FLAG_STATE_MASK ( 0xf << 16 )
|
||||
#define USB_PORT_FLAG_ENABLE ( 0x1 << 16 )
|
||||
#define USB_PORT_FLAG_DISABLE ( 0x2 << 16 )
|
||||
#define USB_PORT_FLAG_DISCONNECT ( 0x3 << 16 )
|
||||
|
||||
#define USB_PORT_QUE_STATE_MASK 0xff // for detail, refer to document.txt
|
||||
#define STATE_IDLE 0x00
|
||||
#define STATE_EXAMINE_STATUS_QUE 0x01 // set when post a event to examine the status queue
|
||||
#define STATE_WAIT_STABLE 0x02 // set when a new connection comes and about to wait some ms
|
||||
#define STATE_WAIT_RESET 0x03 // set when dev stable and about to reset, may pending in the event queue
|
||||
#define STATE_WAIT_RESET_COMPLETE 0x04 // set when reset signal is about to assert on the port
|
||||
#define STATE_WAIT_ADDRESSED 0x05 // set when reset complete and before address is assigned
|
||||
|
||||
#define port_state( port_FLAG ) \
|
||||
( port_FLAG & USB_PORT_QUE_STATE_MASK )
|
||||
|
||||
#define set_port_state( port_FLAG, stATE ) \
|
||||
{ port_FLAG = ( port_FLAG & (~USB_PORT_QUE_STATE_MASK ) ) | ( stATE & USB_PORT_QUE_STATE_MASK ) ;}
|
||||
|
||||
#define default_endp_handle( endp_HANDLE ) \
|
||||
( ( endp_HANDLE & 0xffff ) == 0xffff )
|
||||
|
||||
#define is_if_dev( pdev ) ( pdev->flags & USB_DEV_FLAG_IF_DEV )
|
||||
|
||||
#define is_composite_dev( pdev ) \
|
||||
( is_if_dev( pdev ) == FALSE \
|
||||
&& pdev->pusb_dev_desc->bDeviceClass == 0 \
|
||||
&& pdev->pusb_dev_desc->bDeviceSubClass == 0 )
|
||||
|
||||
#define dev_handle_from_dev( pdev ) ( pdev->dev_id << 16 )
|
||||
#define hub_ext_from_dev( pdEV ) ( ( PHUB2_EXTENSION )pdEV->dev_ext )
|
||||
|
||||
#pragma pack( push, hub_align, 1 )
|
||||
typedef struct _USB_PORT_STATUS
|
||||
{
|
||||
USHORT wPortStatus;
|
||||
USHORT wPortChange;
|
||||
|
||||
} USB_PORT_STATUS, *PUSB_PORT_STATUS;
|
||||
|
||||
|
||||
typedef struct _USB_HUB_STATUS
|
||||
{
|
||||
USHORT wHubStatus;
|
||||
USHORT wHubChange;
|
||||
|
||||
} USB_HUB_STATUS, *PUSB_HUB_STATUS;
|
||||
|
||||
|
||||
typedef struct _USB_HUB_DESCRIPTOR
|
||||
{
|
||||
BYTE bLength;
|
||||
BYTE bDescriptorType;
|
||||
BYTE bNbrPorts;
|
||||
USHORT wHubCharacteristics;
|
||||
BYTE bPwrOn2PwrGood;
|
||||
BYTE bHubContrCurrent;
|
||||
|
||||
/* DeviceRemovable and PortPwrCtrlMask want to be variable-length
|
||||
bitmaps that hold max 256 entries, but for now they're ignored */
|
||||
BYTE bitmap[0];
|
||||
} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
|
||||
#pragma pack( pop, hub_align )
|
||||
|
||||
typedef struct _PORT_STATUS_QUEUE
|
||||
{
|
||||
USB_PORT_STATUS port_status[ 4 ];
|
||||
BYTE status_count;
|
||||
ULONG port_flags;
|
||||
|
||||
} PORT_STATUS_QUEUE, *PPORT_STATUS_QUEUE;
|
||||
|
||||
VOID
|
||||
psq_init(
|
||||
PPORT_STATUS_QUEUE psq
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
psq_enqueue(
|
||||
PPORT_STATUS_QUEUE psq,
|
||||
ULONG status
|
||||
);
|
||||
ULONG
|
||||
psq_outqueue(
|
||||
PPORT_STATUS_QUEUE psq
|
||||
); //return 0xffffffff if no element
|
||||
|
||||
BOOLEAN
|
||||
psq_push(
|
||||
PPORT_STATUS_QUEUE psq,
|
||||
ULONG status
|
||||
);
|
||||
|
||||
#define psq_is_empty( pSQ ) ( ( pSQ )->status_count == 0 )
|
||||
#define psq_is_full( pSQ ) ( ( pSQ )->status_count == 4 )
|
||||
#define psq_count( psq ) ( ( psq )->status_count )
|
||||
#define psq_peek( psq, i ) \
|
||||
( ( ( ULONG )i ) < 3 ? ( psq )->port_status[ i ] : ( psq )->port_status[ 3 ] )
|
||||
|
||||
#define MAX_DEVS 127
|
||||
#define EHCI_MAX_ROOT_PORTS 15
|
||||
|
||||
typedef struct _HUB_EXTENSION
|
||||
{
|
||||
|
||||
LONG port_count;
|
||||
PUSB_DEV child_dev[ MAX_HUB_PORTS + 1 ];
|
||||
|
||||
PORT_STATUS_QUEUE port_status_queue[ MAX_HUB_PORTS + 1];
|
||||
PUSB_DEV pdev;
|
||||
PUSB_INTERFACE pif;
|
||||
BYTE int_data_buf[ 64 ];
|
||||
|
||||
USB_HUB_STATUS hub_status;
|
||||
USB_PORT_STATUS port_status; //working data buf for get port feature
|
||||
|
||||
USB_PORT_STATUS rh_port1_status; //working buf for get rh port1 feature
|
||||
USB_PORT_STATUS rh_port2_status; //working buf for get rh port2 feature
|
||||
|
||||
USB_HUB_DESCRIPTOR hub_desc;
|
||||
|
||||
} HUB_EXTENSION, *PHUB_EXTENSION;
|
||||
|
||||
typedef struct _HUB2_PORT_TT
|
||||
{
|
||||
ULONG tt_busy : 1;
|
||||
|
||||
} HUB2_PORT_TT, *PHUB2_PORT_TT;
|
||||
|
||||
typedef struct _HUB2_EXTENSION
|
||||
{
|
||||
|
||||
LONG port_count;
|
||||
PUSB_DEV child_dev[ MAX_HUB_PORTS + 1 ];
|
||||
|
||||
PORT_STATUS_QUEUE port_status_queue[ MAX_HUB_PORTS + 1];
|
||||
|
||||
PUSB_DEV pdev;
|
||||
PUSB_INTERFACE pif;
|
||||
BYTE int_data_buf[ 32 ]; // for ports up to 127
|
||||
|
||||
USB_HUB_STATUS hub_status;
|
||||
USB_PORT_STATUS port_status; //working data buf for get port feature
|
||||
|
||||
USB_PORT_STATUS rh_port_status[ EHCI_MAX_ROOT_PORTS + 1 ]; //working buf for get rh ports feature
|
||||
|
||||
UCHAR multiple_tt; // boolean
|
||||
ULONG tt_status_map[ 4 ]; // bit map to indicate the indexed tt's periodic buffer busy or not
|
||||
ULONG tt_bulk_map[ 4 ]; // bit map to indicate the indexed tt's bulk/control buffer busy or not
|
||||
USB_HUB_DESCRIPTOR hub_desc;
|
||||
|
||||
} HUB2_EXTENSION, *PHUB2_EXTENSION;
|
||||
|
||||
|
||||
VOID
|
||||
event_list_default_process_queue(
|
||||
PLIST_HEAD event_list,
|
||||
PUSB_EVENT_POOL event_pool,
|
||||
PUSB_EVENT usb_event,
|
||||
PUSB_EVENT out_event
|
||||
);
|
||||
|
||||
VOID
|
||||
event_list_default_process_event(
|
||||
PUSB_DEV dev,
|
||||
ULONG event,
|
||||
ULONG context,
|
||||
ULONG param
|
||||
);
|
||||
|
||||
// root hub routines and definitions
|
||||
|
||||
#define RH_INTERVAL ( USB_HUB_INTERVAL / DEV_MGR_TIMER_INTERVAL_MS )
|
||||
|
||||
BOOLEAN
|
||||
rh_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
rh_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
rh_destroy(
|
||||
PUSB_DEV pdev
|
||||
);
|
||||
|
||||
VOID
|
||||
rh_timer_svc(
|
||||
PUSB_DEV dev,
|
||||
PVOID context
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
rh_submit_urb(
|
||||
PUSB_DEV pdev,
|
||||
PURB urb
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
hub_init(
|
||||
PUSB_DEV pdev
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
hub_destroy(
|
||||
PUSB_DEV pdev
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
hub_lock_tt(
|
||||
PUSB_DEV pdev,
|
||||
UCHAR port_idx,
|
||||
UCHAR type // transfer type
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
hub_unlock_tt(
|
||||
PUSB_DEV pdev,
|
||||
UCHAR port_idx,
|
||||
UCHAR type
|
||||
);
|
||||
|
||||
|
||||
VOID
|
||||
hub_post_clear_tt_event(
|
||||
PUSB_DEV pdev,
|
||||
BYTE port_idx,
|
||||
ULONG pipe
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
compdev_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
compdev_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
gendrv_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
gendrv_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
gendrv_if_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
gendrv_if_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN hub_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
BOOLEAN hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
BOOLEAN hub_remove_reset_event(PUSB_DEV pdev, ULONG port_idx, BOOLEAN from_dpc);
|
||||
BOOLEAN hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr, BOOLEAN from_dpc);
|
||||
NTSTATUS hub_start_int_request(PUSB_DEV pdev);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#ifndef __IRPLIST_H
|
||||
#define __IRPLIST_H
|
||||
|
||||
#define MAX_IRP_LIST_SIZE 32
|
||||
|
||||
typedef struct _IRP_LIST_ELEMENT
|
||||
{
|
||||
LIST_ENTRY irp_link;
|
||||
PIRP pirp;
|
||||
struct _URB *purb;
|
||||
|
||||
} IRP_LIST_ELEMENT, *PIRP_LIST_ELEMENT;
|
||||
|
||||
typedef struct _IRP_LIST
|
||||
{
|
||||
KSPIN_LOCK irp_list_lock;
|
||||
LIST_HEAD irp_busy_list;
|
||||
LONG irp_free_list_count;
|
||||
LIST_HEAD irp_free_list;
|
||||
PIRP_LIST_ELEMENT irp_list_element_array;
|
||||
|
||||
} IRP_LIST, *PIRP_LIST;
|
||||
|
||||
BOOLEAN
|
||||
init_irp_list(
|
||||
PIRP_LIST irp_list
|
||||
);
|
||||
|
||||
VOID
|
||||
destroy_irp_list(
|
||||
PIRP_LIST irp_list
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
add_irp_to_list(
|
||||
PIRP_LIST irp_list,
|
||||
PIRP pirp,
|
||||
PURB purb
|
||||
);
|
||||
|
||||
PURB
|
||||
remove_irp_from_list(
|
||||
PIRP_LIST irp_list,
|
||||
PIRP pirp,
|
||||
struct _USB_DEV_MANAGER *dev_mgr
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
irp_list_empty(
|
||||
PIRP_LIST irp_list
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
irp_list_full(
|
||||
PIRP_LIST irp_list
|
||||
);
|
||||
|
||||
#endif
|
|
@ -1,581 +0,0 @@
|
|||
/*
|
||||
* PROJECT: ReactOS USB Drivers
|
||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* FILE: keyboard.c
|
||||
* PURPOSE: Generic USB keyboard driver
|
||||
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
NTSTATUS
|
||||
AddRegistryEntry(IN PCWSTR PortTypeName,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN PCWSTR RegistryPath);
|
||||
|
||||
BOOLEAN kbd_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN kbd_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN kbd_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
VOID kbd_irq(PURB purb, PVOID pcontext);
|
||||
static NTSTATUS
|
||||
KeyboardCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PKEYBOARD_DRVR_EXTENSION DriverExtension);
|
||||
void * memscan(void * addr, int c, size_t size);
|
||||
|
||||
static UCHAR usb_kbd_keycode[256] =
|
||||
{
|
||||
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
|
||||
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
|
||||
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
|
||||
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
|
||||
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
|
||||
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
|
||||
115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
|
||||
122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
|
||||
150,158,159,128,136,177,178,176,142,152,173,140
|
||||
};
|
||||
|
||||
/* This structure starts with the same layout as KEYBOARD_INDICATOR_TRANSLATION */
|
||||
typedef struct _LOCAL_KEYBOARD_INDICATOR_TRANSLATION {
|
||||
USHORT NumberOfIndicatorKeys;
|
||||
INDICATOR_LIST IndicatorList[3];
|
||||
} LOCAL_KEYBOARD_INDICATOR_TRANSLATION, *PLOCAL_KEYBOARD_INDICATOR_TRANSLATION;
|
||||
|
||||
static LOCAL_KEYBOARD_INDICATOR_TRANSLATION IndicatorTranslation = { 3, {
|
||||
{0x3A, KEYBOARD_CAPS_LOCK_ON},
|
||||
{0x45, KEYBOARD_NUM_LOCK_ON},
|
||||
{0x46, KEYBOARD_SCROLL_LOCK_ON}}};
|
||||
|
||||
|
||||
BOOLEAN
|
||||
kbd_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
PKEYBOARD_DRVR_EXTENSION pdrvr_ext;
|
||||
|
||||
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 = 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 = USB_CLASS_HID; // Interface Class
|
||||
pdriver->driver_desc.if_sub_class = 1; // Interface SubClass
|
||||
pdriver->driver_desc.if_protocol = 1; // Interface Protocol
|
||||
|
||||
pdriver->driver_desc.driver_name = "USB Keyboard driver"; // Driver name for Name Registry
|
||||
pdriver->driver_desc.dev_class = USB_CLASS_HID;
|
||||
pdriver->driver_desc.dev_sub_class = 1; // Device Subclass
|
||||
pdriver->driver_desc.dev_protocol = 1; // Protocol Info.
|
||||
|
||||
pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(KEYBOARD_DRVR_EXTENSION));
|
||||
if (!pdriver->driver_ext) return FALSE;
|
||||
pdriver->driver_ext_size = sizeof(KEYBOARD_DRVR_EXTENSION);
|
||||
|
||||
RtlZeroMemory(pdriver->driver_ext, sizeof(KEYBOARD_DRVR_EXTENSION));
|
||||
pdrvr_ext = (PKEYBOARD_DRVR_EXTENSION) pdriver->driver_ext;
|
||||
pdrvr_ext->dev_mgr = dev_mgr;
|
||||
|
||||
pdriver->disp_tbl.version = 1;
|
||||
pdriver->disp_tbl.dev_connect = kbd_connect;
|
||||
pdriver->disp_tbl.dev_disconnect = kbd_disconnect;
|
||||
pdriver->disp_tbl.dev_stop = kbd_stop;
|
||||
pdriver->disp_tbl.dev_reserved = NULL;
|
||||
|
||||
// Create the device
|
||||
KeyboardCreateDevice(dev_mgr->usb_driver_obj, pdrvr_ext);
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_driver_init(): keyboard driver is initialized\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
kbd_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
//PMOUSE_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, ("kbd_driver_destroy(): keyboard driver is destroyed\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
kbd_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
|
||||
{
|
||||
PURB purb;
|
||||
NTSTATUS status;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PUSB_DRIVER pdrvr;
|
||||
PUSB_DEV pdev;
|
||||
PKEYBOARD_DRVR_EXTENSION pdev_ext;
|
||||
PUSB_ENDPOINT_DESC pendp_desc = NULL;
|
||||
ULONG MaxPacketSize;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_connect(): entering...\n"));
|
||||
|
||||
dev_mgr = param->dev_mgr;
|
||||
pdrvr = param->pdriver;
|
||||
pdev_ext = (PKEYBOARD_DRVR_EXTENSION)pdrvr->driver_ext;
|
||||
pdev_ext->dev_handle = dev_handle;
|
||||
|
||||
// Lock USB Device
|
||||
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MEDIUM, ("kbd_connect(): unable to query&lock device, status=0x%x\n", status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get pointer to the endpoint descriptor
|
||||
pendp_desc = pdev->usb_config->interf[0].endp[0].pusb_endp_desc;
|
||||
|
||||
// Store max packet size
|
||||
MaxPacketSize = pendp_desc->wMaxPacketSize;
|
||||
if (MaxPacketSize > 8)
|
||||
MaxPacketSize = 8;
|
||||
|
||||
// Unlock USB Device
|
||||
usb_unlock_dev(pdev);
|
||||
|
||||
// Send interrupt URB
|
||||
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
|
||||
if (purb == NULL)
|
||||
return FALSE;
|
||||
RtlZeroMemory(purb, sizeof(URB));
|
||||
|
||||
RtlZeroMemory(pdev_ext->kbd_old, 8);
|
||||
|
||||
// Build a URB for our interrupt transfer
|
||||
UsbBuildInterruptOrBulkTransferRequest(purb,
|
||||
usb_make_handle((dev_handle >> 16), 0, 0),
|
||||
(PUCHAR)&pdev_ext->kbd_data,
|
||||
MaxPacketSize, //use max packet size
|
||||
kbd_irq,
|
||||
pdev_ext->device_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 TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
kbd_irq(PURB purb, PVOID pcontext)
|
||||
{
|
||||
KEYBOARD_INPUT_DATA KeyboardInputData[20];
|
||||
ULONG DataPrepared=0, DataConsumed, i;
|
||||
UCHAR ScanCode;
|
||||
NTSTATUS status;
|
||||
PKEYBOARD_DRVR_EXTENSION pdev_ext;
|
||||
PKEYBOARD_DEVICE_EXTENSION DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)pcontext;
|
||||
PUCHAR data, data_old;
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_irq(): called\n"));
|
||||
|
||||
ASSERT(purb);
|
||||
|
||||
if (purb->status != STATUS_SUCCESS)
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_irq(): purb->status 0x%08X\n", purb->status));
|
||||
return;
|
||||
}
|
||||
|
||||
pdev_ext = DeviceExtension->DriverExtension;
|
||||
data = pdev_ext->kbd_data;
|
||||
data_old = pdev_ext->kbd_old;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Kbd input: %d %d %d %d %d %d %d %d\n", data[0], data[1], data[2], data[3],
|
||||
data[4], data[5], data[6], data[7]));
|
||||
|
||||
// Zero initial kbd data array
|
||||
RtlZeroMemory(&KeyboardInputData[0], sizeof(KeyboardInputData));
|
||||
|
||||
// Scan modifier keys
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
ScanCode = usb_kbd_keycode[i + 224];
|
||||
|
||||
if (((data[0] >> i) & 1) != ((data_old[0] >> i) & 1))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key p/r %d\n", ScanCode, (data[0] >> i) & 1));
|
||||
|
||||
KeyboardInputData[DataPrepared].MakeCode = ScanCode;
|
||||
if ((data[0] >> i) & 1)
|
||||
KeyboardInputData[DataPrepared].Flags |= KEY_MAKE;
|
||||
else
|
||||
KeyboardInputData[DataPrepared].Flags |= KEY_BREAK;
|
||||
DataPrepared++;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan normal keys
|
||||
for (i=2; i<8; i++)
|
||||
{
|
||||
if (data_old[i] > 3 && memscan(data + 2, data_old[i], 6) == data + 8)
|
||||
{
|
||||
if (usb_kbd_keycode[data_old[i]])
|
||||
{
|
||||
// key released
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key released 1\n", usb_kbd_keycode[data_old[i]]));
|
||||
|
||||
KeyboardInputData[DataPrepared].MakeCode = usb_kbd_keycode[data_old[i]];
|
||||
KeyboardInputData[DataPrepared].Flags |= KEY_BREAK;
|
||||
DataPrepared++;
|
||||
}
|
||||
}
|
||||
|
||||
if (data[i] > 3 && memscan(data_old + 2, data[i], 6) == data_old + 8)
|
||||
{
|
||||
if (usb_kbd_keycode[data[i]])
|
||||
{
|
||||
// key pressed
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key pressed 1\n", usb_kbd_keycode[data[i]]));
|
||||
|
||||
KeyboardInputData[DataPrepared].MakeCode = usb_kbd_keycode[data[i]];
|
||||
KeyboardInputData[DataPrepared].Flags |= KEY_MAKE;
|
||||
DataPrepared++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the input data somewhere...
|
||||
if (DeviceExtension->ConnectData.ClassService && DataPrepared > 0)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)(
|
||||
DeviceExtension->ConnectData.ClassDeviceObject,
|
||||
&KeyboardInputData[0],
|
||||
(&KeyboardInputData[0])+DataPrepared,
|
||||
&DataConsumed);
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
// Save old keyboard data
|
||||
RtlCopyMemory(pdev_ext->kbd_old, data, 8);
|
||||
|
||||
// resubmit the urb
|
||||
status = usb_submit_urb(pdev_ext->dev_mgr, purb);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
kbd_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dev_handle);
|
||||
UNREFERENCED_PARAMETER(dev_mgr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
kbd_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 TRUE;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
kbd_setleds(PKEYBOARD_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PURB Urb;
|
||||
PUSB_CTRL_SETUP_PACKET Setup;
|
||||
NTSTATUS Status;
|
||||
|
||||
// Set LEDs request
|
||||
Urb = usb_alloc_mem(NonPagedPool, sizeof(URB));
|
||||
if (!Urb) return;
|
||||
RtlZeroMemory(Urb, sizeof(URB));
|
||||
|
||||
DeviceExtension->DriverExtension->leds_old = 0;
|
||||
DeviceExtension->DriverExtension->leds = 7;
|
||||
|
||||
// Convert from LedFlags to USB format
|
||||
//DeviceExtension->KeyboardIndicators.LedFlags
|
||||
|
||||
// Build a URB for setting LEDs
|
||||
Setup = (PUSB_CTRL_SETUP_PACKET)Urb->setup_packet;
|
||||
urb_init((Urb));
|
||||
|
||||
Urb->endp_handle = usb_make_handle((DeviceExtension->DriverExtension->dev_handle >> 16), 0, 0) | 0xffff;
|
||||
Urb->data_buffer = &DeviceExtension->DriverExtension->leds;
|
||||
Urb->data_length = 1;
|
||||
Urb->completion = NULL;
|
||||
Urb->context = NULL;
|
||||
Urb->reference = 0;
|
||||
Setup->bmRequestType = USB_DT_HID;
|
||||
Setup->bRequest = USB_REQ_SET_CONFIGURATION;
|
||||
Setup->wValue = USB_DT_CONFIG << 8;
|
||||
Setup->wIndex = 0;
|
||||
Setup->wLength = 1;
|
||||
|
||||
// Call USB driver stack
|
||||
Status = usb_submit_urb(DeviceExtension->DriverExtension->dev_mgr, Urb);
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
usb_free_mem(Urb);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch routine for our IRPs
|
||||
NTSTATUS
|
||||
KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("KbdDispatch(DO %p, code 0x%lx) called\n",
|
||||
DeviceObject,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode));
|
||||
|
||||
if (DeviceObject == DeviceExtension->Fdo)
|
||||
{
|
||||
// it's keyboard's IOCTL
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_INTERNAL_KEYBOARD_CONNECT:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_INTERNAL_KEYBOARD_CONNECT\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) {
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT "
|
||||
"invalid buffer size\n"));
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&DeviceExtension->ConnectData,
|
||||
Stack->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||
sizeof(CONNECT_DATA));
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength <
|
||||
sizeof(KEYBOARD_ATTRIBUTES)) {
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES: "
|
||||
"invalid buffer size\n"));
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
/*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&DevExt->KeyboardAttributes,
|
||||
sizeof(KEYBOARD_ATTRIBUTES));*/
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IOCTL_KEYBOARD_QUERY_INDICATORS:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_INDICATORS\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
&DeviceExtension->KeyboardIndicators,
|
||||
sizeof(KEYBOARD_INDICATOR_PARAMETERS));
|
||||
Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength <
|
||||
sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC: "
|
||||
"invalid buffer size\n"));
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
/*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||
&DevExt->KeyboardTypematic,
|
||||
sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IOCTL_KEYBOARD_SET_INDICATORS:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_SET_INDICATORS\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.InputBufferLength <
|
||||
sizeof(KEYBOARD_INDICATOR_PARAMETERS)) {
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS: "
|
||||
"invalid buffer size\n"));
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&DeviceExtension->KeyboardIndicators,
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
sizeof(KEYBOARD_INDICATOR_PARAMETERS));
|
||||
|
||||
//DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags);
|
||||
kbd_setleds(DeviceExtension);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IOCTL_KEYBOARD_SET_TYPEMATIC:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_SET_TYPEMATIC\n"));
|
||||
if (Stack->Parameters.DeviceIoControl.InputBufferLength <
|
||||
sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC "
|
||||
"invalid buffer size\n"));
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*RtlCopyMemory(&DevExt->KeyboardTypematic,
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
|
||||
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
&IndicatorTranslation,
|
||||
sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION));
|
||||
Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("Invalid internal device request!\n"));
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
if (Status != STATUS_PENDING)
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
KeyboardCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PKEYBOARD_DRVR_EXTENSION DriverExtension)
|
||||
{
|
||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPortUSB");
|
||||
PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = AddRegistryEntry(L"KeyboardPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("AddRegistryEntry() for usb keyboard driver failed with status 0x%08lx\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(KEYBOARD_DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_KEYBOARD,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
TRUE,
|
||||
&Fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status));
|
||||
return Status;
|
||||
}
|
||||
DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(KEYBOARD_DEVICE_EXTENSION));
|
||||
|
||||
DeviceExtension->hdr.dispatch = KbdDispatch;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
DriverExtension->device_ext = DeviceExtension;
|
||||
|
||||
DeviceExtension->Fdo = Fdo;
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
usb_dbg_print(DBGLVL_MEDIUM, ("Created keyboard Fdo: %p\n", Fdo));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* memscan - Find a character in an area of memory.
|
||||
* @addr: The memory area
|
||||
* @c: The byte to search for
|
||||
* @size: The size of the area.
|
||||
*
|
||||
* returns the address of the first occurrence of @c, or 1 byte past
|
||||
* the area if @c is not found
|
||||
*/
|
||||
void * memscan(void * addr, int c, size_t size)
|
||||
{
|
||||
unsigned char * p = (unsigned char *) addr;
|
||||
|
||||
while (size) {
|
||||
if (*p == c)
|
||||
return (void *) p;
|
||||
p++;
|
||||
size--;
|
||||
}
|
||||
return (void *) p;
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef __KEYBOARD_H__
|
||||
#define __KEYBOARD_H__
|
||||
|
||||
#include "kbdmou.h"
|
||||
|
||||
typedef struct _KEYBOARD_DRVR_EXTENSION
|
||||
{
|
||||
PUSB_INTERFACE_DESC pif_desc;
|
||||
DEV_HANDLE dev_handle;
|
||||
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
|
||||
UCHAR kbd_data[8];
|
||||
UCHAR kbd_old[8];
|
||||
|
||||
UCHAR leds;
|
||||
UCHAR leds_old;
|
||||
|
||||
struct _KEYBOARD_DEVICE_EXTENSION *device_ext; // back pointer
|
||||
} KEYBOARD_DRVR_EXTENSION, *PKEYBOARD_DRVR_EXTENSION;
|
||||
|
||||
typedef struct _KEYBOARD_DEVICE_EXTENSION
|
||||
{
|
||||
DEVEXT_HEADER hdr; // mandatory header
|
||||
PKEYBOARD_DRVR_EXTENSION DriverExtension;
|
||||
KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators;
|
||||
CONNECT_DATA ConnectData;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
} KEYBOARD_DEVICE_EXTENSION, *PKEYBOARD_DEVICE_EXTENSION;
|
||||
|
||||
BOOLEAN
|
||||
kbd_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
|
||||
BOOLEAN
|
||||
kbd_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
|
||||
#endif
|
|
@ -1,417 +0,0 @@
|
|||
/*
|
||||
* PROJECT: ReactOS USB Drivers
|
||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* FILE: mouse.c
|
||||
* PURPOSE: Generic USB mouse driver
|
||||
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
BOOLEAN mouse_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN mouse_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
BOOLEAN mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
|
||||
VOID mouse_irq(PURB purb, PVOID pcontext);
|
||||
static NTSTATUS MouseCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PMOUSE_DRVR_EXTENSION DriverExtension);
|
||||
|
||||
BOOLEAN
|
||||
mouse_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
PMOUSE_DRVR_EXTENSION pdrvr_ext;
|
||||
|
||||
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 = 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 = 1; // Configuration Value
|
||||
pdriver->driver_desc.if_num = 1; // Interface Number
|
||||
pdriver->driver_desc.if_class = USB_CLASS_HID; // Interface Class
|
||||
pdriver->driver_desc.if_sub_class = 1; // Interface SubClass
|
||||
pdriver->driver_desc.if_protocol = 2; // Interface Protocol
|
||||
|
||||
pdriver->driver_desc.driver_name = "USB Mouse driver"; // Driver name for Name Registry
|
||||
pdriver->driver_desc.dev_class = USB_CLASS_HID;
|
||||
pdriver->driver_desc.dev_sub_class = 1; // Device Subclass
|
||||
pdriver->driver_desc.dev_protocol = 2; // Protocol Info.
|
||||
|
||||
pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(MOUSE_DRVR_EXTENSION));
|
||||
if (!pdriver->driver_ext) return FALSE;
|
||||
|
||||
pdriver->driver_ext_size = sizeof(MOUSE_DRVR_EXTENSION);
|
||||
|
||||
RtlZeroMemory(pdriver->driver_ext, sizeof(MOUSE_DRVR_EXTENSION));
|
||||
pdrvr_ext = (PMOUSE_DRVR_EXTENSION) pdriver->driver_ext;
|
||||
pdrvr_ext->dev_mgr = dev_mgr;
|
||||
|
||||
pdriver->disp_tbl.version = 1;
|
||||
pdriver->disp_tbl.dev_connect = mouse_connect;
|
||||
pdriver->disp_tbl.dev_disconnect = mouse_disconnect;
|
||||
pdriver->disp_tbl.dev_stop = mouse_stop;
|
||||
pdriver->disp_tbl.dev_reserved = NULL;
|
||||
|
||||
// Create the device
|
||||
MouseCreateDevice(dev_mgr->usb_driver_obj, pdrvr_ext);
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_driver_init(): mouse driver is initialized\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
//PMOUSE_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, ("mouse_driver_destroy(): mouse driver is destroyed\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
mouse_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
|
||||
{
|
||||
PURB purb;
|
||||
NTSTATUS status;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PUSB_DRIVER pdrvr;
|
||||
PUSB_DEV pdev;
|
||||
PMOUSE_DRVR_EXTENSION pdev_ext;
|
||||
// LONG i;
|
||||
PUSB_ENDPOINT_DESC pendp_desc = NULL;
|
||||
ULONG MaxPacketSize;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_connect(): entering...\n"));
|
||||
|
||||
dev_mgr = param->dev_mgr;
|
||||
pdrvr = param->pdriver;
|
||||
pdev_ext = (PMOUSE_DRVR_EXTENSION)pdrvr->driver_ext;
|
||||
|
||||
// Lock USB Device
|
||||
status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
//usb_free_mem(desc_buf);
|
||||
usb_dbg_print(DBGLVL_MEDIUM, ("mouse_connect(): unable to query&lock device, status=0x%x\n", status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get pointer to the endpoint descriptor
|
||||
pendp_desc = pdev->usb_config->interf[0].endp[0].pusb_endp_desc;
|
||||
|
||||
// Store max packet size
|
||||
MaxPacketSize = pendp_desc->wMaxPacketSize;
|
||||
if (MaxPacketSize > 8)
|
||||
MaxPacketSize = 8;
|
||||
|
||||
// Unlock USB Device
|
||||
usb_unlock_dev(pdev);
|
||||
|
||||
// Send URB
|
||||
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
|
||||
if (purb == NULL)
|
||||
return FALSE;
|
||||
RtlZeroMemory(purb, sizeof(URB));
|
||||
|
||||
// Build a URB for our interrupt transfer
|
||||
UsbBuildInterruptOrBulkTransferRequest(purb,
|
||||
usb_make_handle((dev_handle >> 16), 0, 0),
|
||||
(PUCHAR)&pdev_ext->mouse_data,
|
||||
MaxPacketSize, //use max packet size
|
||||
mouse_irq,
|
||||
pdev_ext->device_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 TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
mouse_irq(PURB purb, PVOID pcontext)
|
||||
{
|
||||
MOUSE_INPUT_DATA MouseInputData;
|
||||
ULONG InputDataConsumed;
|
||||
NTSTATUS status;
|
||||
PMOUSE_DRVR_EXTENSION pdev_ext;
|
||||
PMOUSE_DEVICE_EXTENSION DeviceExtension = (PMOUSE_DEVICE_EXTENSION)pcontext;
|
||||
signed char *data;
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): called\n"));
|
||||
|
||||
ASSERT(purb);
|
||||
|
||||
if (purb->status != STATUS_SUCCESS)
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): purb->status 0x%08X\n", purb->status));
|
||||
return;
|
||||
}
|
||||
|
||||
pdev_ext = DeviceExtension->DriverExtension;
|
||||
data = pdev_ext->mouse_data;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0]));
|
||||
|
||||
// Fill mouse input data structure
|
||||
MouseInputData.Flags = MOUSE_MOVE_RELATIVE;
|
||||
MouseInputData.LastX = data[1];
|
||||
MouseInputData.LastY = data[2];
|
||||
|
||||
MouseInputData.ButtonFlags = 0;
|
||||
MouseInputData.ButtonData = 0;
|
||||
|
||||
if ((data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
|
||||
else if (!(data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
|
||||
|
||||
if ((data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
|
||||
else if (!(data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
|
||||
|
||||
if ((data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
|
||||
else if (!(data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
|
||||
|
||||
if ((data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN;
|
||||
else if (!(data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP;
|
||||
|
||||
if ((data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN;
|
||||
else if (!(data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10)))
|
||||
MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP;
|
||||
|
||||
if (data[3])
|
||||
{
|
||||
MouseInputData.ButtonFlags |= MOUSE_WHEEL;
|
||||
MouseInputData.ButtonData = data[3];
|
||||
}
|
||||
|
||||
// Commit the input data somewhere...
|
||||
if (DeviceExtension->ConnectData.ClassService)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)(
|
||||
DeviceExtension->ConnectData.ClassDeviceObject,
|
||||
&MouseInputData,
|
||||
(&MouseInputData)+1,
|
||||
&InputDataConsumed);
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
// Save old button data
|
||||
pdev_ext->btn_old = data[0];
|
||||
|
||||
// resubmit the urb
|
||||
status = usb_submit_urb(pdev_ext->dev_mgr, purb);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dev_handle);
|
||||
UNREFERENCED_PARAMETER(dev_mgr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
mouse_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 TRUE;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
|
||||
}
|
||||
|
||||
// Dispatch routine for our IRPs
|
||||
NTSTATUS
|
||||
MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PMOUSE_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("MouseDispatch(DO %p, code 0x%lx) called\n",
|
||||
DeviceObject,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode));
|
||||
|
||||
if (DeviceObject == DeviceExtension->Fdo)
|
||||
{
|
||||
// it's mouse's IOCTL
|
||||
PIO_STACK_LOCATION Stk;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (Stk->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT\n"));
|
||||
if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) {
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT: "
|
||||
"invalid buffer size\n"));
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
goto intcontfailure2;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&DeviceExtension->ConnectData,
|
||||
Stk->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||
sizeof(CONNECT_DATA));
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
intcontfailure2:
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (Status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("Invalid internal device request!\n"));
|
||||
}
|
||||
|
||||
if (Status != STATUS_PENDING)
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
AddRegistryEntry(
|
||||
IN PCWSTR PortTypeName,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN PCWSTR RegistryPath)
|
||||
{
|
||||
UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hDeviceMapKey = (HANDLE)-1;
|
||||
HANDLE hPortKey = (HANDLE)-1;
|
||||
UNICODE_STRING PortTypeNameU;
|
||||
NTSTATUS Status;
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("ZwOpenKey() failed with status 0x%08lx\n", Status));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
|
||||
Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("ZwCreateKey() failed with status 0x%08lx\n", Status));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, (ULONG)(wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("ZwSetValueKey() failed with status 0x%08lx\n", Status));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (hDeviceMapKey != (HANDLE)-1)
|
||||
ZwClose(hDeviceMapKey);
|
||||
if (hPortKey != (HANDLE)-1)
|
||||
ZwClose(hPortKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
MouseCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PMOUSE_DRVR_EXTENSION DriverExtension)
|
||||
{
|
||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerPortUSB");
|
||||
PMOUSE_DEVICE_EXTENSION DeviceExtension;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = AddRegistryEntry(L"PointerPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(MOUSE_DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_MOUSE,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
TRUE,
|
||||
&Fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
usb_dbg_print(DBGLVL_MINIMUM, ("IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status));
|
||||
return Status;
|
||||
}
|
||||
DeviceExtension = (PMOUSE_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(MOUSE_DEVICE_EXTENSION));
|
||||
|
||||
DeviceExtension->hdr.dispatch = MouseDispatch;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
DriverExtension->device_ext = DeviceExtension;
|
||||
|
||||
DeviceExtension->Fdo = Fdo;
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
usb_dbg_print(DBGLVL_MEDIUM, ("Created mouse Fdo: %p\n", Fdo));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#ifndef __MOUSE_H__
|
||||
#define __MOUSE_H__
|
||||
|
||||
#include "kbdmou.h"
|
||||
|
||||
typedef struct _MOUSE_DRVR_EXTENSION
|
||||
{
|
||||
PUSB_INTERFACE_DESC pif_desc;
|
||||
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
signed char mouse_data[8];
|
||||
UCHAR btn_old;
|
||||
|
||||
struct _MOUSE_DEVICE_EXTENSION *device_ext; // back pointer
|
||||
} MOUSE_DRVR_EXTENSION, *PMOUSE_DRVR_EXTENSION;
|
||||
|
||||
typedef struct _MOUSE_DEVICE_EXTENSION
|
||||
{
|
||||
DEVEXT_HEADER hdr; // mandatory header
|
||||
PMOUSE_DRVR_EXTENSION DriverExtension;
|
||||
CONNECT_DATA ConnectData;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
} MOUSE_DEVICE_EXTENSION, *PMOUSE_DEVICE_EXTENSION;
|
||||
|
||||
BOOLEAN
|
||||
mouse_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
|
||||
BOOLEAN
|
||||
mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,358 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2007 by Aleksey Bragin
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __OHCI_H__
|
||||
#define __OHCI_H__
|
||||
|
||||
#define OHCI_DEVICE_NAME "\\Device\\OHCI"
|
||||
#define OHCI_DOS_DEVICE_NAME "\\DosDevices\\OHCI"
|
||||
|
||||
/* Host Controller Operational Registers */
|
||||
|
||||
#define OHCI_REVISION 0x0
|
||||
#define OHCI_CONTROL 0x4
|
||||
#define OHCI_CMDSTATUS 0x8
|
||||
#define OHCI_INTRSTATUS 0xc
|
||||
#define OHCI_INTRENABLE 0x10
|
||||
#define OHCI_INTRDISABLE 0x14
|
||||
|
||||
/* OHCI CONTROL AND STATUS REGISTER MASKS */
|
||||
|
||||
/*
|
||||
* HcControl (control) register masks
|
||||
*/
|
||||
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
|
||||
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
|
||||
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
|
||||
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
|
||||
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
|
||||
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
|
||||
|
||||
/* pre-shifted values for HCFS */
|
||||
# define OHCI_USB_RESET (0 << 6)
|
||||
# define OHCI_USB_RESUME (1 << 6)
|
||||
# define OHCI_USB_OPER (2 << 6)
|
||||
# define OHCI_USB_SUSPEND (3 << 6)
|
||||
|
||||
/*
|
||||
* HcCommandStatus (cmdstatus) register masks
|
||||
*/
|
||||
#define OHCI_HCR (1 << 0) /* host controller reset */
|
||||
#define OHCI_CLF (1 << 1) /* control list filled */
|
||||
#define OHCI_BLF (1 << 2) /* bulk list filled */
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
|
||||
|
||||
/*
|
||||
* masks used with interrupt registers:
|
||||
* HcInterruptStatus (intrstatus)
|
||||
* HcInterruptEnable (intrenable)
|
||||
* HcInterruptDisable (intrdisable)
|
||||
*/
|
||||
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
|
||||
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
|
||||
#define OHCI_INTR_SF (1 << 2) /* start frame */
|
||||
#define OHCI_INTR_RD (1 << 3) /* resume detect */
|
||||
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
|
||||
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
|
||||
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
|
||||
|
||||
|
||||
/* OHCI ROOT HUB REGISTER MASKS */
|
||||
|
||||
/* roothub.portstatus [i] bits */
|
||||
#define RH_PS_CCS 0x00000001 /* current connect status */
|
||||
#define RH_PS_PES 0x00000002 /* port enable status*/
|
||||
#define RH_PS_PSS 0x00000004 /* port suspend status */
|
||||
#define RH_PS_POCI 0x00000008 /* port over current indicator */
|
||||
#define RH_PS_PRS 0x00000010 /* port reset status */
|
||||
#define RH_PS_PPS 0x00000100 /* port power status */
|
||||
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
|
||||
#define RH_PS_CSC 0x00010000 /* connect status change */
|
||||
#define RH_PS_PESC 0x00020000 /* port enable status change */
|
||||
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
|
||||
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
|
||||
#define RH_PS_PRSC 0x00100000 /* port reset status change */
|
||||
|
||||
/* roothub.status bits */
|
||||
#define RH_HS_LPS 0x00000001 /* local power status */
|
||||
#define RH_HS_OCI 0x00000002 /* over current indicator */
|
||||
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
|
||||
#define RH_HS_LPSC 0x00010000 /* local power status change */
|
||||
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
|
||||
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
/*
|
||||
* OHCI Endpoint Descriptor (ED) ... holds TD queue
|
||||
* See OHCI spec, section 4.2
|
||||
*
|
||||
* This is a "Queue Head" for those transfers, which is why
|
||||
* both EHCI and UHCI call similar structures a "QH".
|
||||
*/
|
||||
typedef struct _OHCI_ED {
|
||||
/* first fields are hardware-specified */
|
||||
ULONG hwINFO; /* endpoint config bitmap */
|
||||
/* info bits defined by hcd */
|
||||
#define ED_DEQUEUE (1 << 27)
|
||||
/* info bits defined by the hardware */
|
||||
#define ED_ISO (1 << 15)
|
||||
#define ED_SKIP (1 << 14)
|
||||
#define ED_LOWSPEED (1 << 13)
|
||||
#define ED_OUT (0x01 << 11)
|
||||
#define ED_IN (0x02 << 11)
|
||||
ULONG hwTailP; /* tail of TD list */
|
||||
ULONG hwHeadP; /* head of TD list (hc r/w) */
|
||||
#define ED_C (0x02) /* toggle carry */
|
||||
#define ED_H (0x01) /* halted */
|
||||
ULONG hwNextED; /* next ED in list */
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
#if 0
|
||||
dma_addr_t dma; /* addr of ED */
|
||||
struct _OHCI_TD *dummy; /* next TD to activate */
|
||||
|
||||
/* host's view of schedule */
|
||||
struct _OHCI_ED *ed_next; /* on schedule or rm_list */
|
||||
struct _OHCI_ED *ed_prev; /* for non-interrupt EDs */
|
||||
struct list_head td_list; /* "shadow list" of our TDs */
|
||||
|
||||
/* create --> IDLE --> OPER --> ... --> IDLE --> destroy
|
||||
* usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
|
||||
*/
|
||||
UCHAR state; /* ED_{IDLE,UNLINK,OPER} */
|
||||
#define ED_IDLE 0x00 /* NOT linked to HC */
|
||||
#define ED_UNLINK 0x01 /* being unlinked from hc */
|
||||
#define ED_OPER 0x02 /* IS linked to hc */
|
||||
|
||||
UCHAR type; /* PIPE_{BULK,...} */
|
||||
|
||||
/* periodic scheduling params (for intr and iso) */
|
||||
UCHAR branch;
|
||||
USHORT interval;
|
||||
USHORT load;
|
||||
USHORT last_iso; /* iso only */
|
||||
|
||||
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
|
||||
USHORT tick;
|
||||
#endif
|
||||
} OHCI_ED, *POHCI_ED;
|
||||
|
||||
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
|
||||
|
||||
|
||||
/*
|
||||
* OHCI Transfer Descriptor (TD) ... one per transfer segment
|
||||
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
|
||||
* and 4.3.2 (iso)
|
||||
*/
|
||||
typedef struct _OHCI_TD {
|
||||
/* first fields are hardware-specified */
|
||||
ULONG hwINFO; /* transfer info bitmask */
|
||||
|
||||
/* hwINFO bits for both general and iso tds: */
|
||||
#define TD_CC 0xf0000000 /* condition code */
|
||||
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
|
||||
//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
|
||||
#define TD_DI 0x00E00000 /* frames before interrupt */
|
||||
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
|
||||
/* these two bits are available for definition/use by HCDs in both
|
||||
* general and iso tds ... others are available for only one type
|
||||
*/
|
||||
#define TD_DONE 0x00020000 /* retired to donelist */
|
||||
#define TD_ISO 0x00010000 /* copy of ED_ISO */
|
||||
|
||||
/* hwINFO bits for general tds: */
|
||||
#define TD_EC 0x0C000000 /* error count */
|
||||
#define TD_T 0x03000000 /* data toggle state */
|
||||
#define TD_T_DATA0 0x02000000 /* DATA0 */
|
||||
#define TD_T_DATA1 0x03000000 /* DATA1 */
|
||||
#define TD_T_TOGGLE 0x00000000 /* uses ED_C */
|
||||
#define TD_DP 0x00180000 /* direction/pid */
|
||||
#define TD_DP_SETUP 0x00000000 /* SETUP pid */
|
||||
#define TD_DP_IN 0x00100000 /* IN pid */
|
||||
#define TD_DP_OUT 0x00080000 /* OUT pid */
|
||||
/* 0x00180000 rsvd */
|
||||
#define TD_R 0x00040000 /* round: short packets OK? */
|
||||
|
||||
/* (no hwINFO #defines yet for iso tds) */
|
||||
|
||||
ULONG hwCBP; /* Current Buffer Pointer (or 0) */
|
||||
ULONG hwNextTD; /* Next TD Pointer */
|
||||
ULONG hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
/* PSW is only for ISO. Only 1 PSW entry is used, but on
|
||||
* big-endian PPC hardware that's the second entry.
|
||||
*/
|
||||
#define MAXPSW 2
|
||||
USHORT hwPSW [MAXPSW];
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
#if 0
|
||||
UCHAR index;
|
||||
struct ed *ed;
|
||||
struct td *td_hash; /* dma-->td hashtable */
|
||||
struct td *next_dl_td;
|
||||
struct urb *urb;
|
||||
|
||||
dma_addr_t td_dma; /* addr of this TD */
|
||||
dma_addr_t data_dma; /* addr of data it points to */
|
||||
|
||||
struct list_head td_list; /* "shadow list", TDs on same ED */
|
||||
#endif
|
||||
} OHCI_TD, *POHCI_TD;
|
||||
|
||||
/*
|
||||
* The HCCA (Host Controller Communications Area) is a 256 byte
|
||||
* structure defined section 4.4.1 of the OHCI spec. The HC is
|
||||
* told the base address of it. It must be 256-byte aligned.
|
||||
*/
|
||||
typedef struct _OHCI_HCCA
|
||||
{
|
||||
#define NUM_INTS 32
|
||||
ULONG int_table [NUM_INTS]; /* periodic schedule */
|
||||
|
||||
/*
|
||||
* OHCI defines u16 frame_no, followed by u16 zero pad.
|
||||
* Since some processors can't do 16 bit bus accesses,
|
||||
* portable access must be a 32 bits wide.
|
||||
*/
|
||||
ULONG frame_no; /* current frame number */
|
||||
ULONG done_head; /* info returned for an interrupt */
|
||||
UCHAR reserved_for_hc [116];
|
||||
UCHAR what [4]; /* spec only identifies 252 bytes :) */
|
||||
} OHCI_HCCA, *POHCI_HCCA;
|
||||
|
||||
/*
|
||||
* This is the structure of the OHCI controller's memory mapped I/O region.
|
||||
* You must use readl() and writel() (in <asm/io.h>) to access these fields!!
|
||||
* Layout is in section 7 (and appendix B) of the spec.
|
||||
*/
|
||||
typedef struct _OHCI_REGS
|
||||
{
|
||||
/* control and status registers (section 7.1) */
|
||||
ULONG revision;
|
||||
ULONG control;
|
||||
ULONG cmdstatus;
|
||||
ULONG intrstatus;
|
||||
ULONG intrenable;
|
||||
ULONG intrdisable;
|
||||
|
||||
/* memory pointers (section 7.2) */
|
||||
ULONG hcca;
|
||||
ULONG ed_periodcurrent;
|
||||
ULONG ed_controlhead;
|
||||
ULONG ed_controlcurrent;
|
||||
ULONG ed_bulkhead;
|
||||
ULONG ed_bulkcurrent;
|
||||
ULONG donehead;
|
||||
|
||||
/* frame counters (section 7.3) */
|
||||
ULONG fminterval;
|
||||
ULONG fmremaining;
|
||||
ULONG fmnumber;
|
||||
ULONG periodicstart;
|
||||
ULONG lsthresh;
|
||||
|
||||
/* Root hub ports (section 7.4) */
|
||||
struct ohci_roothub_regs {
|
||||
ULONG a;
|
||||
ULONG b;
|
||||
ULONG status;
|
||||
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
|
||||
ULONG portstatus [MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
|
||||
/* and optional "legacy support" registers (appendix B) at 0x0100 */
|
||||
} OHCI_REGS, *POHCI_REGS;
|
||||
|
||||
typedef struct _OHCI_DEV
|
||||
{
|
||||
HCD hcd_interf;
|
||||
|
||||
PHYSICAL_ADDRESS ohci_reg_base; // io space
|
||||
BOOLEAN port_mapped;
|
||||
PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base
|
||||
struct _OHCI_REGS *regs;
|
||||
struct _OHCI_HCCA *hcca;
|
||||
PVOID td_cache;
|
||||
PVOID ed_cache;
|
||||
|
||||
PHYSICAL_ADDRESS hcca_logic_addr;
|
||||
PHYSICAL_ADDRESS td_logic_addr;
|
||||
PHYSICAL_ADDRESS ed_logic_addr;
|
||||
|
||||
USHORT num_ports;
|
||||
|
||||
LIST_HEAD urb_list; // active urb-list
|
||||
|
||||
//
|
||||
//for iso and int bandwidth claim, bandwidth schedule
|
||||
//
|
||||
KSPIN_LOCK pending_endp_list_lock; //lock to access the following two
|
||||
LIST_HEAD pending_endp_list;
|
||||
UHCI_PENDING_ENDP_POOL pending_endp_pool;
|
||||
|
||||
KTIMER reset_timer; //used to reset the host controller
|
||||
struct _OHCI_DEVICE_EXTENSION *pdev_ext;
|
||||
PUSB_DEV root_hub; //root hub
|
||||
} OHCI_DEV, *POHCI_DEV;
|
||||
|
||||
typedef struct _OHCI_DEVICE_EXTENSION
|
||||
{
|
||||
DEVEXT_HEADER dev_ext_hdr;
|
||||
PDEVICE_OBJECT pdev_obj;
|
||||
PDRIVER_OBJECT pdrvr_obj;
|
||||
POHCI_DEV ohci;
|
||||
|
||||
//device resources
|
||||
PADAPTER_OBJECT padapter;
|
||||
ULONG map_regs;
|
||||
PCM_RESOURCE_LIST res_list;
|
||||
ULONG pci_addr; // bus number | slot number | funciton number
|
||||
UHCI_INTERRUPT res_interrupt;
|
||||
union
|
||||
{
|
||||
UHCI_PORT res_port;
|
||||
EHCI_MEMORY res_memory;
|
||||
};
|
||||
|
||||
PKINTERRUPT ohci_int;
|
||||
KDPC ohci_dpc;
|
||||
} OHCI_DEVICE_EXTENSION, *POHCI_DEVICE_EXTENSION;
|
||||
|
||||
#define ohci_from_hcd( hCD ) ( struct_ptr( ( hCD ), OHCI_DEV, hcd_interf ) )
|
||||
|
||||
#endif /* __OHCI_H__ */
|
|
@ -1,433 +0,0 @@
|
|||
/**
|
||||
* roothub.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
rh_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
|
||||
{
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
//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
|
||||
BOOLEAN
|
||||
rh_destroy(PUSB_DEV pdev)
|
||||
{
|
||||
PUSB_DEV rh;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
VOID
|
||||
rh_timer_svc_int_completion(PUSB_DEV pdev, PVOID context)
|
||||
{
|
||||
PURB purb;
|
||||
PHCD hcd;
|
||||
USE_BASIC_NON_PENDING_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);
|
||||
|
||||
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_ULTRA, ("rh_timer_svc_int_completion(): rh's ref_count=0x%x\n", pdev->ref_count));
|
||||
unlock_dev(pdev, TRUE);
|
||||
usb_dbg_print(DBGLVL_ULTRA, ("rh_timer_svc_int_completion(): exitiing...\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
rh_timer_svc_reset_port_completion(PUSB_DEV pdev, PVOID context)
|
||||
{
|
||||
PURB purb;
|
||||
ULONG i;
|
||||
PHUB2_EXTENSION hub_ext;
|
||||
PLIST_ENTRY pthis, pnext;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PUSB_CTRL_SETUP_PACKET psetup;
|
||||
|
||||
USE_BASIC_NON_PENDING_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;
|
||||
}
|
|
@ -1,603 +0,0 @@
|
|||
/**
|
||||
* td.c - USB driver stack project for Windows NT 4.0
|
||||
*
|
||||
* Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program (in the main directory of the distribution, the file
|
||||
* COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "usbdriver.h"
|
||||
|
||||
#define UHCI_MIN_TD_POOLS 4
|
||||
|
||||
BOOLEAN 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
|
||||
|
||||
BOOLEAN
|
||||
init_td_pool(PUHCI_TD_POOL ptd_pool)
|
||||
{
|
||||
int i, pages;
|
||||
PTD_EXTENSION ptde;
|
||||
|
||||
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->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++)
|
||||
{
|
||||
//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]);
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
//add tds till pnext == NULL
|
||||
BOOLEAN
|
||||
free_td_to_pool(PUHCI_TD_POOL ptd_pool, PUHCI_TD ptd)
|
||||
{
|
||||
if (ptd_pool == NULL || ptd == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
// qh routines
|
||||
|
||||
//null if failed
|
||||
PUHCI_TD
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
return ptde->ptd;
|
||||
|
||||
}
|
||||
|
||||
//test whether the pool is all free
|
||||
BOOLEAN
|
||||
is_pool_free(PUHCI_TD_POOL pool)
|
||||
{
|
||||
if (pool == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (pool->free_count == pool->total_count)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
is_pool_empty(PUHCI_TD_POOL pool)
|
||||
{
|
||||
if (pool == NULL)
|
||||
return FALSE;
|
||||
|
||||
return (BOOLEAN) (pool->free_count == 0);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
destroy_td_pool(PUHCI_TD_POOL ptd_pool)
|
||||
{
|
||||
int i, pages;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
//private
|
||||
LONG
|
||||
get_num_free_tds(PUHCI_TD_POOL_LIST pool_list)
|
||||
{
|
||||
return pool_list->free_tds;
|
||||
}
|
||||
|
||||
//private
|
||||
LONG
|
||||
get_max_free_tds(PUHCI_TD_POOL_LIST pool_list)
|
||||
{
|
||||
return pool_list->free_tds + pool_list->free_count * UHCI_MAX_POOL_TDS;
|
||||
}
|
||||
|
||||
//add tds till pnext == NULL
|
||||
BOOLEAN
|
||||
free_td(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd)
|
||||
{
|
||||
if (pool_list == NULL || ptd == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (free_td_to_pool(ptd->pool, ptd) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
pool_list->free_tds++;
|
||||
|
||||
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)
|
||||
{
|
||||
PLIST_ENTRY prev, next;
|
||||
PUHCI_TD new_td;
|
||||
|
||||
if (pool_list == NULL)
|
||||
return NULL;
|
||||
|
||||
if (pool_list->free_tds == 0)
|
||||
{
|
||||
if (expand_pool_list(pool_list, 1) == FALSE)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (new_td == NULL)
|
||||
TRAP();
|
||||
|
||||
pool_list->free_tds--;
|
||||
|
||||
return new_td;
|
||||
}
|
||||
|
||||
ListNext(&pool_list->busy_pools, prev, next);
|
||||
prev = next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PUHCI_TD
|
||||
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;
|
||||
|
||||
if (pool_list == NULL || count <= 0)
|
||||
return NULL;
|
||||
|
||||
if (count >= get_max_free_tds(pool_list))
|
||||
return NULL;
|
||||
|
||||
ptd = alloc_td(pool_list);
|
||||
if (!ptd) return NULL;
|
||||
|
||||
for(i = 1; i < count; i++)
|
||||
{
|
||||
pnext = alloc_td(pool_list);
|
||||
|
||||
if (pnext)
|
||||
{
|
||||
InsertTailList(&ptd->ptde->vert_link, &pnext->ptde->vert_link);
|
||||
}
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
free_tds(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd)
|
||||
{
|
||||
PUHCI_TD ptofree;
|
||||
PLIST_ENTRY pthis;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
free_td(pool_list, ptd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOLEAN
|
||||
can_transfer(PUHCI_TD_POOL_LIST pool_list, LONG td_count)
|
||||
{
|
||||
if (td_count > get_max_free_tds(pool_list))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
lock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOLEAN at_dpc)
|
||||
{
|
||||
//if( !at_dpc )
|
||||
// KeAcquireSpinLock( &pool_list->pool_lock );
|
||||
//else
|
||||
// KeAcquireSpinLockAtDpcLevel( &pool_list->pool_lock );
|
||||
}
|
||||
|
||||
VOID
|
||||
unlock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOLEAN at_dpc)
|
||||
{
|
||||
//if( !at_dpc )
|
||||
// KeReleaseSpinLock( &pool_list->pool_lock );
|
||||
//else
|
||||
// KeReleaseSpinLockFromDpcLevel( &pool_list->pool_lock );
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
init_qh_pool(PUHCI_QH_POOL pqh_pool, PADAPTER_OBJECT padapter)
|
||||
{
|
||||
PQH_EXTENSION pqhe;
|
||||
LONG i;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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];
|
||||
|
||||
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;
|
||||
|
||||
free_qh(pqh_pool, &pqh_pool->qh_array[i]);
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
//add qhs till pnext == NULL
|
||||
BOOLEAN
|
||||
free_qh(PUHCI_QH_POOL pqh_pool, PUHCI_QH pqh)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//null if failed
|
||||
PUHCI_QH
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
destroy_qh_pool(PUHCI_QH_POOL pqh_pool)
|
||||
{
|
||||
if (pqh_pool)
|
||||
{
|
||||
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);
|
||||
|
||||
RtlZeroMemory(pqh_pool, sizeof(UHCI_QH_POOL));
|
||||
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
lock_qh_pool(PUHCI_QH_POOL pool, BOOLEAN at_dpc)
|
||||
{
|
||||
//if( !at_dpc )
|
||||
// KeAcquireSpinLock( &pool->pool_lock );
|
||||
//else
|
||||
// KeAcquireSpinLockAtDpcLevel( &pool->pool_lock );
|
||||
}
|
||||
|
||||
VOID
|
||||
unlock_qh_pool(PUHCI_QH_POOL pool, BOOLEAN at_dpc)
|
||||
{
|
||||
//if( !at_dpc )
|
||||
// KeReleaseSpinLock( &pool->pool_lock );
|
||||
//else
|
||||
// KeReleaseSpinLockFromDpcLevel( &pool->pool_lock );
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,13 +0,0 @@
|
|||
#ifndef __UHCIVER_H__
|
||||
#define __UHCIVER_H__
|
||||
|
||||
//#define _MULTI_UHCI
|
||||
//#define _TIANSHENG_DRIVER
|
||||
|
||||
#ifdef _MULTI_UHCI
|
||||
#define UHCI_VER_STR "m564.a\0"
|
||||
#else
|
||||
#define UHCI_VER_STR "0564.d\0"
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,350 +0,0 @@
|
|||
#ifndef __UMSS_H__
|
||||
#define __UMSS_H__
|
||||
|
||||
#define MAX_BULK_TRANSFER_LENGTH 0x100000
|
||||
|
||||
#define PROTOCOL_CBI 0x00
|
||||
#define PROTOCOL_CB 0x01
|
||||
#define PROTOCOL_BULKONLY 0x50
|
||||
|
||||
#define PROTOCOL_UNDEFINED 0xFF // Not in spec
|
||||
|
||||
#define UMSS_SUBCLASS_RBC 0x01
|
||||
#define UMSS_SUBCLASS_SFF8020I 0X02
|
||||
#define UMSS_SUBCLASS_QIC157 0x03
|
||||
#define UMSS_SUBCLASS_UFI 0x04
|
||||
#define UMSS_SUBCLASS_SFF8070I 0x05
|
||||
#define UMSS_SUBCLASS_SCSI_TCS 0x06
|
||||
|
||||
#define ACCEPT_DEVICE_SPECIFIC_COMMAND 0
|
||||
|
||||
#define BULK_ONLY_MASS_STORAGE_RESET 0xFF
|
||||
#define BULK_ONLY_GET_MAX_LUN 0xFE
|
||||
|
||||
#define CBW_SIGNATURE 0x43425355L
|
||||
#define CSW_SIGNATURE 0x53425355L
|
||||
#define CSW_OLYMPUS_SIGNATURE 0x55425355L
|
||||
|
||||
#define CSW_STATUS_PASSED 0x00
|
||||
#define CSW_STATUS_FAILED 0x01
|
||||
#define CSW_STATUS_PHASE_ERROR 0x02
|
||||
|
||||
#define IOCTL_UMSS_SUBMIT_CDB CTL_CODE( FILE_USB_DEV_TYPE, 4200, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// for request with no other input and output
|
||||
// input buffer is a _USER_IO_PACKET and input_buffer_length is length of the _USER_IO_PACKET
|
||||
// output_buffer is NULL, and output_buffer_length is zero
|
||||
|
||||
#define IOCTL_UMSS_SUBMIT_CDB_IN CTL_CODE( FILE_USB_DEV_TYPE, 4201, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
|
||||
// for request to read in data
|
||||
// input_buffer is a _USER_IO_PACKET and input_buffer_length is length to the _USER_IO_PACKET
|
||||
// output_buffer is a buffer to receive the data from dev, and
|
||||
// output_buffer_length is the size of the buffer
|
||||
|
||||
#define IOCTL_UMSS_SUBMIT_CDB_OUT CTL_CODE( FILE_USB_DEV_TYPE, 4202, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
|
||||
// for request to write data to device
|
||||
// input_buffer is a _USER_IO_PACKET and input_buffer_length is length to the _USER_IO_PACKET
|
||||
// output_buffer is data to send to the device, and
|
||||
// output_buffer_length is the size of the buffer
|
||||
|
||||
#define IOCTL_REGISTER_DRIVER CTL_CODE( FILE_USB_DEV_TYPE, 4203, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// input_buffer is a CLASS_DRV_REG_INFO, and input_buffer_length is equal to or greater than
|
||||
// sizeof( CLASS_DRV_REG_INFO ); the output_buffer is null and no output_buffer_length,
|
||||
// only the following fields in urb can be accessed, others must be zeroed.
|
||||
|
||||
#define IOCTL_REVOKE_DRIVER CTL_CODE( FILE_USB_DEV_TYPE, 4204, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// tell the umss driver to clear the information in the drivers registry
|
||||
// no other parameters
|
||||
|
||||
#define IOCTL_UMSS_SUBMIT_SRB CTL_CODE( FILE_USB_DEV_TYPE, 4205, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// irpStack->Parameters.Scsi.Srb points to an Srb structure and all the data buffer and buffer
|
||||
// size are stored in the srb
|
||||
|
||||
|
||||
#define IOCTL_UMSS_SET_FDO CTL_CODE( FILE_USB_DEV_TYPE, 4206, METHOD_BUFFERED, FILE_ANY_ACCESS )
|
||||
// input_buffer is a pointer to PDEVICE_OBJECT, and input_buffer_length should be
|
||||
// no less than sizeof( PDEVICE_OBJECT )
|
||||
// output buffer is NULL, and output_buffer_length is zero
|
||||
// if the deivce is accessable, the fdo is set, else, the fdo is not set and return
|
||||
// STATUS_DEVICE_DOES_NOT_EXIST
|
||||
|
||||
#define SFF_FORMAT_UNIT 0x04
|
||||
#define SFF_INQUIRY 0x12
|
||||
#define SFF_MODE_SELECT 0x55
|
||||
#define SFF_MODE_SENSE 0x5a
|
||||
#define SFF_ALLOW_REMOVE 0x1e
|
||||
#define SFF_READ10 0x28
|
||||
#define SFF_READ12 0xa8
|
||||
#define SFF_READ_CAPACITY 0x25
|
||||
#define SFF_REQUEST_SENSEE 0x03
|
||||
#define SFF_SEEK 0x2b
|
||||
#define SFF_START_STOP 0x1b
|
||||
#define SFF_TUR 0x00
|
||||
#define SFF_VERIFY 0x2f
|
||||
#define SFF_WRITE10 0x2a
|
||||
#define SFF_WRITE12 0xaa
|
||||
#define SFF_READ_FMT_CAPACITY 0x23
|
||||
#define SFF_WRITE_VERIFY 0x2e
|
||||
|
||||
#define MAX_CDB_LENGTH 0x10
|
||||
|
||||
typedef struct _USER_IO_PACKET
|
||||
{
|
||||
UCHAR sub_class;
|
||||
UCHAR lun;
|
||||
UCHAR cdb_length;
|
||||
UCHAR cdb[ MAX_CDB_LENGTH ];
|
||||
|
||||
} USER_IO_PACKET, *PUSER_IO_PACKET;
|
||||
|
||||
//flags for IO_PACKET::flags
|
||||
#define IOP_FLAG_REQ_SENSE 0x80000000 // sense data would be fetched if error occurs
|
||||
#define IOP_FLAG_SRB_TRANSFER 0x40000000 // current tranfer is initiated by an srb request, the srb is held by the irp
|
||||
#define IOP_FLAG_SCSI_CTRL_TRANSFER 0x20000000 // current transfer is initiated by an scsi ioctrl request
|
||||
|
||||
#define IOP_FLAG_DIR_IN USB_DIR_IN
|
||||
#define IOP_FLAG_STAGE_MASK 0x03
|
||||
#define IOP_FLAG_STAGE_NORMAL 0x00
|
||||
#define IOP_FLAG_STAGE_SENSE 0x01
|
||||
|
||||
typedef struct _IO_PACKET
|
||||
{
|
||||
ULONG flags;
|
||||
UCHAR cdb_length;
|
||||
UCHAR cdb[ MAX_CDB_LENGTH ];
|
||||
UCHAR lun;
|
||||
PVOID data_buffer;
|
||||
ULONG data_length;
|
||||
PVOID sense_data;
|
||||
ULONG sense_data_length;
|
||||
PIRP pirp;
|
||||
|
||||
} IO_PACKET, *PIO_PACKET;
|
||||
|
||||
#pragma pack( 1 )
|
||||
|
||||
typedef struct _COMMAND_BLOCK_WRAPPER
|
||||
{
|
||||
ULONG dCBWSignature;
|
||||
ULONG dCBWTag;
|
||||
ULONG dCBWDataTransferLength;
|
||||
UCHAR bmCBWFlags;
|
||||
UCHAR bCBWLun;
|
||||
UCHAR bCBWLength;
|
||||
UCHAR CBWCB[ MAX_CDB_LENGTH ];
|
||||
|
||||
} COMMAND_BLOCK_WRAPPER, *PCOMMAND_BLOCK_WRAPPER;
|
||||
|
||||
typedef struct _COMMAND_STATUS_WRAPPER
|
||||
{
|
||||
ULONG dCSWSignature;
|
||||
ULONG dCSWTag;
|
||||
ULONG dCSWDataResidue;
|
||||
UCHAR bCSWStatus;
|
||||
|
||||
} COMMAND_STATUS_WRAPPER, *PCOMMAND_STATUS_WRAPPER;
|
||||
|
||||
|
||||
typedef struct _INTERRUPT_DATA_BLOCK
|
||||
{
|
||||
UCHAR bType;
|
||||
UCHAR bValue;
|
||||
|
||||
} INTERRUPT_DATA_BLOCK, *PINTERRUPT_DATA_BLOCK;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#define UMSS_PNPMSG_STOP 0x01
|
||||
#define UMSS_PNPMSG_DISCONNECT 0x02
|
||||
|
||||
typedef NTSTATUS ( *PCLASS_DRVR_PNP_DISP )( PDEVICE_OBJECT pdo, ULONG ctrl_code, PVOID context );
|
||||
// pdo is the device object umss created
|
||||
|
||||
typedef PDEVICE_OBJECT ( *PCLASS_DRIVER_ADD_DEV )( PDRIVER_OBJECT fdo_drvr, PDEVICE_OBJECT pdo );
|
||||
// if the return value is not zero, it is a pointer to the
|
||||
// fdo sitting over the pdo of this driver. if it is null,
|
||||
// the add_device failed, and initialization process should
|
||||
// stall.
|
||||
|
||||
typedef struct _CLASS_DRV_REGISTRY_INFO
|
||||
{
|
||||
// class driver will pass this structure to umss port
|
||||
// driver after loaded
|
||||
PDRIVER_OBJECT fdo_driver;
|
||||
PCLASS_DRIVER_ADD_DEV add_device;
|
||||
PCLASS_DRVR_PNP_DISP pnp_dispatch;
|
||||
|
||||
} CLASS_DRV_REG_INFO, *PCLASS_DRV_REG_INFO;
|
||||
|
||||
typedef struct _UMSS_PORT_DEVICE_EXTENSION
|
||||
{
|
||||
// this structure is the device extension for port dev_obj
|
||||
// it is used to has class driver pass CLASS_DRV_REG_INFO
|
||||
// to our umss driver.
|
||||
DEVEXT_HEADER dev_ext_hdr;
|
||||
PUSB_DRIVER pdriver;
|
||||
|
||||
} UMSS_PORT_DEV_EXT, *PUMSS_PORT_DEV_EXT;
|
||||
|
||||
typedef struct _UMSS_DRVR_EXTENSION
|
||||
{
|
||||
LIST_HEAD dev_list;
|
||||
FAST_MUTEX dev_list_mutex;
|
||||
UCHAR dev_count;
|
||||
CLASS_DRV_REG_INFO class_driver_info;
|
||||
PDEVICE_OBJECT port_dev_obj; // we use this obj as a connection point for class driver, its name usbPort0
|
||||
|
||||
} UMSS_DRVR_EXTENSION, *PUMSS_DRVR_EXTENSION;
|
||||
|
||||
#define UMSS_DEV_FLAG_IF_DEV 0x01
|
||||
#define UMSS_DEV_FLAG_OLYMPUS_DEV 0x02
|
||||
|
||||
#define UMSS_OLYMPUS_VENDOR_ID 0x07b4
|
||||
|
||||
typedef struct _UMSS_DEVICE_EXTENSION
|
||||
{
|
||||
//this structure is the device extension for dev_obj
|
||||
//created for the device.
|
||||
DEVEXT_HEADER dev_ext_hdr;
|
||||
|
||||
ULONG flags;
|
||||
LIST_ENTRY dev_obj_link; // this link is used by the driver object to track the existing dev_objs
|
||||
|
||||
PDEVICE_OBJECT pdo; // this is the pdo
|
||||
PDEVICE_OBJECT fdo; // driver object for the dev_obj
|
||||
|
||||
DEV_HANDLE dev_handle; // handle to the usb_dev under
|
||||
|
||||
PUCHAR desc_buf;
|
||||
UCHAR umss_dev_id; // used to build symbolic link
|
||||
|
||||
PUSB_INTERFACE_DESC pif_desc;
|
||||
PUSB_ENDPOINT_DESC pout_endp_desc, pin_endp_desc, pint_endp_desc;
|
||||
UCHAR if_idx, out_endp_idx, in_endp_idx, int_endp_idx;
|
||||
|
||||
struct _USB_DEV_MANAGER *dev_mgr;
|
||||
|
||||
//working data
|
||||
COMMAND_BLOCK_WRAPPER cbw;
|
||||
union
|
||||
{
|
||||
INTERRUPT_DATA_BLOCK idb;
|
||||
COMMAND_STATUS_WRAPPER csw;
|
||||
};
|
||||
|
||||
KEVENT sync_event; //for umss_sync_submit_urb
|
||||
KSPIN_LOCK dev_lock;
|
||||
IO_PACKET io_packet;
|
||||
BOOLEAN retry;
|
||||
|
||||
PUSB_DRIVER pdriver; //used by umss_delete_device
|
||||
NTSTATUS reset_pipe_status;
|
||||
} UMSS_DEVICE_EXTENSION, *PUMSS_DEVICE_EXTENSION;
|
||||
|
||||
// for device creation workitem
|
||||
typedef struct _UMSS_CREATE_DATA
|
||||
{
|
||||
DEV_HANDLE dev_handle;
|
||||
PUCHAR desc_buf;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PUSB_DRIVER pdriver;
|
||||
|
||||
} UMSS_CREATE_DATA, *PUMSS_CREATE_DATA;
|
||||
|
||||
// for reset pipe item
|
||||
//typedef void ( _stdcall *COMPLETION_HANDLER )( PVOID );
|
||||
typedef void ( *UMSS_WORKER_ROUTINE )( PVOID );
|
||||
|
||||
typedef struct _UMSS_WORKER_PACKET
|
||||
{
|
||||
UMSS_WORKER_ROUTINE completion;
|
||||
PVOID context;
|
||||
PUSB_DEV_MANAGER dev_mgr;
|
||||
PVOID pdev;
|
||||
|
||||
} UMSS_WORKER_PACKET, *PUMSS_WORKER_PACKET;
|
||||
|
||||
BOOLEAN
|
||||
umss_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
umss_if_driver_init(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
umss_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
#define umss_if_driver_destroy umss_driver_destroy
|
||||
|
||||
BOOLEAN
|
||||
umss_if_driver_destroy(
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
PUSB_DRIVER pdriver
|
||||
);
|
||||
|
||||
VOID
|
||||
umss_complete_request(
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
NTSTATUS status
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
umss_reset_pipe(
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
DEV_HANDLE endp_handle
|
||||
);
|
||||
|
||||
PVOID
|
||||
umss_get_buffer(
|
||||
PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
ULONG* buf_length
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
umss_bulk_transfer(
|
||||
IN PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
IN UCHAR trans_dir,
|
||||
IN PVOID buf,
|
||||
IN ULONG buf_length,
|
||||
IN PURBCOMPLETION completion
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
umss_schedule_workitem(
|
||||
PVOID context,
|
||||
UMSS_WORKER_ROUTINE completion,
|
||||
PUSB_DEV_MANAGER dev_mgr,
|
||||
DEV_HANDLE dev_handle
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
umss_bulkonly_startio(
|
||||
IN PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
IN PIO_PACKET io_packet
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
umss_cbi_startio(
|
||||
IN PUMSS_DEVICE_EXTENSION pdev_ext,
|
||||
IN PIO_PACKET io_packet
|
||||
);
|
||||
|
||||
#define UMSS_FORGE_GOOD_SENSE( sense_BUF ) \
|
||||
{\
|
||||
int i;\
|
||||
PUCHAR buf = ( PUCHAR )( sense_BUF ); \
|
||||
for( i = 0; i < 18; i++)\
|
||||
{\
|
||||
buf[i] = 0;\
|
||||
}\
|
||||
buf[7] = 10;\
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,31 +0,0 @@
|
|||
//#define NTDDI_VERSION NTDDI_WIN2K
|
||||
//#define _WIN32_WINNT _WIN32_WINNT_WIN2K
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// NT4 DDK-compatibility
|
||||
#ifndef RTL_CONSTANT_STRING
|
||||
# define RTL_CONSTANT_STRING(s) { sizeof( s ) - sizeof( (s)[0] ), sizeof( s ), s }
|
||||
#endif
|
||||
|
||||
#ifndef OBJ_KERNEL_HANDLE
|
||||
# define OBJ_KERNEL_HANDLE 0x00000200L
|
||||
#endif
|
||||
|
||||
#ifndef FILE_DEVICE_SECURE_OPEN
|
||||
# define FILE_DEVICE_SECURE_OPEN 0x00000100
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "usb.h"
|
||||
#include "hcd.h"
|
||||
#include "td.h"
|
||||
#include "irplist.h"
|
||||
#include "events.h"
|
||||
#include "devmgr.h"
|
||||
#include "hub.h"
|
||||
#include "umss.h"
|
||||
#include "mouse.h"
|
||||
#include "keyboard.h"
|
||||
#include "uhciver.h"
|
|
@ -1,45 +0,0 @@
|
|||
// Resource script for USBISO driver
|
||||
// Generated by Walt Oney's driver wizard
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,0,1,0
|
||||
PRODUCTVERSION 0,0,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "This is a beta version of usb driver stack( ehci ), contact me at mypublic99@yahoo.com\0"
|
||||
VALUE "CompanyName", "Woodhead Software\0"
|
||||
VALUE "FileDescription", "usbdriver.sys\0"
|
||||
VALUE "FileVersion", "0, 0, 1, 0\0"
|
||||
VALUE "InternalName", "usbdriver.sys\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2002-2004 Woodhead Software\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "usbdriver.sys\0"
|
||||
VALUE "PrivateBuild", "0.01\0"
|
||||
VALUE "ProductName", "usb driver stack for windows NT\0"
|
||||
VALUE "ProductVersion", "0, 0, 1, 0\0"
|
||||
VALUE "SpecialBuild", "0131.d\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||
<module name="usbdrv" type="kernelmodedriver" installbase="system32/drivers" installname="usbdrv.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<define name="INCLUDE_EHCI" />
|
||||
<define name="_MULTI_UHCI" />
|
||||
<define name="_MULTI_EHCI" />
|
||||
<define name="_X86" />
|
||||
<include base="usbdrv">.</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<file>ehci.c</file>
|
||||
<file>ohci.c</file>
|
||||
<file>uhci.c</file>
|
||||
<file>roothub.c</file>
|
||||
<file>hub.c</file>
|
||||
<file>td.c</file>
|
||||
<file>usb.c</file>
|
||||
<file>umss.c</file>
|
||||
<file>bulkonly.c</file>
|
||||
<file>cbi.c</file>
|
||||
<file>devmgr.c</file>
|
||||
<file>dmgrdisp.c</file>
|
||||
<file>compdrv.c</file>
|
||||
<file>etd.c</file>
|
||||
<file>gendrv.c</file>
|
||||
<file>mouse.c</file>
|
||||
<file>keyboard.c</file>
|
||||
<file>usbdriver.rc</file>
|
||||
<pch>usbdriver.h</pch>
|
||||
</module>
|
Loading…
Reference in a new issue