- Terminate the NT4 USB driver

svn path=/trunk/; revision=55569
This commit is contained in:
Cameron Gutman 2012-02-12 18:34:05 +00:00
parent 98d609d403
commit 65beefbcd8
38 changed files with 0 additions and 31393 deletions

View file

@ -1,2 +0,0 @@
add_subdirectory(usbdrv)

View file

@ -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>

View file

@ -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)

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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(&param, usb_make_handle(dev_id, i, 0));
}
}
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
{
break;
}
}
usb_unlock_dev(pdev);
if (buf)
{
usb_free_mem(buf);
buf = NULL;
}
return;
}
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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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__ */

View file

@ -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;
}
//----------------------------------------------------------

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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>