mirror of
https://github.com/reactos/reactos
synced 2025-10-06 16:32:42 +02:00
Compare commits
6 Commits
taskmgr_op
...
backups/us
Author | SHA1 | Date | |
---|---|---|---|
|
23b5638e57 | ||
|
539644d05f | ||
|
8b8378a51e | ||
|
ebaf2fcb94 | ||
|
1786c4ac08 | ||
|
7a17598925 |
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "usbcommon.h"
|
||||
|
||||
NTSTATUS STDCALL
|
||||
|
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "usbcommon.h"
|
||||
|
||||
NTSTATUS STDCALL
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<module name="usbminiportcommon" type="objectlibrary">
|
||||
<module name="usbminiportcommon" type="objectlibrary" allowwarnings="true">
|
||||
<define name="__USE_W32API" />
|
||||
<include>../linux</include>
|
||||
<include base="usbport">.</include>
|
||||
|
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "usbcommon.h"
|
||||
|
||||
NTSTATUS STDCALL
|
||||
|
@@ -8,9 +8,7 @@
|
||||
* James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include "usbcommon.h"
|
||||
|
||||
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
|
||||
@@ -48,6 +46,35 @@ UsbMpGetUserBuffers(
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN STDCALL
|
||||
HciInterruptService(IN PKINTERRUPT Interrupt,
|
||||
IN OUT PVOID ServiceContext)
|
||||
{
|
||||
DPRINT1("USBMP Interrupt\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID
|
||||
UsbMpRegisterIsr(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PUSBMP_DEVICE_EXTENSION DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* Connect interrupt and enable them */
|
||||
DPRINT("IoConnectInterrupt: vec=0x%x,lev=0x%x,mode=0x%x,aff=0x%x\n", DeviceExtension->InterruptVector, DeviceExtension->InterruptLevel, DeviceExtension->InterruptMode, DeviceExtension->InterruptAffinity);
|
||||
Status = IoConnectInterrupt(
|
||||
&DeviceExtension->InterruptObject, (PKSERVICE_ROUTINE)HciInterruptService,
|
||||
DeviceObject, NULL,
|
||||
DeviceExtension->InterruptVector, DeviceExtension->InterruptLevel, DeviceExtension->InterruptLevel,
|
||||
DeviceExtension->InterruptMode, DeviceExtension->InterruptShare,
|
||||
DeviceExtension->InterruptAffinity, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("usbmp: IoConnectInterrupt() failed with status 0x%08x\n", Status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
UsbMpFdoStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
@@ -59,6 +86,8 @@ UsbMpFdoStartDevice(
|
||||
PUSBMP_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
ULONG Size;
|
||||
USHORT FunctionNum, DeviceNum;
|
||||
ULONG propAddress;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (DeviceObject == KeyboardFdo || DeviceObject == MouseFdo)
|
||||
@@ -74,7 +103,7 @@ UsbMpFdoStartDevice(
|
||||
/*
|
||||
* Store some resources in the DeviceExtension.
|
||||
*/
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResourcesTranslated;
|
||||
if (AllocatedResources != NULL)
|
||||
{
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
|
||||
@@ -116,6 +145,14 @@ UsbMpFdoStartDevice(
|
||||
{
|
||||
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
|
||||
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
|
||||
DeviceExtension->InterruptAffinity = Descriptor->u.Interrupt.Affinity;
|
||||
if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
|
||||
DeviceExtension->InterruptMode = Latched;
|
||||
else
|
||||
DeviceExtension->InterruptMode = LevelSensitive;
|
||||
|
||||
DeviceExtension->InterruptShare = (Descriptor->ShareDisposition == CmResourceShareShared);
|
||||
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypePort)
|
||||
{
|
||||
@@ -144,6 +181,11 @@ UsbMpFdoStartDevice(
|
||||
DeviceExtension->BaseAddress,
|
||||
DeviceExtension->BaseAddrLength);
|
||||
|
||||
/* Register Interrupt Service Routine */
|
||||
UsbMpRegisterIsr(DeviceObject);
|
||||
|
||||
/* Acquire some information about the placement of the controller in the bus */
|
||||
|
||||
/* Get bus number from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
Status = IoGetDeviceProperty(
|
||||
@@ -161,6 +203,30 @@ UsbMpFdoStartDevice(
|
||||
|
||||
DPRINT("USBMP: Busnumber %d\n", DeviceExtension->SystemIoBusNumber);
|
||||
|
||||
/* Get bus device address from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
IoGetDeviceProperty(
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
DevicePropertyAddress,
|
||||
Size,
|
||||
&propAddress,
|
||||
&Size);
|
||||
|
||||
DeviceExtension->SystemIoSlotNumber.u.AsULONG = 0;
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("USBMP: IoGetDeviceProperty DevicePropertyAddress failed\n");
|
||||
}
|
||||
|
||||
FunctionNum = (USHORT)((propAddress) & 0x0000FFFF);
|
||||
DeviceNum = (USHORT)(((propAddress) >> 16) & 0x0000FFFF);
|
||||
|
||||
DeviceExtension->SystemIoSlotNumber.u.bits.DeviceNumber = DeviceNum;
|
||||
DeviceExtension->SystemIoSlotNumber.u.bits.FunctionNumber = FunctionNum;
|
||||
|
||||
DPRINT("USBMP: Slotnumber 0x%x, Device: 0x%x, Func: 0x%x\n", DeviceExtension->SystemIoSlotNumber.u.AsULONG, DeviceNum, FunctionNum);
|
||||
|
||||
/* Init wrapper with this object */
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
}
|
||||
|
@@ -12,8 +12,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define INITGUID
|
||||
#include "usbcommon.h"
|
||||
|
||||
@@ -197,8 +195,7 @@ AddDevice(
|
||||
UNICODE_STRING LinkDeviceName;
|
||||
PUSBMP_DRIVER_EXTENSION DriverExtension;
|
||||
PUSBMP_DEVICE_EXTENSION DeviceExtension;
|
||||
static ULONG DeviceNumber = 0;
|
||||
BOOL AlreadyRestarted = FALSE;
|
||||
ULONG DeviceNumber;
|
||||
|
||||
// Allocate driver extension now
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
@@ -217,33 +214,18 @@ AddDevice(
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a unicode device name. Allocate a new device number every time */
|
||||
do
|
||||
{
|
||||
DeviceNumber++;
|
||||
if (DeviceNumber == 9999)
|
||||
{
|
||||
/* Hmm. We don't have a free number. */
|
||||
if (AlreadyRestarted)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
/* Start again at DeviceNumber = 0 to find a free number */
|
||||
DeviceNumber = 0;
|
||||
AlreadyRestarted = TRUE;
|
||||
}
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
// Create a unicode device name
|
||||
DeviceNumber = 0; //TODO: Allocate new device number every time
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(USBMP_DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_BUS_EXTENDER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
} while (Status == STATUS_OBJECT_NAME_COLLISION);
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(USBMP_DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_BUS_EXTENDER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -414,19 +396,19 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
USBPORT_INTERFACE UsbPortInterface;
|
||||
ULONG i;
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)AddDevice;
|
||||
|
||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
DriverObject->MajorFunction[i] = IrpStub;
|
||||
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)IrpStub;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)DispatchCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)DispatchClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)DispatchCleanup;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchInternalDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH)DispatchPower;
|
||||
|
||||
// Register in usbcore.sys
|
||||
UsbPortInterface.KbdConnectData = &KbdClassInformation;
|
||||
|
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "usbcommon.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -39,7 +37,7 @@ ForwardIrpAndWait(
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
DPRINT("USBMP: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
|
||||
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
Status = IoCallDriver(LowerDevice, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
|
@@ -9,8 +9,6 @@
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "usbcommon.h"
|
||||
|
||||
extern struct usb_driver hub_driver;
|
||||
@@ -87,7 +85,8 @@ UsbMpPdoQueryId(
|
||||
DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
RtlInitUnicodeString(&String, NULL);
|
||||
DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceExtension->FunctionalDeviceObject->DeviceExtension;
|
||||
roothub = ((struct usb_hcd*)DeviceExtension->pdev->data)->self.root_hub;
|
||||
//roothub = ((struct usb_hcd*)DeviceExtension->pdev->data)->self.root_hub;
|
||||
roothub = hcd_to_bus(DeviceExtension->pdev->data)->root_hub;
|
||||
|
||||
switch (IdType)
|
||||
{
|
||||
@@ -297,7 +296,7 @@ UsbMpPnpPdo(
|
||||
|
||||
DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
|
||||
|
||||
Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &SourceString, &Description);
|
||||
Status = _RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &SourceString, &Description);
|
||||
if (NT_SUCCESS(Status))
|
||||
Information = (ULONG_PTR)Description.Buffer;
|
||||
break;
|
||||
|
@@ -12,6 +12,10 @@
|
||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||
#define USB_MINIPORT_TAG TAG('u','s','b','m')
|
||||
|
||||
#ifndef RTL_CONSTANT_STRING
|
||||
#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), s }
|
||||
#endif
|
||||
|
||||
#include "../../usbport/hcd.h"
|
||||
#include "usbcommon_types.h"
|
||||
|
||||
|
@@ -6,7 +6,7 @@ typedef struct _USBMP_DRIVER_EXTENSION
|
||||
//OHCI_HW_INITIALIZATION_DATA InitializationData;
|
||||
//PVOID HwContext;
|
||||
//UNICODE_STRING RegistryPath;
|
||||
|
||||
void *dummy;
|
||||
} USBMP_DRIVER_EXTENSION, *PUSBMP_DRIVER_EXTENSION;
|
||||
|
||||
typedef struct _USBMP_DEVICE_EXTENSTION
|
||||
@@ -33,7 +33,7 @@ typedef struct _USBMP_DEVICE_EXTENSTION
|
||||
ULONG Flags;
|
||||
//ULONG AdapterInterfaceType;
|
||||
ULONG SystemIoBusNumber;
|
||||
ULONG SystemIoSlotNumber;
|
||||
PCI_SLOT_NUMBER SystemIoSlotNumber;
|
||||
//LIST_ENTRY AddressMappingListHead;
|
||||
|
||||
// DMA stuff, and buffers
|
||||
|
@@ -6,10 +6,10 @@
|
||||
</directory>
|
||||
<!--directory name="usbehci">
|
||||
<xi:include href="usbehci/usbehci.xml" />
|
||||
</directory-->
|
||||
</directory
|
||||
<directory name="usbohci">
|
||||
<xi:include href="usbohci/usbohci.xml" />
|
||||
</directory>
|
||||
</directory>-->
|
||||
<directory name="usbuhci">
|
||||
<xi:include href="usbuhci/usbuhci.xml" />
|
||||
</directory>
|
||||
|
@@ -33,12 +33,18 @@
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
static __inline void set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
InterlockedBitTestAndSet(addr, nr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler!
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,12 +56,18 @@ static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __set_bit(int nr, volatile void * addr)
|
||||
static __inline void __set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__(
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
set_bit(nr, addr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,12 +80,22 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
|
||||
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
|
||||
* in order to ensure changes are visible on other processors.
|
||||
*/
|
||||
static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
static __inline void clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
lock btr [ecx], eax
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
@@ -87,12 +109,22 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __change_bit(int nr, volatile void * addr)
|
||||
static __inline void __change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__(
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
btc [ecx], eax
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,12 +136,22 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void change_bit(int nr, volatile void * addr)
|
||||
static __inline void change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
lock btc [ecx], eax
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,15 +162,22 @@ static __inline__ void change_bit(int nr, volatile void * addr)
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
|
||||
static __inline int test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
return InterlockedBitTestAndSet(addr, nr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,8 +189,9 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
static __inline int __test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
@@ -149,6 +199,11 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
return test_and_set_bit(nr, addr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,8 +214,9 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
static __inline int test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
@@ -168,6 +224,11 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
return InterlockedBitTestAndReset(addr, nr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,8 +240,9 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
static __inline int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
@@ -188,11 +250,18 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
test_and_clear_bit(nr, addr);
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef THIS_IS_NOT_USED
|
||||
/* WARNING: non atomic and it can be reordered! */
|
||||
static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
static __inline int __test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
@@ -200,6 +269,16 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
btc [ecx], eax
|
||||
setc al
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,8 +289,9 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
static __inline int test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
@@ -219,8 +299,20 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
btc [ecx], eax
|
||||
setc al
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* THIS_IS_NOT_USED */
|
||||
|
||||
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
@@ -230,26 +322,42 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
static int test_bit(int nr, const volatile void * addr);
|
||||
#endif
|
||||
|
||||
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
static __inline int constant_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
static __inline int variable_test_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__asm__ __volatile__(
|
||||
"btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit)
|
||||
:"m" (ADDR),"Ir" (nr));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm {
|
||||
mov eax, nr
|
||||
mov ecx, addr
|
||||
bt [ecx], eax
|
||||
setc al
|
||||
//mov oldbit, al
|
||||
};
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/*
|
||||
#define test_bit(nr,addr) \
|
||||
(__builtin_constant_p(nr) ? \
|
||||
constant_test_bit((nr),(addr)) : \
|
||||
variable_test_bit((nr),(addr)))
|
||||
*/
|
||||
#define test_bit(nr,addr) \
|
||||
( variable_test_bit( (nr),(addr) ) )
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
@@ -259,7 +367,8 @@ static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
#if defined(__GNUC__)
|
||||
static __inline int find_first_zero_bit(void * addr, unsigned size)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
int res;
|
||||
@@ -282,6 +391,34 @@ static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
|
||||
return res;
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
#define find_first_zero_bit(addr, size) \
|
||||
find_next_zero_bit((addr), (size), 0)
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static __inline unsigned long ffz(unsigned long word)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (word)
|
||||
:"r" (~word));
|
||||
return word;
|
||||
#elif defined(_MSC_VER)
|
||||
ULONG index;
|
||||
BitScanForward(&index, ~word);
|
||||
return index;
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the first zero bit in a memory region
|
||||
@@ -289,7 +426,8 @@ static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
|
||||
#if defined(__GNUC__)
|
||||
static __inline int find_next_zero_bit (void * addr, int size, int offset)
|
||||
{
|
||||
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
|
||||
int set = 0, bit = offset & 31, res;
|
||||
@@ -315,20 +453,47 @@ static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
|
||||
res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
|
||||
return (offset + set + res);
|
||||
}
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static __inline__ unsigned long ffz(unsigned long word)
|
||||
#elif defined(_MSC_VER)
|
||||
static __inline unsigned long find_next_zero_bit(const void *addr, unsigned long size, unsigned long offset)
|
||||
{
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (word)
|
||||
:"r" (~word));
|
||||
return word;
|
||||
const unsigned long *p = addr;
|
||||
unsigned long result = offset & ~63UL;
|
||||
unsigned long tmp;
|
||||
|
||||
p += offset >> 6;
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset &= 63UL;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp |= ~0UL >> (64-offset);
|
||||
if (size < 64)
|
||||
goto found_first;
|
||||
if (~tmp)
|
||||
goto found_middle;
|
||||
size -= 64;
|
||||
result += 64;
|
||||
}
|
||||
while (size & ~63UL) {
|
||||
if (~(tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += 64;
|
||||
size -= 64;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
tmp = *p;
|
||||
found_first:
|
||||
tmp |= ~0UL << size;
|
||||
if (tmp == ~0UL) /* Are any bits zero? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + ffz(tmp);
|
||||
}
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
@@ -1,6 +1,27 @@
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#define _LINUX_BITOPS_H
|
||||
|
||||
/**
|
||||
* __ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static __inline unsigned long __ffs(unsigned long wrd)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (wrd)
|
||||
:"rm" (wrd));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, wrd;
|
||||
__asm bsf eax, eax;
|
||||
__asm mov wrd, eax;
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
return wrd;
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs: find first bit set. This is defined the same way as
|
||||
@@ -8,7 +29,7 @@
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
|
||||
static inline int generic_ffs(int x)
|
||||
static __inline int generic_ffs(int x)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
@@ -42,7 +63,7 @@ static inline int generic_ffs(int x)
|
||||
* of bits set) of a N-bit word
|
||||
*/
|
||||
|
||||
static inline unsigned int generic_hweight32(unsigned int w)
|
||||
static __inline unsigned int generic_hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||
@@ -51,7 +72,7 @@ static inline unsigned int generic_hweight32(unsigned int w)
|
||||
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight16(unsigned int w)
|
||||
static __inline unsigned int generic_hweight16(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
|
||||
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||
@@ -59,7 +80,7 @@ static inline unsigned int generic_hweight16(unsigned int w)
|
||||
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight8(unsigned int w)
|
||||
static __inline unsigned int generic_hweight8(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
|
||||
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||
|
@@ -5,9 +5,25 @@
|
||||
// some typedefs to make for easy sizing
|
||||
|
||||
//typedef unsigned long ULONG;
|
||||
typedef long long u64;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
typedef unsigned int __u32;
|
||||
typedef unsigned short __u16;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
// we don't care much about big-endian
|
||||
typedef unsigned int __le32;
|
||||
typedef unsigned short __le16;
|
||||
typedef unsigned char __le8;
|
||||
|
||||
|
||||
typedef short s16;
|
||||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
#ifndef bool_already_defined_
|
||||
typedef int bool;
|
||||
#endif
|
||||
@@ -24,4 +40,9 @@ typedef unsigned long RGBA; // LSB=R -> MSB = A
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#define __iomem
|
||||
#define __user
|
||||
|
||||
typedef u32 uid_t;
|
||||
|
||||
#endif /* #ifndef cromwell_types_h */
|
||||
|
@@ -11,6 +11,7 @@
|
||||
* macros
|
||||
*
|
||||
* All structs and prototypes are based on kernel source 2.5.72
|
||||
* 2.6.14.3
|
||||
*
|
||||
* Modified by Aleksey Bragin (aleksey@reactos.com) for ReactOS needs
|
||||
*
|
||||
@@ -23,17 +24,6 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
#include "cromwell_types.h"
|
||||
|
||||
typedef unsigned int __u32;
|
||||
//typedef __u32 u32;
|
||||
typedef unsigned short __u16;
|
||||
//typedef __u16 u16;
|
||||
typedef unsigned char __u8;
|
||||
//typedef __u8 u8;
|
||||
|
||||
typedef short s16;
|
||||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
KSPIN_LOCK SpinLock;
|
||||
@@ -58,8 +48,9 @@ typedef int ssize_t;
|
||||
#endif
|
||||
typedef int irqreturn_t;
|
||||
typedef unsigned long kernel_ulong_t;
|
||||
typedef unsigned long gfp_t;
|
||||
|
||||
typedef int wait_queue_head_t;
|
||||
typedef KEVENT wait_queue_head_t;
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Stuff from xbox/linux environment */
|
||||
/*------------------------------------------------------------------------*/
|
||||
@@ -93,7 +84,7 @@ extern size_t strlen(const char *);
|
||||
extern int memcmp(const void *,const void *,unsigned int);
|
||||
|
||||
#else
|
||||
#include "boot.h"
|
||||
//#include "boot.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
#else
|
||||
@@ -109,6 +100,9 @@ extern int memcmp(const void *,const void *,unsigned int);
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
struct timer_list {
|
||||
PKTIMER kTimer;
|
||||
PKDPC kDPC;
|
||||
// usual stuff
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
int expires;
|
||||
@@ -137,17 +131,25 @@ struct semaphore{int a;};
|
||||
struct device_driver{
|
||||
char *name;
|
||||
struct bus_type *bus;
|
||||
int owner;
|
||||
int (*probe) (struct device * dev);
|
||||
int (*remove) (struct device * dev);
|
||||
struct list_head devices;
|
||||
};
|
||||
|
||||
typedef struct pm_message {
|
||||
int event;
|
||||
} pm_message_t;
|
||||
|
||||
struct bus_type {
|
||||
char * name;
|
||||
int (*match)(struct device * dev, struct device_driver * drv);
|
||||
struct device * (*add) (struct device * parent, char * bus_id);
|
||||
int (*hotplug) (struct device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size);
|
||||
struct device * (*add) (struct device * parent, char * bus_id);
|
||||
int (*hotplug) (struct device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size);
|
||||
int (*suspend)(struct device * dev, pm_message_t state);
|
||||
int (*resume)(struct device * dev);
|
||||
|
||||
};
|
||||
|
||||
struct dummy_process
|
||||
@@ -168,9 +170,9 @@ struct completion {
|
||||
// windows lookaside list head
|
||||
typedef void* kmem_cache_t;
|
||||
|
||||
struct dma_pool
|
||||
{
|
||||
int dummy;
|
||||
// misc stuff
|
||||
struct kref {
|
||||
atomic_t refcount;
|
||||
};
|
||||
|
||||
/* These definitions mirror those in pci.h, so they can be used
|
||||
@@ -233,7 +235,17 @@ struct usb_device_id {
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* PCI structs (taken from linux/pci.h et al., but slightly modified) */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
typedef int pci_power_t;
|
||||
|
||||
#define PCI_D0 ((pci_power_t) 0)
|
||||
#define PCI_D1 ((pci_power_t) 1)
|
||||
#define PCI_D2 ((pci_power_t) 2)
|
||||
#define PCI_D3hot ((pci_power_t) 3)
|
||||
#define PCI_D3cold ((pci_power_t) 4)
|
||||
#define PCI_UNKNOWN ((pci_power_t) 5)
|
||||
#define PCI_POWER_ERROR ((pci_power_t) -1)
|
||||
|
||||
struct pci_dev {
|
||||
int vendor;
|
||||
@@ -241,6 +253,9 @@ struct pci_dev {
|
||||
struct pci_bus *bus;
|
||||
int irq;
|
||||
char *slot_name;
|
||||
pci_power_t current_state; /* Current operating state. In ACPI-speak,
|
||||
this is D0-D3, D0 being fully functional,
|
||||
and D3 being off. */
|
||||
struct device dev;
|
||||
int base[4];
|
||||
int flags[4];
|
||||
@@ -263,12 +278,13 @@ struct pci_driver {
|
||||
struct list_head node;
|
||||
char *name;
|
||||
const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
|
||||
int STDCALL (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
|
||||
void STDCALL (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
|
||||
int (STDCALL *probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
|
||||
void (STDCALL *remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
|
||||
int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */
|
||||
int (*suspend) (struct pci_dev *dev, u32 state); /* Device suspended */
|
||||
int (*resume) (struct pci_dev *dev); /* Device woken up */
|
||||
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */
|
||||
void (*shutdown) (struct pci_dev *dev);
|
||||
};
|
||||
|
||||
struct scatterlist
|
||||
@@ -300,7 +316,7 @@ struct usbdevfs_hub_portinfo
|
||||
#define SLAB_ATOMIC 0
|
||||
#define PCI_ANY_ID (~0)
|
||||
#define SIGKILL 9
|
||||
#define THIS_MODULE 0
|
||||
#define THIS_MODULE NULL
|
||||
//#define PAGE_SIZE 4096
|
||||
|
||||
|
||||
@@ -335,6 +351,7 @@ struct usbdevfs_hub_portinfo
|
||||
#define __devinitdata
|
||||
#define module_init(x) static void module_init_##x(void){ x();}
|
||||
#define module_exit(x) void module_exit_##x(void){ x();}
|
||||
#define module_param(a,b,c) //
|
||||
#define EXPORT_SYMBOL_GPL(x)
|
||||
#define EXPORT_SYMBOL(x)
|
||||
|
||||
@@ -344,7 +361,6 @@ struct usbdevfs_hub_portinfo
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Access macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define dev_get_drvdata(a) (a)->driver_data
|
||||
#define dev_set_drvdata(a,b) (a)->driver_data=(b)
|
||||
|
||||
@@ -356,38 +372,96 @@ struct usbdevfs_hub_portinfo
|
||||
#define prefetch(x) 1
|
||||
|
||||
#define inw(x) READ_PORT_USHORT((PUSHORT)(x))
|
||||
|
||||
#define outb(x,p) WRITE_PORT_UCHAR((PUCHAR)(p),(x))
|
||||
#define outw(x,p) WRITE_PORT_USHORT((PUSHORT)(p),(x))
|
||||
#define outl(x,p) WRITE_PORT_ULONG((PULONG)(p),(x))
|
||||
|
||||
/* The kernel macro for list_for_each_entry makes nonsense (have no clue
|
||||
* why, this is just the same definition...) */
|
||||
|
||||
#undef list_for_each_entry
|
||||
/*#undef list_for_each_entry
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
prefetch(pos->member.next))*/
|
||||
#define list_for_each_entry_safe(pos, type, n, typen, head, member) \
|
||||
for (pos = list_entry((head)->next, type, member), \
|
||||
n = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typen, member))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Misc stuff (to be categorized later) */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
|
||||
static __inline long IS_ERR(const void *ptr)
|
||||
{
|
||||
return (long)IS_ERR_VALUE((unsigned long)ptr);
|
||||
}
|
||||
|
||||
|
||||
#define usbdev_add(x) do {} while(0)
|
||||
#define usbdev_remove(x) do {} while(0)
|
||||
#define usb_remove_sysfs_dev_files(x) do {} while(0)
|
||||
#define usb_create_sysfs_dev_files(x) do {} while(0)
|
||||
#define usbdev_init(x) 0
|
||||
#define usbdev_cleanup(x) do {} while(0)
|
||||
#define debugfs_remove(x) do {} while(0)
|
||||
|
||||
#define __acquires(x)
|
||||
#define __releases(x)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* function wrapper macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define kmalloc(x,y) ExAllocatePool(PagedPool,x)
|
||||
#define kmalloc(x,y) ExAllocatePool(NonPagedPool,x)
|
||||
#define kfree(x) ExFreePool(x)
|
||||
#define kzalloc(x, y) my_kzalloc(x)
|
||||
void *my_kzalloc(size_t size/*, gfp_t flags*/);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
int memcmp(const void * cs,const void * ct,size_t count);
|
||||
#else
|
||||
int __cdecl memcmp(const void * cs,const void * ct,size_t count);
|
||||
#endif
|
||||
|
||||
// kernel reference counting
|
||||
#define kref_init(a) do {} while(0)
|
||||
#define kref_get(a) do {} while(0)
|
||||
#define kref_put(a, b) my_kref_put(a, b)
|
||||
|
||||
static int __inline my_kref_put(struct kref *kref, void (*release) (struct kref *kref))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//#define sprintf(a,b,format, arg...) zxsprintf((a),(b),format, ## arg)
|
||||
//#define snprintf(a,b,format, arg...) zxsnprintf((a),(b),format, ##arg)
|
||||
//#define printk(format, arg...) zxprintf(format, ## arg)
|
||||
#define snprintf(a,b,format, arg...) _snprintf((a),(b),format, ##arg)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf(...) _snprintf(__VA_ARGS__)
|
||||
#define printk(format,...) DPRINT1(format, __VA_ARGS__)
|
||||
#else
|
||||
#define snprintf(a,b,format, arg...) _snprintf((a),(b),format, ## arg)
|
||||
#define printk(format, arg...) DPRINT1(format, ## arg)
|
||||
#endif
|
||||
|
||||
#define BUG(...) do {} while(0)
|
||||
|
||||
size_t strlcpy(char *dest, const char *src, size_t size);
|
||||
|
||||
/* Locks & friends */
|
||||
|
||||
#define DECLARE_MUTEX(x) struct semaphore x
|
||||
#define init_MUTEX(x)
|
||||
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x
|
||||
|
||||
#define SPIN_LOCK_UNLOCKED 0
|
||||
|
||||
#define spin_lock_init(a) my_spin_lock_init(a)
|
||||
@@ -401,16 +475,25 @@ void my_spin_unlock(spinlock_t *sl);
|
||||
|
||||
#define spin_lock_irqsave(a,b) b=0, my_spin_lock_irqsave(a,b)
|
||||
void my_spin_lock_irqsave(spinlock_t *sl, int flags);
|
||||
#define spin_unlock_irqrestore(a,b) my_spin_unlock(a)
|
||||
#define spin_unlock_irqrestore(a,b) my_spin_unlock_irqrestore(a,b)
|
||||
void my_spin_unlock_irqrestore(spinlock_t *sl, int flags);
|
||||
|
||||
#define spin_lock_irq(x) my_spin_lock_irq(x)
|
||||
void my_spin_lock_irq(spinlock_t *sl);
|
||||
#define spin_unlock_irq(x) my_spin_unlock_irq(x)
|
||||
void my_spin_unlock_irq(spinlock_t *sl);
|
||||
|
||||
#if 0
|
||||
#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
|
||||
#define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
|
||||
#else
|
||||
#define local_irq_save(x) do {} while(0)
|
||||
#define local_irq_restore(x) do {} while(0)
|
||||
static void __inline local_irq_save(unsigned long flags) {}
|
||||
static void __inline local_irq_restore(unsigned long flags) {}
|
||||
#endif
|
||||
|
||||
#define local_irq_enable() do {} while(0)
|
||||
#define local_irq_disable() do {} while(0)
|
||||
|
||||
#define atomic_inc(x) *(x)+=1
|
||||
#define atomic_dec(x) *(x)-=1
|
||||
#define atomic_dec_and_test(x) (*(x)-=1,(*(x))==0)
|
||||
@@ -421,11 +504,15 @@ void my_spin_lock_irqsave(spinlock_t *sl, int flags);
|
||||
#define down(x) do {} while(0)
|
||||
#define up(x) do {} while(0)
|
||||
#define down_trylock(a) 0
|
||||
#define down_read_trylock(a) TRUE
|
||||
|
||||
#define down_read(a) do {} while(0)
|
||||
#define up_read(a) do {} while(0)
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(x) KEVENT x
|
||||
#define down_write(a) do {} while(0)
|
||||
#define up_write(a) do {} while(0)
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(x) wait_queue_head_t x // YOU MUST INITIALIZE ALL GLOBAL VARIABLES OF THIS TYPE!
|
||||
|
||||
#define DECLARE_COMPLETION(x) struct completion x
|
||||
|
||||
@@ -462,10 +549,13 @@ struct pci_pool
|
||||
struct pci_page pages[MAX_POOL_PAGES];
|
||||
};
|
||||
|
||||
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
|
||||
#define dma_pool pci_pool
|
||||
|
||||
//#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
|
||||
#define to_pci_dev(n) CONTAINING_RECORD(n, struct pci_dev, dev)
|
||||
|
||||
#define pci_pool_create(a,b,c,d,e) my_pci_pool_create(a,b,c,d,e)
|
||||
struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, size_t size, size_t align, size_t allocation);
|
||||
struct pci_pool *my_pci_pool_create(const char * name, struct device * pdev, size_t size, size_t align, size_t allocation);
|
||||
|
||||
#define pci_pool_alloc(a,b,c) my_pci_pool_alloc(a,b,c)
|
||||
void *my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_handle);
|
||||
@@ -485,11 +575,18 @@ int my_pci_module_init(struct pci_driver *x);
|
||||
|
||||
#define pci_unregister_driver(a) do {} while(0)
|
||||
|
||||
#define pci_write_config_word(a,b,c) my_pci_write_config_word(a,b,c)
|
||||
#define pci_read_config_word(a,b,c) my_pci_read_config_word(a,b,c)
|
||||
int my_pci_read_config_word(struct pci_dev *, int, u16*);
|
||||
|
||||
#define bus_register(a) do {} while(0)
|
||||
#define pci_write_config_word(a,b,c) my_pci_write_config_word(a,b,c)
|
||||
int my_pci_write_config_word(struct pci_dev *, int, u16);
|
||||
|
||||
|
||||
#define bus_register(a) 0
|
||||
#define bus_unregister(a) do {} while(0)
|
||||
|
||||
static __inline char *pci_name(struct pci_dev *pdev) { return pdev->dev.bus_id; };
|
||||
|
||||
/* DMA */
|
||||
//#define dma_pool_alloc(a,b,c) my_dma_pool_alloc((a),(b),(c))
|
||||
#define dma_pool_alloc(a,b,c) pci_pool_alloc(a,b,c)
|
||||
@@ -497,8 +594,10 @@ int my_pci_module_init(struct pci_driver *x);
|
||||
#define dma_pool_free(a,b,c) pci_pool_free(a,b,c)
|
||||
#define dma_pool_destroy(a) pci_pool_destroy(a)
|
||||
|
||||
//#define dma_alloc_coherent(a,b,c,d) NULL
|
||||
//#define dma_free_coherent(a,b,c,d) do {} while(0)
|
||||
#define dma_alloc_coherent(dev,sz,dma_handle,gfp) my_dma_alloc_coherent(dev, sz, dma_handle, gfp)
|
||||
void *my_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag);
|
||||
#define dma_free_coherent(dev,sz,vaddr,dma_handle) DPRINT1("dma_free_coherent UNIMPLEMENTED!\n");
|
||||
|
||||
#define dma_map_single(a,b,c,d) my_dma_map_single(a,b,c,d)
|
||||
dma_addr_t my_dma_map_single(struct device *hwdev, void *ptr, size_t size, enum dma_data_direction direction);
|
||||
|
||||
@@ -522,10 +621,13 @@ void my_dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, en
|
||||
|
||||
#define usb_create_driverfs_dev_files(a) do {} while(0)
|
||||
#define usb_create_driverfs_intf_files(a) do {} while(0)
|
||||
#define usb_create_sysfs_intf_files(a) do {} while(0)
|
||||
#define usb_remove_sysfs_intf_files(a) do {} while(0)
|
||||
|
||||
#define sg_dma_address(x) ((u32)((x)->page*4096 + (x)->offset))
|
||||
#define sg_dma_len(x) ((x)->length)
|
||||
|
||||
#define page_address(x) ((void*)(x/4096))
|
||||
#define page_address(x) ((u8 *)(x/4096))
|
||||
|
||||
#define PCI_ROM_RESOURCE 1
|
||||
#define IORESOURCE_IO CM_RESOURCE_PORT_IO
|
||||
@@ -540,7 +642,10 @@ VOID KeMemoryBarrier(VOID);
|
||||
|
||||
#define mb() KeMemoryBarrier()
|
||||
#define wmb() do {} while (0)
|
||||
#define smp_wmb() do {} while (0)
|
||||
#define rmb() do {} while (0)
|
||||
#define smp_rmb() do {} while (0)
|
||||
#define barrier() KeMemoryBarrier() //FIXME: Is this right?
|
||||
/*#define wmb() __asm__ __volatile__ ("": : :"memory")
|
||||
#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")*/
|
||||
|
||||
@@ -562,6 +667,7 @@ void my_wait_for_completion(struct completion*);
|
||||
#define daemonize(a) do {} while(0)
|
||||
#define allow_signal(a) do {} while(0)
|
||||
#define wait_event_interruptible(x,y) do {} while(0)
|
||||
#define wait_event(x,y) do {} while(0)
|
||||
|
||||
#define interruptible_sleep_on(a) my_interruptible_sleep_on(a)
|
||||
void my_interruptible_sleep_on(PKEVENT evnt);
|
||||
@@ -606,16 +712,28 @@ void my_kmem_cache_free(kmem_cache_t *co, void *ptr);
|
||||
#define UTS_RELEASE "----"
|
||||
|
||||
/* from linux/kernel.h */
|
||||
#if defined(__GNUC__)
|
||||
#define max_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
|
||||
#else
|
||||
#define max_t(type,x,y) \
|
||||
( ((type)(x) > (type)(y)) ? (type)(x): (type)(y) )
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define min_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
|
||||
#else
|
||||
#define min_t(type,x,y) \
|
||||
( ((type)(x) < (type)(y)) ? (type)(x): (type)(y) )
|
||||
#endif
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
//#define container_of(ptr, type, member) CONTAINING_RECORD(ptr, type, member)
|
||||
|
||||
/* from linux/stddef.h */
|
||||
|
||||
#undef offsetof
|
||||
@@ -626,6 +744,7 @@ void my_kmem_cache_free(kmem_cache_t *co, void *ptr);
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define __constant_cpu_to_le32(x) (x)
|
||||
#define __constant_cpu_to_le16(x) (__le16)(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
@@ -635,17 +754,29 @@ void my_kmem_cache_free(kmem_cache_t *co, void *ptr);
|
||||
#define le16_to_cpus(x) do {} while (0)
|
||||
#define le16_to_cpup(x) (*(__u16*)(x))
|
||||
#define cpu_to_le16p(x) (*(__u16*)(x))
|
||||
#define cpu_to_le16s(x) // nothing here
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Debug output */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#ifdef DEBUG_MODE
|
||||
#if defined(_MSC_VER)
|
||||
#define dev_printk(lvl,x,f,...) { DPRINT(f, __VA_ARGS__); }
|
||||
#define dev_dbg(x,f,...) { DPRINT(f, __VA_ARGS__); }
|
||||
#define dev_info(x,f,...) { DPRINT1(f,__VA_ARGS__); }
|
||||
#define dev_warn(x,f,...) { DPRINT1(f,__VA_ARGS__); }
|
||||
#define dev_err(x,f,...) { DPRINT1(f,__VA_ARGS__); }
|
||||
#define pr_debug(f,...) { DPRINT(f,__VA_ARGS__); }
|
||||
#define pr_info(f,...) { DPRINT1(f,__VA_ARGS__); }
|
||||
#else
|
||||
#define dev_printk(lvl,x,f,arg...) printk(f, ## arg)
|
||||
#define dev_dbg(x,f,arg...) printk(f, ## arg)
|
||||
#define dev_info(x,f,arg...) printk(f,## arg)
|
||||
#define dev_warn(x,f,arg...) printk(f,## arg)
|
||||
#define dev_err(x,f,arg...) printk(f,## arg)
|
||||
#define pr_debug(x,f,arg...) printk(f,## arg)
|
||||
#define pr_debug(f,arg...) printk(f,## arg)
|
||||
#define pr_info(f,arg...) printk(f,## arg)
|
||||
#endif
|
||||
#define usbprintk printk
|
||||
#endif
|
||||
|
||||
@@ -655,12 +786,11 @@ void my_kmem_cache_free(kmem_cache_t *co, void *ptr);
|
||||
#define dev_info(x,f,arg...) do {} while (0)
|
||||
#define dev_warn(x,f,arg...) do {} while (0)
|
||||
#define dev_err(x,f,arg...) do {} while (0)
|
||||
#define pr_debug(x,f,arg...) do {} while (0)
|
||||
#define pr_debug(f,arg...) do {} while (0)
|
||||
#define pr_info(f,arg...) do {} while (0)
|
||||
#define usbprintk(arg...) dev_printk(0,0,0,## arg)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define PCI_DEVFN(a,b) 0
|
||||
#define PCI_SLOT(a) 0
|
||||
|
||||
@@ -704,78 +834,230 @@ extern struct list_head interrupt_list;
|
||||
void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#define my_wait_ms(x) wait_ms(x) // milliseconds
|
||||
|
||||
#define udelay(x) my_udelay(x) // microseconds
|
||||
|
||||
#define my_mdelay(x) wait_ms(1+x/1000);
|
||||
#define mdelay(x) my_mdelay(x); // milliseconds = udelay(1000*x)
|
||||
//#define my_mdelay(x) wait_ms(1+x/1000)
|
||||
#define mdelay(x) wait_ms(x) // milliseconds = udelay(1000*x)
|
||||
#define msleep(x) wait_ms(x)
|
||||
|
||||
#define pci_find_slot(a,b) my_pci_find_slot(a,b)
|
||||
struct pci_dev *my_pci_find_slot(int a,int b);
|
||||
#define pci_find_capability(a,b) FALSE
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Timer management */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_TIMERS 20
|
||||
#define MAX_TIMERS 5
|
||||
extern struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
extern PKDEFERRED_ROUTINE timer_dpcs[MAX_TIMERS];
|
||||
|
||||
static void __inline__ init_timer(struct timer_list* t)
|
||||
void STDCALL _TimerDpc0(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
void STDCALL _TimerDpc1(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
void STDCALL _TimerDpc2(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
void STDCALL _TimerDpc3(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
void STDCALL _TimerDpc4(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
|
||||
static __inline unsigned int jiffies_to_msecs(const unsigned long j);
|
||||
static __inline unsigned long msecs_to_jiffies(const unsigned int m);
|
||||
|
||||
static void __inline init_timer(struct timer_list* t)
|
||||
{
|
||||
INIT_LIST_HEAD(&t->timer_list);
|
||||
t->function=NULL;
|
||||
t->expires=0;
|
||||
|
||||
t->kDPC = NULL;
|
||||
t->kTimer = NULL;
|
||||
|
||||
//printk("init_timer %p\n", t);
|
||||
}
|
||||
|
||||
static void __inline__ add_timer(struct timer_list* t)
|
||||
static void __inline add_timer(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
//printk("add_timer %p, expires-jiffies=%d, 100nsec intervals=%d\n", t, t->expires-jiffies, -10000 * jiffies_to_msecs(t->expires - jiffies));
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==0)
|
||||
{
|
||||
LARGE_INTEGER delay;
|
||||
//delay.QuadPart = -10*1000000; // 10 seconds
|
||||
delay.QuadPart = -10000 * jiffies_to_msecs(t->expires - jiffies);// convert msecs to 100nsec intervals
|
||||
if (delay.QuadPart == 0)
|
||||
DPRINT1("add_timer with 0 expire time!");
|
||||
|
||||
main_timer_list[n]=t;
|
||||
|
||||
// Allocate non-paged buffers if needed
|
||||
//FIXME: Not optimal to allocate such small things!
|
||||
|
||||
if (!t->kDPC)
|
||||
t->kDPC = ExAllocatePool(NonPagedPool, sizeof(KDPC));
|
||||
if (!t->kTimer)
|
||||
t->kTimer = ExAllocatePool(NonPagedPool, sizeof(KTIMER));
|
||||
|
||||
KeInitializeTimer(t->kTimer);
|
||||
|
||||
switch(n)
|
||||
{
|
||||
case 0:
|
||||
KeInitializeDpc(t->kDPC, (PKDEFERRED_ROUTINE)_TimerDpc0, NULL);
|
||||
break;
|
||||
case 1:
|
||||
KeInitializeDpc(t->kDPC, (PKDEFERRED_ROUTINE)_TimerDpc1, NULL);
|
||||
break;
|
||||
case 2:
|
||||
KeInitializeDpc(t->kDPC, (PKDEFERRED_ROUTINE)_TimerDpc2, NULL);
|
||||
break;
|
||||
case 3:
|
||||
KeInitializeDpc(t->kDPC, (PKDEFERRED_ROUTINE)_TimerDpc3, NULL);
|
||||
break;
|
||||
case 4:
|
||||
KeInitializeDpc(t->kDPC, (PKDEFERRED_ROUTINE)_TimerDpc4, NULL);
|
||||
break;
|
||||
default:
|
||||
printk("No more timer DPCs left, panic!!\n");
|
||||
}
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
//KeDelayExecutionThread(KernelMode, FALSE, &delay);
|
||||
KeSetTimer(t->kTimer, delay, t->kDPC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __inline__ del_timer(struct timer_list* t)
|
||||
static void __inline del_timer(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
//printk("del_timer %p\n", t);
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==t)
|
||||
{
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
KeWaitForSingleObject(t->kTimer, Executive, KernelMode, FALSE, NULL);
|
||||
KeCancelTimer(t->kTimer);
|
||||
main_timer_list[n]=0;
|
||||
ExFreePool(t->kTimer);
|
||||
ExFreePool(t->kDPC);
|
||||
t->kTimer = NULL;
|
||||
t->kDPC = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void __inline__ del_timer_sync(struct timer_list* t)
|
||||
static void __inline del_timer_sync(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
//printk("del_timer_sync %p\n", t);
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==t)
|
||||
{
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
KeWaitForSingleObject(t->kTimer, Executive, KernelMode, FALSE, NULL);
|
||||
KeCancelTimer(t->kTimer);
|
||||
main_timer_list[n]=0;
|
||||
ExFreePool(t->kTimer);
|
||||
ExFreePool(t->kDPC);
|
||||
t->kTimer = NULL;
|
||||
t->kDPC = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
static void __inline__ mod_timer(struct timer_list* t, int ex)
|
||||
static void __inline mod_timer(struct timer_list* t, int ex)
|
||||
{
|
||||
del_timer(t);
|
||||
LARGE_INTEGER delay;
|
||||
|
||||
//printk("mod_timer %p, kTimer %p, kDpc %p...\n", t, t->kTimer, t->kDPC);
|
||||
//del_timer(t);
|
||||
t->expires=ex;
|
||||
add_timer(t);
|
||||
//add_timer(t);
|
||||
|
||||
// Check, maybe there was no preceding add_timer call.
|
||||
if (t->kTimer == NULL && t->kDPC == NULL)
|
||||
{
|
||||
// If not - make it
|
||||
add_timer(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise just modify existing timer
|
||||
delay.QuadPart = -10000 * jiffies_to_msecs(t->expires - jiffies); // convert msecs to 100nsec intervals
|
||||
if (delay.QuadPart == 0)
|
||||
DPRINT1("mod_timer with 0 expire time!");
|
||||
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
ASSERT(t->kTimer);
|
||||
ASSERT(t->kDPC);
|
||||
KeWaitForSingleObject(t->kTimer, Executive, KernelMode, FALSE, NULL);
|
||||
KeSetTimer(t->kTimer, delay, t->kDPC);
|
||||
}
|
||||
}
|
||||
|
||||
#define time_after(a,b) \
|
||||
((long)(b) - (long)(a) < 0)
|
||||
|
||||
#define time_after_eq(a,b) \
|
||||
(((long)(a) - (long)(b) >= 0))
|
||||
|
||||
/* Parameters used to convert the timespec values */
|
||||
#define MSEC_PER_SEC (1000L)
|
||||
#define USEC_PER_SEC (1000000L)
|
||||
#define NSEC_PER_SEC (1000000000L)
|
||||
#define NSEC_PER_USEC (1000L)
|
||||
|
||||
/*
|
||||
* Change timeval to jiffies, trying to avoid the
|
||||
* most obvious overflows..
|
||||
*
|
||||
* And some not so obvious.
|
||||
*
|
||||
* Note that we don't want to return MAX_LONG, because
|
||||
* for various timeout reasons we often end up having
|
||||
* to wait "jiffies+1" in order to guarantee that we wait
|
||||
* at _least_ "jiffies" - so "jiffies+1" had better still
|
||||
* be positive.
|
||||
*/
|
||||
#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
|
||||
|
||||
/*
|
||||
* Convert jiffies to milliseconds and back.
|
||||
*
|
||||
* Avoid unnecessary multiplications/divisions in the
|
||||
* two most common HZ cases:
|
||||
*/
|
||||
static __inline unsigned int jiffies_to_msecs(const unsigned long j)
|
||||
{
|
||||
#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
|
||||
return (MSEC_PER_SEC / HZ) * j;
|
||||
#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
|
||||
return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
|
||||
#else
|
||||
return (j * MSEC_PER_SEC) / HZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline unsigned long msecs_to_jiffies(const unsigned int m)
|
||||
{
|
||||
if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
|
||||
return MAX_JIFFY_OFFSET;
|
||||
#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
|
||||
return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
|
||||
#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
|
||||
return m * (HZ / MSEC_PER_SEC);
|
||||
#else
|
||||
return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device driver and process related stuff */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
static int __inline__ usb_major_init(void){return 0;}
|
||||
static void __inline__ usb_major_cleanup(void){}
|
||||
static void __inline__ schedule_work(void* p){}
|
||||
static int __inline usb_major_init(void){return 0;}
|
||||
static void __inline usb_major_cleanup(void){}
|
||||
static void __inline schedule_work(void* p){}
|
||||
static void __inline schedule_delayed_work(void *p, int flags){}
|
||||
static void __inline cancel_delayed_work(void *p){}
|
||||
|
||||
|
||||
#define device_initialize(x) my_device_initialize(x)
|
||||
void my_device_initialize(struct device *dev);
|
||||
@@ -786,33 +1068,54 @@ struct device *my_get_device(struct device *dev);
|
||||
#define device_add(x) my_device_add(x)
|
||||
int my_device_add(struct device *dev);
|
||||
|
||||
#define device_del(x) do {} while(0)
|
||||
#define device_bind_driver(x) do {} while(0)
|
||||
#define device_release_driver(x) do {} while(0)
|
||||
|
||||
#define driver_for_each_device(a,b,c,d) NULL
|
||||
|
||||
#define driver_register(x) my_driver_register(x)
|
||||
int my_driver_register(struct device_driver *driver);
|
||||
|
||||
#define device_unregister(a) my_device_unregister(a)
|
||||
int my_device_unregister(struct device *dev);
|
||||
|
||||
#define device_is_registered(a) FALSE
|
||||
|
||||
#define DEVICE_ATTR(a,b,c,d) int xxx_##a
|
||||
#define device_create_file(a,b) do {} while(0)
|
||||
#define device_remove_file(a,b) do {} while(0)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Scheduling, threads */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define schedule_timeout(x) my_schedule_timeout(x)
|
||||
int my_schedule_timeout(int x);
|
||||
|
||||
#define wake_up(x) my_wake_up(x)
|
||||
void my_wake_up(PKEVENT);
|
||||
|
||||
#define wake_up_all(x) do {} while(0)
|
||||
|
||||
#define try_to_freeze(x) my_try_to_freeze()
|
||||
void my_try_to_freeze();
|
||||
#define kthread_should_stop(x) FALSE
|
||||
|
||||
// cannot be mapped via macro due to collision with urb->complete
|
||||
static void __inline__ complete(struct completion *p)
|
||||
static void __inline complete(struct completion *p)
|
||||
{
|
||||
printk("completing event 0x%08x\n", (ULONG)p);
|
||||
//printk("completing event 0x%08x\n", (ULONG)p);
|
||||
/* Wake up x->wait */
|
||||
p->done++;
|
||||
wake_up((PKEVENT)&p->wait);
|
||||
}
|
||||
|
||||
#define kernel_thread(a,b,c) my_kernel_thread(a,b,c)
|
||||
int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags);
|
||||
int my_kernel_thread(int (STDCALL *handler)(void*), void* parm, int flags);
|
||||
|
||||
#define kthread_run(a,b,c) kernel_thread(a,b,0)
|
||||
#define kthread_stop(a) DPRINT1("kthread_stop() called, UNIMPLEMENTED!\n");
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* PCI, simple and inlined... */
|
||||
@@ -848,8 +1151,6 @@ void inc_jiffies(int);
|
||||
void init_wrapper(struct pci_dev *pci_dev);
|
||||
void do_all_timers(void);
|
||||
|
||||
int my_pci_write_config_word(struct pci_dev *, int, u16);
|
||||
|
||||
void UsbKeyBoardInit(void);
|
||||
void UsbKeyBoardRemove(void);
|
||||
void UsbMouseInit(void);
|
||||
|
@@ -30,14 +30,14 @@ struct list_head {
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
static __inline void __list_add(struct list_head *new_,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
next->prev = new_;
|
||||
new_->next = next;
|
||||
new_->prev = prev;
|
||||
prev->next = new_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ static inline void __list_add(struct list_head *new,
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
static __inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
@@ -61,7 +61,7 @@ static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
static __inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
static __inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
@@ -84,7 +84,7 @@ static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
static __inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
@@ -95,7 +95,7 @@ static inline void list_del(struct list_head *entry)
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
static __inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
@@ -106,7 +106,7 @@ static inline void list_del_init(struct list_head *entry)
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
static __inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
@@ -117,7 +117,7 @@ static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
static __inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
@@ -128,12 +128,12 @@ static inline void list_move_tail(struct list_head *list,
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(struct list_head *head)
|
||||
static __inline int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
static __inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
@@ -152,7 +152,7 @@ static inline void __list_splice(struct list_head *list,
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
static __inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
@@ -165,7 +165,7 @@ static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
static __inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
@@ -180,8 +180,12 @@ static inline void list_splice_init(struct list_head *list,
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
//#define list_entry(ptr, type, member) \
|
||||
// ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
CONTAINING_RECORD(ptr, type, member)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
@@ -216,9 +220,11 @@ static inline void list_splice_init(struct list_head *list,
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member) \
|
||||
// unfortunately there is no good "typeof" in msvc, thus we have
|
||||
// to provide additional parameter "type"
|
||||
#define list_for_each_entry(pos, type, head, member) \
|
||||
for (pos = list_entry((head)->next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
pos = list_entry(pos->member.next, type, member))
|
||||
|
||||
#endif
|
||||
|
@@ -8,14 +8,21 @@
|
||||
Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory.
|
||||
Wake up the device if it was suspended. Beware, this function can fail.
|
||||
*/
|
||||
static int __inline__ pci_enable_device(struct pci_dev *dev)
|
||||
static int __inline pci_enable_device(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_enable_device() called...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __inline pci_disable_device(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_disable_device() called...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get physical address where resource x resides
|
||||
static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int x)
|
||||
static PHYSICAL_ADDRESS __inline pci_resource_start (struct pci_dev *dev, int x)
|
||||
{
|
||||
PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
DPRINT1("pci_resource_start() called, x=0x%x\n", x);
|
||||
@@ -26,7 +33,7 @@ static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int
|
||||
}
|
||||
|
||||
// ???
|
||||
static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x)
|
||||
static unsigned long __inline pci_resource_len (struct pci_dev *dev, int x)
|
||||
{
|
||||
PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
@@ -37,7 +44,7 @@ static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x)
|
||||
}
|
||||
|
||||
// ???
|
||||
static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
|
||||
static int __inline pci_resource_flags(struct pci_dev *dev, int x)
|
||||
{
|
||||
PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
@@ -50,10 +57,10 @@ static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
|
||||
/*
|
||||
Enables bus-mastering for device dev
|
||||
*/
|
||||
static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;}
|
||||
static int __inline pci_set_master(struct pci_dev *dev) {return 0;}
|
||||
|
||||
// Store pointer to data for this device
|
||||
static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
static int __inline pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
{
|
||||
DPRINT1("pci_set_drvdata() called...\n");
|
||||
dev->data=(void*)d;
|
||||
@@ -61,9 +68,9 @@ static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
}
|
||||
|
||||
// Get pointer to previously saved data
|
||||
static void __inline__ *pci_get_drvdata(struct pci_dev *dev)
|
||||
static void __inline *pci_get_drvdata(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_get_drvdata() called...\n");
|
||||
DPRINT1("pci_get_drvdata() called, dev %p...\n", dev);
|
||||
return dev->data;
|
||||
}
|
||||
|
||||
@@ -81,7 +88,7 @@ start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
static int __inline request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return ~0;
|
||||
@@ -94,7 +101,7 @@ Parameters:
|
||||
addr virtual start address
|
||||
|
||||
*/
|
||||
static int __inline__ iounmap(void* p)
|
||||
static int __inline iounmap(void* p)
|
||||
{
|
||||
DPRINT1("iounmap(): p=0x%x. FIXME - how to obtain len of mapped region?\n", p);
|
||||
|
||||
@@ -110,7 +117,7 @@ Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
static int __inline release_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 0;
|
||||
@@ -124,7 +131,7 @@ start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
static int __inline request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 1;
|
||||
@@ -140,7 +147,7 @@ size size of physical address range
|
||||
Returns:
|
||||
virtual start address of mapped range
|
||||
*/
|
||||
static void __inline__ *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
static void __inline *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
// MmMapIoSpace with NoCache param
|
||||
DPRINT1("ioremap_nocache(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
@@ -155,7 +162,7 @@ Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
static int __inline release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 0;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "usb_ch9.h"
|
||||
|
||||
#define USB_MAJOR 180
|
||||
#define USB_DEVICE_MAJOR 189
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
@@ -14,23 +15,14 @@
|
||||
#include <linux/delay.h> /* for mdelay() */
|
||||
#include <linux/interrupt.h> /* for in_interrupt() */
|
||||
#include <linux/list.h> /* for struct list_head */
|
||||
#include <linux/kref.h> /* for struct kref */
|
||||
#include <linux/device.h> /* for struct device */
|
||||
#include <linux/fs.h> /* for struct file_operations */
|
||||
#include <linux/completion.h> /* for struct completion */
|
||||
#include <linux/sched.h> /* for current && schedule_timeout */
|
||||
|
||||
|
||||
static __inline__ void wait_ms(unsigned int ms)
|
||||
{
|
||||
if(!in_interrupt()) {
|
||||
current->state = TASK_UNINTERRUPTIBLE;
|
||||
schedule_timeout(1 + ms * HZ / 1000);
|
||||
}
|
||||
else
|
||||
mdelay(ms);
|
||||
}
|
||||
#endif
|
||||
struct usb_device;
|
||||
struct usb_driver;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -49,9 +41,22 @@ struct usb_device;
|
||||
* Devices may also have class-specific or vendor-specific descriptors.
|
||||
*/
|
||||
|
||||
/* host-side wrapper for parsed endpoint descriptors */
|
||||
/**
|
||||
* struct usb_host_endpoint - host-side endpoint descriptor and queue
|
||||
* @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder
|
||||
* @urb_list: urbs queued to this endpoint; maintained by usbcore
|
||||
* @hcpriv: for use by HCD; typically holds hardware dma queue head (QH)
|
||||
* with one or more transfer descriptors (TDs) per urb
|
||||
* @extra: descriptors following this endpoint in the configuration
|
||||
* @extralen: how many bytes of "extra" are valid
|
||||
*
|
||||
* USB requests are always queued to a given endpoint, identified by a
|
||||
* descriptor within an active interface in a given USB configuration.
|
||||
*/
|
||||
struct usb_host_endpoint {
|
||||
struct usb_endpoint_descriptor desc;
|
||||
struct list_head urb_list;
|
||||
void *hcpriv;
|
||||
|
||||
unsigned char *extra; /* Extra descriptors */
|
||||
int extralen;
|
||||
@@ -66,27 +71,34 @@ struct usb_host_interface {
|
||||
*/
|
||||
struct usb_host_endpoint *endpoint;
|
||||
|
||||
char *string; /* iInterface string, if present */
|
||||
unsigned char *extra; /* Extra descriptors */
|
||||
int extralen;
|
||||
};
|
||||
|
||||
enum usb_interface_condition {
|
||||
USB_INTERFACE_UNBOUND = 0,
|
||||
USB_INTERFACE_BINDING,
|
||||
USB_INTERFACE_BOUND,
|
||||
USB_INTERFACE_UNBINDING,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct usb_interface - what usb device drivers talk to
|
||||
* @altsetting: array of interface descriptors, one for each alternate
|
||||
* @altsetting: array of interface structures, one for each alternate
|
||||
* setting that may be selected. Each one includes a set of
|
||||
* endpoint configurations and will be in numberic order,
|
||||
* 0..num_altsetting.
|
||||
* endpoint configurations. They will be in no particular order.
|
||||
* @num_altsetting: number of altsettings defined.
|
||||
* @act_altsetting: index of current altsetting. this number is always
|
||||
* less than num_altsetting. after the device is configured, each
|
||||
* interface uses its default setting of zero.
|
||||
* @max_altsetting:
|
||||
* @cur_altsetting: the current altsetting.
|
||||
* @driver: the USB driver that is bound to this interface.
|
||||
* @minor: the minor number assigned to this interface, if this
|
||||
* interface is bound to a driver that uses the USB major number.
|
||||
* If this interface does not use the USB major, this field should
|
||||
* be unused. The driver should set this value in the probe()
|
||||
* function of the driver, after it has been assigned a minor
|
||||
* number from the USB core by calling usb_register_dev().
|
||||
* @condition: binding state of the interface: not bound, binding
|
||||
* (in probe()), bound to a driver, or unbinding (in disconnect())
|
||||
* @dev: driver model's view of this device
|
||||
* @class_dev: driver model's class view of this device.
|
||||
*
|
||||
@@ -102,78 +114,140 @@ struct usb_host_interface {
|
||||
* calls such as dev_get_drvdata() on the dev member of this structure.
|
||||
*
|
||||
* Each interface may have alternate settings. The initial configuration
|
||||
* of a device sets the first of these, but the device driver can change
|
||||
* of a device sets altsetting 0, but the device driver can change
|
||||
* that setting using usb_set_interface(). Alternate settings are often
|
||||
* used to control the the use of periodic endpoints, such as by having
|
||||
* different endpoints use different amounts of reserved USB bandwidth.
|
||||
* All standards-conformant USB devices that use isochronous endpoints
|
||||
* will use them in non-default settings.
|
||||
*
|
||||
* The USB specification says that alternate setting numbers must run from
|
||||
* 0 to one less than the total number of alternate settings. But some
|
||||
* devices manage to mess this up, and the structures aren't necessarily
|
||||
* stored in numerical order anyhow. Use usb_altnum_to_altsetting() to
|
||||
* look up an alternate setting in the altsetting array based on its number.
|
||||
*/
|
||||
|
||||
struct usb_interface {
|
||||
/* array of alternate settings for this interface.
|
||||
* these will be in numeric order, 0..num_altsettting
|
||||
*/
|
||||
|
||||
/* array of alternate settings for this interface,
|
||||
* stored in no particular order */
|
||||
struct usb_host_interface *altsetting;
|
||||
|
||||
unsigned act_altsetting; /* active alternate setting */
|
||||
struct usb_host_interface *cur_altsetting; /* the currently
|
||||
* active alternate setting */
|
||||
unsigned num_altsetting; /* number of alternate settings */
|
||||
unsigned max_altsetting; /* total memory allocated */
|
||||
|
||||
struct usb_driver *driver; /* driver */
|
||||
int minor; /* minor number this interface is bound to */
|
||||
enum usb_interface_condition condition; /* state of binding */
|
||||
struct device dev; /* interface specific device info */
|
||||
struct class_device class_dev;
|
||||
}USB_INTERFACE, *PUSB_INTERFACE;
|
||||
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
|
||||
#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev)
|
||||
#define interface_to_usbdev(intf) \
|
||||
container_of(intf->dev.parent, struct usb_device, dev)
|
||||
|
||||
static inline void *usb_get_intfdata (struct usb_interface *intf)
|
||||
static __inline void *usb_get_intfdata (struct usb_interface *intf)
|
||||
{
|
||||
return dev_get_drvdata (&intf->dev);
|
||||
}
|
||||
|
||||
static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
|
||||
static __inline void usb_set_intfdata (struct usb_interface *intf, void *data)
|
||||
{
|
||||
dev_set_drvdata(&intf->dev, data);
|
||||
}
|
||||
|
||||
/* USB_DT_CONFIG: Configuration descriptor information.
|
||||
struct usb_interface *usb_get_intf(struct usb_interface *intf);
|
||||
void usb_put_intf(struct usb_interface *intf);
|
||||
|
||||
/* this maximum is arbitrary */
|
||||
#define USB_MAXINTERFACES 32
|
||||
|
||||
/**
|
||||
* struct usb_interface_cache - long-term representation of a device interface
|
||||
* @num_altsetting: number of altsettings defined.
|
||||
* @ref: reference counter.
|
||||
* @altsetting: variable-length array of interface structures, one for
|
||||
* each alternate setting that may be selected. Each one includes a
|
||||
* set of endpoint configurations. They will be in no particular order.
|
||||
*
|
||||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
|
||||
* descriptor type is different. Highspeed-capable devices can look
|
||||
* different depending on what speed they're currently running. Only
|
||||
* devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
|
||||
* These structures persist for the lifetime of a usb_device, unlike
|
||||
* struct usb_interface (which persists only as long as its configuration
|
||||
* is installed). The altsetting arrays can be accessed through these
|
||||
* structures at any time, permitting comparison of configurations and
|
||||
* providing support for the /proc/bus/usb/devices pseudo-file.
|
||||
*/
|
||||
struct usb_interface_cache {
|
||||
unsigned num_altsetting; /* number of alternate settings */
|
||||
struct kref ref; /* reference counter */
|
||||
|
||||
/* variable-length array of alternate settings for this interface,
|
||||
* stored in no particular order */
|
||||
struct usb_host_interface altsetting[0];
|
||||
};
|
||||
#define ref_to_usb_interface_cache(r) \
|
||||
container_of(r, struct usb_interface_cache, ref)
|
||||
#define altsetting_to_usb_interface_cache(a) \
|
||||
container_of(a, struct usb_interface_cache, altsetting[0])
|
||||
|
||||
/**
|
||||
* struct usb_host_config - representation of a device's configuration
|
||||
* @desc: the device's configuration descriptor.
|
||||
* @string: pointer to the cached version of the iConfiguration string, if
|
||||
* present for this configuration.
|
||||
* @interface: array of pointers to usb_interface structures, one for each
|
||||
* interface in the configuration. The number of interfaces is stored
|
||||
* in desc.bNumInterfaces. These pointers are valid only while the
|
||||
* the configuration is active.
|
||||
* @intf_cache: array of pointers to usb_interface_cache structures, one
|
||||
* for each interface in the configuration. These structures exist
|
||||
* for the entire life of the device.
|
||||
* @extra: pointer to buffer containing all extra descriptors associated
|
||||
* with this configuration (those preceding the first interface
|
||||
* descriptor).
|
||||
* @extralen: length of the extra descriptors buffer.
|
||||
*
|
||||
* USB devices may have multiple configurations, but only one can be active
|
||||
* at any time. Each encapsulates a different operational environment;
|
||||
* for example, a dual-speed device would have separate configurations for
|
||||
* full-speed and high-speed operation. The number of configurations
|
||||
* available is stored in the device descriptor as bNumConfigurations.
|
||||
*
|
||||
* A configuration can contain multiple interfaces. Each corresponds to
|
||||
* a different function of the USB device, and all are available whenever
|
||||
* the configuration is active. The USB standard says that interfaces
|
||||
* are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot
|
||||
* of devices get this wrong. In addition, the interface array is not
|
||||
* guaranteed to be sorted in numerical order. Use usb_ifnum_to_if() to
|
||||
* look up an interface entry based on its number.
|
||||
*
|
||||
* Device drivers should not attempt to activate configurations. The choice
|
||||
* of which configuration to install is a policy decision based on such
|
||||
* considerations as available power, functionality provided, and the user's
|
||||
* desires (expressed through hotplug scripts). However, drivers can call
|
||||
* usb_reset_configuration() to reinitialize the current configuration and
|
||||
* all its interfaces.
|
||||
*/
|
||||
struct usb_host_config {
|
||||
struct usb_config_descriptor desc;
|
||||
|
||||
/* the interfaces associated with this configuration
|
||||
* these will be in numeric order, 0..desc.bNumInterfaces
|
||||
*/
|
||||
|
||||
struct usb_interface *interface;
|
||||
char *string;
|
||||
/* the interfaces associated with this configuration,
|
||||
* stored in no particular order */
|
||||
struct usb_interface *interface[USB_MAXINTERFACES];
|
||||
|
||||
/* Interface information available even when this is not the
|
||||
* active configuration */
|
||||
struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
|
||||
|
||||
unsigned char *extra; /* Extra descriptors */
|
||||
int extralen;
|
||||
};
|
||||
|
||||
// FIXME remove; exported only for drivers/usb/misc/auserwald.c
|
||||
// prefer usb_device->epnum[0..31]
|
||||
extern struct usb_endpoint_descriptor *
|
||||
usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
|
||||
|
||||
int __usb_get_extra_descriptor(char *buffer, unsigned size,
|
||||
unsigned char type, void **ptr);
|
||||
#define usb_get_extra_descriptor(ifpoint,type,ptr)\
|
||||
__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
|
||||
type,(void**)ptr)
|
||||
|
||||
void usb_choose_address(struct usb_device *dev);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct usb_operations;
|
||||
@@ -190,6 +264,9 @@ struct usb_bus {
|
||||
struct device *controller; /* host/master side hardware */
|
||||
int busnum; /* Bus number (in order of reg) */
|
||||
char *bus_name; /* stable id (PCI slot_name etc) */
|
||||
u8 otg_port; /* 0, or number of OTG/HNP port */
|
||||
unsigned is_b_host:1; /* true during some HNP roleswitches */
|
||||
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
|
||||
|
||||
int devnum_next; /* Next open device number in round-robin allocation */
|
||||
|
||||
@@ -210,12 +287,16 @@ struct usb_bus {
|
||||
int bandwidth_isoc_reqs; /* number of Isoc. requests */
|
||||
|
||||
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
|
||||
struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */
|
||||
|
||||
atomic_t refcnt;
|
||||
struct class_device *class_dev; /* class device for this bus */
|
||||
struct kref kref; /* handles reference counting this bus */
|
||||
void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */
|
||||
#if defined(CONFIG_USB_MON)
|
||||
struct mon_bus *mon_bus; /* non-null when associated */
|
||||
int monitored; /* non-zero when monitored */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* This is arbitrary.
|
||||
@@ -226,6 +307,14 @@ struct usb_bus {
|
||||
|
||||
struct usb_tt;
|
||||
|
||||
/*
|
||||
* struct usb_device - kernel's representation of a USB device
|
||||
*
|
||||
* FIXME: Write the kerneldoc!
|
||||
*
|
||||
* Usbcore drivers should not set usbdev->state directly. Instead use
|
||||
* usb_set_device_state().
|
||||
*/
|
||||
struct usb_device {
|
||||
int devnum; /* Address on USB bus */
|
||||
char devpath [16]; /* Use in messages: /port/port/... */
|
||||
@@ -238,30 +327,31 @@ struct usb_device {
|
||||
struct semaphore serialize;
|
||||
|
||||
unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */
|
||||
unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */
|
||||
/* [0] = IN, [1] = OUT */
|
||||
int epmaxpacketin[16]; /* INput endpoint specific maximums */
|
||||
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
|
||||
|
||||
struct usb_device *parent; /* our hub, unless we're the root */
|
||||
struct usb_bus *bus; /* Bus we're part of */
|
||||
struct usb_host_endpoint ep0;
|
||||
|
||||
struct device dev; /* Generic device interface */
|
||||
|
||||
struct usb_device_descriptor descriptor;/* Descriptor */
|
||||
struct usb_host_config *config; /* All of the configs */
|
||||
|
||||
struct usb_host_config *actconfig;/* the active configuration */
|
||||
struct usb_host_endpoint *ep_in[16];
|
||||
struct usb_host_endpoint *ep_out[16];
|
||||
|
||||
char **rawdescriptors; /* Raw descriptors for each config */
|
||||
|
||||
int have_langid; /* whether string_langid is valid yet */
|
||||
int string_langid; /* language ID for strings */
|
||||
|
||||
void *hcpriv; /* Host Controller private data */
|
||||
|
||||
char *product;
|
||||
char *manufacturer;
|
||||
char *serial; /* static strings from the device */
|
||||
struct list_head filelist;
|
||||
struct class_device *class_dev;
|
||||
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
|
||||
struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the device */
|
||||
|
||||
/*
|
||||
* Child devices - these can be either new devices
|
||||
@@ -276,29 +366,54 @@ struct usb_device {
|
||||
};
|
||||
#define to_usb_device(d) container_of(d, struct usb_device, dev)
|
||||
|
||||
extern struct usb_device STDCALL *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
|
||||
extern struct usb_device STDCALL *usb_get_dev(struct usb_device *dev);
|
||||
extern struct usb_device* STDCALL usb_get_dev(struct usb_device *dev);
|
||||
extern void STDCALL usb_put_dev(struct usb_device *dev);
|
||||
|
||||
/* mostly for devices emulating SCSI over USB */
|
||||
extern void usb_lock_device(struct usb_device *udev);
|
||||
extern int usb_trylock_device(struct usb_device *udev);
|
||||
extern int usb_lock_device_for_reset(struct usb_device *udev,
|
||||
struct usb_interface *iface);
|
||||
extern void usb_unlock_device(struct usb_device *udev);
|
||||
|
||||
/* USB port reset for device reinitialization */
|
||||
extern int usb_reset_device(struct usb_device *dev);
|
||||
|
||||
extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* for drivers using iso endpoints */
|
||||
extern int usb_get_current_frame_number (struct usb_device *usb_dev);
|
||||
|
||||
/* used these for multi-interface device registration */
|
||||
extern void usb_driver_claim_interface(struct usb_driver *driver,
|
||||
extern int usb_driver_claim_interface(struct usb_driver *driver,
|
||||
struct usb_interface *iface, void* priv);
|
||||
extern int usb_interface_claimed(struct usb_interface *iface);
|
||||
|
||||
/**
|
||||
* usb_interface_claimed - returns true iff an interface is claimed
|
||||
* @iface: the interface being checked
|
||||
*
|
||||
* Returns true (nonzero) iff the interface is claimed, else false (zero).
|
||||
* Callers must own the driver model's usb bus readlock. So driver
|
||||
* probe() entries don't need extra locking, but other call contexts
|
||||
* may need to explicitly claim that lock.
|
||||
*
|
||||
*/
|
||||
static __inline int usb_interface_claimed(struct usb_interface *iface) {
|
||||
return (iface->dev.driver != NULL);
|
||||
}
|
||||
|
||||
extern void usb_driver_release_interface(struct usb_driver *driver,
|
||||
struct usb_interface *iface);
|
||||
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
|
||||
const struct usb_device_id *id);
|
||||
|
||||
extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor);
|
||||
extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
|
||||
extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
|
||||
int minor);
|
||||
extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
|
||||
unsigned ifnum);
|
||||
extern struct usb_host_interface *usb_altnum_to_altsetting(
|
||||
struct usb_interface *intf, unsigned int altnum);
|
||||
|
||||
|
||||
/**
|
||||
@@ -325,11 +440,11 @@ extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned if
|
||||
* USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
|
||||
* high speed, and a different one if they are full or low speed.
|
||||
*/
|
||||
static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
|
||||
static __inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
|
||||
{
|
||||
int actual;
|
||||
actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath);
|
||||
return (actual >= size) ? -1 : actual;
|
||||
return (actual >= (int)size) ? -1 : actual;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -386,9 +501,14 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
|
||||
* This macro is used to create a struct usb_device_id that matches a
|
||||
* specific class of interfaces.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define USB_INTERFACE_INFO(cl,sc,pr) \
|
||||
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
|
||||
|
||||
#else
|
||||
#define USB_INTERFACE_INFO(cl,sc,pr) \
|
||||
USB_DEVICE_ID_MATCH_INT_INFO, 0, 0, 0, 0, 0, 0, 0, \
|
||||
(cl), (sc), (pr)
|
||||
#endif
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@@ -410,9 +530,12 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
|
||||
* the "usbfs" filesystem. This lets devices provide ways to
|
||||
* expose information to user space regardless of where they
|
||||
* do (or don't) show up otherwise in the filesystem.
|
||||
* @suspend: Called when the device is going to be suspended by the system.
|
||||
* @resume: Called when the device is being resumed by the system.
|
||||
* @id_table: USB drivers use ID table to support hotplugging.
|
||||
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
|
||||
* or your driver's probe function will never get called.
|
||||
* or your driver's probe function will never get called.
|
||||
* @driver: the driver model core driver structure.
|
||||
*
|
||||
* USB drivers must provide a name, probe() and disconnect() methods,
|
||||
* and an id_table. Other driver fields are optional.
|
||||
@@ -441,11 +564,12 @@ struct usb_driver {
|
||||
|
||||
int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
|
||||
|
||||
int (*suspend) (struct usb_interface *intf, pm_message_t message);
|
||||
int (*resume) (struct usb_interface *intf);
|
||||
|
||||
const struct usb_device_id *id_table;
|
||||
|
||||
struct device_driver driver;
|
||||
|
||||
struct semaphore serialize;
|
||||
};
|
||||
#define to_usb_driver(d) container_of(d, struct usb_driver, driver)
|
||||
|
||||
@@ -460,8 +584,8 @@ extern struct bus_type usb_bus_type;
|
||||
* @minor_base: the start of the minor range for this driver.
|
||||
*
|
||||
* This structure is used for the usb_register_dev() and
|
||||
* usb_unregister_dev() functions, to consolodate a number of the
|
||||
* paramaters used for them.
|
||||
* usb_unregister_dev() functions, to consolidate a number of the
|
||||
* parameters used for them.
|
||||
*/
|
||||
struct usb_class_driver {
|
||||
char *name;
|
||||
@@ -482,8 +606,6 @@ extern int usb_register_dev(struct usb_interface *intf,
|
||||
extern void usb_deregister_dev(struct usb_interface *intf,
|
||||
struct usb_class_driver *class_driver);
|
||||
|
||||
extern int usb_device_probe(struct device *dev);
|
||||
extern int usb_device_remove(struct device *dev);
|
||||
extern int STDCALL usb_disabled(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@@ -497,8 +619,8 @@ extern int STDCALL usb_disabled(void);
|
||||
*/
|
||||
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
|
||||
#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */
|
||||
#define URB_NO_DMA_MAP 0x0004 /* urb->*_dma are valid on submit */
|
||||
#define URB_ASYNC_UNLINK 0x0008 /* usb_unlink_urb() returns asap */
|
||||
#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
|
||||
#define URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */
|
||||
#define URB_NO_FSBR 0x0020 /* UHCI-specific */
|
||||
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */
|
||||
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
|
||||
@@ -520,7 +642,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* @urb_list: For use by current owner of the URB.
|
||||
* @pipe: Holds endpoint number, direction, type, and more.
|
||||
* Create these values with the eight macros available;
|
||||
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl"
|
||||
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
|
||||
* (control), "bulk", "int" (interrupt), or "iso" (isochronous).
|
||||
* For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint
|
||||
* numbers range from zero to fifteen. Note that "in" endpoint two
|
||||
@@ -536,14 +658,15 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* submission, unlinking, or operation are handled. Different
|
||||
* kinds of URB can use different flags.
|
||||
* @transfer_buffer: This identifies the buffer to (or from) which
|
||||
* the I/O request will be performed (unless URB_NO_DMA_MAP is set).
|
||||
* This buffer must be suitable for DMA; allocate it with kmalloc()
|
||||
* or equivalent. For transfers to "in" endpoints, contents of
|
||||
* this buffer will be modified. This buffer is used for data
|
||||
* phases of control transfers.
|
||||
* @transfer_dma: When transfer_flags includes URB_NO_DMA_MAP, the device
|
||||
* driver is saying that it provided this DMA address, which the host
|
||||
* controller driver should use instead of the transfer_buffer.
|
||||
* the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP
|
||||
* is set). This buffer must be suitable for DMA; allocate it with
|
||||
* kmalloc() or equivalent. For transfers to "in" endpoints, contents
|
||||
* of this buffer will be modified. This buffer is used for the data
|
||||
* stage of control transfers.
|
||||
* @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP,
|
||||
* the device driver is saying that it provided this DMA address,
|
||||
* which the host controller driver should use in preference to the
|
||||
* transfer_buffer.
|
||||
* @transfer_buffer_length: How big is transfer_buffer. The transfer may
|
||||
* be broken up into chunks according to the current maximum packet
|
||||
* size for the endpoint, which is a function of the configuration
|
||||
@@ -558,13 +681,11 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* @setup_packet: Only used for control transfers, this points to eight bytes
|
||||
* of setup data. Control transfers always start by sending this data
|
||||
* to the device. Then transfer_buffer is read or written, if needed.
|
||||
* (Not used when URB_NO_DMA_MAP is set.)
|
||||
* @setup_dma: For control transfers with URB_NO_DMA_MAP set, the device
|
||||
* driver has provided this DMA address for the setup packet. The
|
||||
* host controller driver should use this instead of setup_buffer.
|
||||
* If there is a data phase, its buffer is identified by transfer_dma.
|
||||
* @start_frame: Returns the initial frame for interrupt or isochronous
|
||||
* transfers.
|
||||
* @setup_dma: For control transfers with URB_NO_SETUP_DMA_MAP set, the
|
||||
* device driver has provided this DMA address for the setup packet.
|
||||
* The host controller driver should use this in preference to
|
||||
* setup_packet.
|
||||
* @start_frame: Returns the initial frame for isochronous transfers.
|
||||
* @number_of_packets: Lists the number of ISO transfer buffers.
|
||||
* @interval: Specifies the polling interval for interrupt or isochronous
|
||||
* transfers. The units are frames (milliseconds) for for full and low
|
||||
@@ -582,7 +703,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* calling usb_alloc_urb() and freed with a call to usb_free_urb().
|
||||
* Initialization may be done using various usb_fill_*_urb() functions. URBs
|
||||
* are submitted using usb_submit_urb(), and pending requests may be canceled
|
||||
* using usb_unlink_urb().
|
||||
* using usb_unlink_urb() or usb_kill_urb().
|
||||
*
|
||||
* Data Transfer Buffers:
|
||||
*
|
||||
@@ -594,22 +715,20 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* bounce buffer or talking to an IOMMU),
|
||||
* although they're cheap on commodity x86 and ppc hardware.
|
||||
*
|
||||
* Alternatively, drivers may pass the URB_NO_DMA_MAP transfer flag, which
|
||||
* tells the host controller driver that no such mapping is needed since
|
||||
* the device driver is DMA-aware. For example, they might allocate a DMA
|
||||
* buffer with usb_buffer_alloc(), or call usb_buffer_map().
|
||||
* When this transfer flag is provided, host controller drivers will use the
|
||||
* dma addresses found in the transfer_dma and/or setup_dma fields rather than
|
||||
* determing a dma address themselves.
|
||||
* Alternatively, drivers may pass the URB_NO_xxx_DMA_MAP transfer flags,
|
||||
* which tell the host controller driver that no such mapping is needed since
|
||||
* the device driver is DMA-aware. For example, a device driver might
|
||||
* allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map().
|
||||
* When these transfer flags are provided, host controller drivers will
|
||||
* attempt to use the dma addresses found in the transfer_dma and/or
|
||||
* setup_dma fields rather than determining a dma address themselves. (Note
|
||||
* that transfer_buffer and setup_packet must still be set because not all
|
||||
* host controllers use DMA, nor do virtual root hubs).
|
||||
*
|
||||
* Initialization:
|
||||
*
|
||||
* All URBs submitted must initialize dev, pipe,
|
||||
* transfer_flags (may be zero), complete, timeout (may be zero).
|
||||
* The URB_ASYNC_UNLINK transfer flag affects later invocations of
|
||||
* the usb_unlink_urb() routine.
|
||||
*
|
||||
* All URBs must also initialize
|
||||
* All URBs submitted must initialize the dev, pipe, transfer_flags (may be
|
||||
* zero), and complete fields. All URBs must also initialize
|
||||
* transfer_buffer and transfer_buffer_length. They may provide the
|
||||
* URB_SHORT_NOT_OK transfer flag, indicating that short reads are
|
||||
* to be treated as errors; that flag is invalid for write requests.
|
||||
@@ -619,18 +738,23 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* should always terminate with a short packet, even if it means adding an
|
||||
* extra zero length packet.
|
||||
*
|
||||
* Control URBs must provide a setup_packet.
|
||||
* Control URBs must provide a setup_packet. The setup_packet and
|
||||
* transfer_buffer may each be mapped for DMA or not, independently of
|
||||
* the other. The transfer_flags bits URB_NO_TRANSFER_DMA_MAP and
|
||||
* URB_NO_SETUP_DMA_MAP indicate which buffers have already been mapped.
|
||||
* URB_NO_SETUP_DMA_MAP is ignored for non-control URBs.
|
||||
*
|
||||
* Interrupt UBS must provide an interval, saying how often (in milliseconds
|
||||
* Interrupt URBs must provide an interval, saying how often (in milliseconds
|
||||
* or, for highspeed devices, 125 microsecond units)
|
||||
* to poll for transfers. After the URB has been submitted, the interval
|
||||
* and start_frame fields reflect how the transfer was actually scheduled.
|
||||
* field reflects how the transfer was actually scheduled.
|
||||
* The polling interval may be more frequent than requested.
|
||||
* For example, some controllers have a maximum interval of 32 microseconds,
|
||||
* while others support intervals of up to 1024 microseconds.
|
||||
* For example, some controllers have a maximum interval of 32 milliseconds,
|
||||
* while others support intervals of up to 1024 milliseconds.
|
||||
* Isochronous URBs also have transfer intervals. (Note that for isochronous
|
||||
* endpoints, as well as high speed interrupt endpoints, the encoding of
|
||||
* the transfer interval in the endpoint descriptor is logarithmic.)
|
||||
* the transfer interval in the endpoint descriptor is logarithmic.
|
||||
* Device drivers must convert that value to linear units themselves.)
|
||||
*
|
||||
* Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
|
||||
* the host controller to schedule the transfer as soon as bandwidth
|
||||
@@ -663,20 +787,31 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||
* The context field is normally used to link URBs back to the relevant
|
||||
* driver or request state.
|
||||
*
|
||||
* When completion callback is invoked for non-isochronous URBs, the
|
||||
* actual_length field tells how many bytes were transferred.
|
||||
* When the completion callback is invoked for non-isochronous URBs, the
|
||||
* actual_length field tells how many bytes were transferred. This field
|
||||
* is updated even when the URB terminated with an error or was unlinked.
|
||||
*
|
||||
* ISO transfer status is reported in the status and actual_length fields
|
||||
* of the iso_frame_desc array, and the number of errors is reported in
|
||||
* error_count. Completion callbacks for ISO transfers will normally
|
||||
* (re)submit URBs to ensure a constant transfer rate.
|
||||
*
|
||||
* Note that even fields marked "public" should not be touched by the driver
|
||||
* when the urb is owned by the hcd, that is, since the call to
|
||||
* usb_submit_urb() till the entry into the completion routine.
|
||||
*/
|
||||
struct urb
|
||||
{
|
||||
/* private, usb core and host controller only fields in the urb */
|
||||
struct kref kref; /* reference count of the URB */
|
||||
spinlock_t lock; /* lock for the URB */
|
||||
atomic_t count; /* reference count of the URB */
|
||||
void *hcpriv; /* private data for host controller */
|
||||
struct list_head urb_list; /* list pointer to all active urbs */
|
||||
int bandwidth; /* bandwidth for INT/ISO request */
|
||||
atomic_t use_count; /* concurrent submissions counter */
|
||||
u8 reject; /* submissions will fail */
|
||||
|
||||
/* public, documented fields in the urb that can be used by drivers */
|
||||
struct list_head urb_list; /* list head for use by the urb owner */
|
||||
struct usb_device *dev; /* (in) pointer to associated device */
|
||||
unsigned int pipe; /* (in) pipe information */
|
||||
int status; /* (return) non-ISO status */
|
||||
@@ -685,14 +820,12 @@ struct urb
|
||||
dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
|
||||
int transfer_buffer_length; /* (in) data buffer length */
|
||||
int actual_length; /* (return) actual transfer length */
|
||||
int bandwidth; /* bandwidth for INT/ISO request */
|
||||
unsigned char *setup_packet; /* (in) setup packet (control only) */
|
||||
dma_addr_t setup_dma; /* (in) dma addr for setup_packet */
|
||||
int start_frame; /* (modify) start frame (INT/ISO) */
|
||||
int start_frame; /* (modify) start frame (ISO) */
|
||||
int number_of_packets; /* (in) number of ISO packets */
|
||||
int interval; /* (in) transfer interval (INT/ISO) */
|
||||
int interval; /* (modify) transfer interval (INT/ISO) */
|
||||
int error_count; /* (return) number of ISO errors */
|
||||
int timeout; /* (in) timeout, in jiffies */
|
||||
void *context; /* (in) context for completion */
|
||||
usb_complete_t complete; /* (in) completion routine */
|
||||
struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */
|
||||
@@ -714,7 +847,7 @@ struct urb
|
||||
* Initializes a control urb with the proper information needed to submit
|
||||
* it to a device.
|
||||
*/
|
||||
static inline void usb_fill_control_urb (struct urb *urb,
|
||||
static __inline void usb_fill_control_urb (struct urb *urb,
|
||||
struct usb_device *dev,
|
||||
unsigned int pipe,
|
||||
unsigned char *setup_packet,
|
||||
@@ -746,7 +879,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
|
||||
* Initializes a bulk urb with the proper information needed to submit it
|
||||
* to a device.
|
||||
*/
|
||||
static inline void usb_fill_bulk_urb (struct urb *urb,
|
||||
static __inline void usb_fill_bulk_urb (struct urb *urb,
|
||||
struct usb_device *dev,
|
||||
unsigned int pipe,
|
||||
void *transfer_buffer,
|
||||
@@ -781,7 +914,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
|
||||
* the endpoint interval, and express polling intervals in microframes
|
||||
* (eight per millisecond) rather than in frames (one per millisecond).
|
||||
*/
|
||||
static inline void usb_fill_int_urb (struct urb *urb,
|
||||
static __inline void usb_fill_int_urb (struct urb *urb,
|
||||
struct usb_device *dev,
|
||||
unsigned int pipe,
|
||||
void *transfer_buffer,
|
||||
@@ -805,28 +938,33 @@ static inline void usb_fill_int_urb (struct urb *urb,
|
||||
}
|
||||
|
||||
extern void STDCALL usb_init_urb(struct urb *urb);
|
||||
extern struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags);
|
||||
extern struct urb* STDCALL usb_alloc_urb(int iso_packets, unsigned mem_flags);
|
||||
extern void STDCALL usb_free_urb(struct urb *urb);
|
||||
#define usb_put_urb usb_free_urb
|
||||
extern struct urb STDCALL *usb_get_urb(struct urb *urb);
|
||||
extern int STDCALL usb_submit_urb(struct urb *urb, int mem_flags);
|
||||
extern struct urb* STDCALL usb_get_urb(struct urb *urb);
|
||||
extern int STDCALL usb_submit_urb(struct urb *urb, unsigned mem_flags);
|
||||
extern int STDCALL usb_unlink_urb(struct urb *urb);
|
||||
extern void STDCALL usb_kill_urb(struct urb *urb);
|
||||
|
||||
#define HAVE_USB_BUFFERS
|
||||
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
|
||||
int mem_flags, dma_addr_t *dma);
|
||||
unsigned mem_flags, dma_addr_t *dma);
|
||||
void usb_buffer_free (struct usb_device *dev, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
#if 0
|
||||
struct urb *usb_buffer_map (struct urb *urb);
|
||||
void usb_buffer_dmasync (struct urb *urb);
|
||||
void usb_buffer_unmap (struct urb *urb);
|
||||
#endif
|
||||
|
||||
struct scatterlist;
|
||||
int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
|
||||
struct scatterlist *sg, int nents);
|
||||
#if 0
|
||||
void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
|
||||
struct scatterlist *sg, int n_hw_ents);
|
||||
#endif
|
||||
void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
|
||||
struct scatterlist *sg, int n_hw_ents);
|
||||
|
||||
@@ -841,10 +979,14 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
|
||||
void *data, int len, int *actual_length,
|
||||
int timeout);
|
||||
|
||||
/* selective suspend/resume */
|
||||
extern int usb_suspend_device(struct usb_device *dev, pm_message_t message);
|
||||
extern int usb_resume_device(struct usb_device *dev);
|
||||
|
||||
|
||||
/* wrappers around usb_control_msg() for the most common standard requests */
|
||||
extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
|
||||
unsigned char descindex, void *buf, int size);
|
||||
extern int usb_get_device_descriptor(struct usb_device *dev);
|
||||
extern int usb_get_status(struct usb_device *dev,
|
||||
int type, int target, void *data);
|
||||
extern int usb_get_string(struct usb_device *dev,
|
||||
@@ -854,17 +996,17 @@ extern int usb_string(struct usb_device *dev, int index,
|
||||
|
||||
/* wrappers that also update important state inside usbcore */
|
||||
extern int usb_clear_halt(struct usb_device *dev, int pipe);
|
||||
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
||||
extern int usb_reset_configuration(struct usb_device *dev);
|
||||
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
|
||||
|
||||
/*
|
||||
* timeouts, in seconds, used for sending/receiving control messages
|
||||
* timeouts, in milliseconds, used for sending/receiving control messages
|
||||
* they typically complete within a few frames (msec) after they're issued
|
||||
* USB identifies 5 second timeouts, maybe more in a few cases, and a few
|
||||
* slow devices (like some MGE Ellipse UPSes) actually push that limit.
|
||||
*/
|
||||
#define USB_CTRL_GET_TIMEOUT 5
|
||||
#define USB_CTRL_SET_TIMEOUT 5
|
||||
#define USB_CTRL_GET_TIMEOUT 5000
|
||||
#define USB_CTRL_SET_TIMEOUT 5000
|
||||
|
||||
|
||||
/**
|
||||
@@ -887,8 +1029,10 @@ struct usb_sg_request {
|
||||
int status;
|
||||
size_t bytes;
|
||||
|
||||
// members not documented above are private to usbcore,
|
||||
// and are not provided for driver access!
|
||||
/*
|
||||
* members below are private to usbcore,
|
||||
* and are not provided for driver access!
|
||||
*/
|
||||
spinlock_t lock;
|
||||
|
||||
struct usb_device *dev;
|
||||
@@ -911,7 +1055,7 @@ int usb_sg_init (
|
||||
struct scatterlist *sg,
|
||||
int nents,
|
||||
size_t length,
|
||||
int mem_flags
|
||||
unsigned mem_flags
|
||||
);
|
||||
void usb_sg_cancel (struct usb_sg_request *io);
|
||||
void usb_sg_wait (struct usb_sg_request *io);
|
||||
@@ -920,55 +1064,35 @@ void usb_sg_wait (struct usb_sg_request *io);
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Calling this entity a "pipe" is glorifying it. A USB pipe
|
||||
* is something embarrassingly simple: it basically consists
|
||||
* of the following information:
|
||||
* - device number (7 bits)
|
||||
* - endpoint number (4 bits)
|
||||
* - current Data0/1 state (1 bit) [Historical; now gone]
|
||||
* - direction (1 bit)
|
||||
* - speed (1 bit) [Historical and specific to USB 1.1; now gone.]
|
||||
* - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.]
|
||||
* - pipe type (2 bits: control, interrupt, bulk, isochronous)
|
||||
* For various legacy reasons, Linux has a small cookie that's paired with
|
||||
* a struct usb_device to identify an endpoint queue. Queue characteristics
|
||||
* are defined by the endpoint's descriptor. This cookie is called a "pipe",
|
||||
* an unsigned int encoded as:
|
||||
*
|
||||
* That's 18 bits. Really. Nothing more. And the USB people have
|
||||
* documented these eighteen bits as some kind of glorious
|
||||
* virtual data structure.
|
||||
*
|
||||
* Let's not fall in that trap. We'll just encode it as a simple
|
||||
* unsigned int. The encoding is:
|
||||
*
|
||||
* - max size: bits 0-1 [Historical; now gone.]
|
||||
* - direction: bit 7 (0 = Host-to-Device [Out],
|
||||
* 1 = Device-to-Host [In] ...
|
||||
* like endpoint bEndpointAddress)
|
||||
* - device: bits 8-14 ... bit positions known to uhci-hcd
|
||||
* - device address: bits 8-14 ... bit positions known to uhci-hcd
|
||||
* - endpoint: bits 15-18 ... bit positions known to uhci-hcd
|
||||
* - Data0/1: bit 19 [Historical; now gone. ]
|
||||
* - lowspeed: bit 26 [Historical; now gone. ]
|
||||
* - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,
|
||||
* 10 = control, 11 = bulk)
|
||||
*
|
||||
* Why? Because it's arbitrary, and whatever encoding we select is really
|
||||
* up to us. This one happens to share a lot of bit positions with the UHCI
|
||||
* specification, so that much of the uhci driver can just mask the bits
|
||||
* appropriately.
|
||||
* Given the device address and endpoint descriptor, pipes are redundant.
|
||||
*/
|
||||
|
||||
/* NOTE: these are not the standard USB_ENDPOINT_XFER_* values!! */
|
||||
/* (yet ... they're the values used by usbfs) */
|
||||
#define PIPE_ISOCHRONOUS 0
|
||||
#define PIPE_INTERRUPT 1
|
||||
#define PIPE_CONTROL 2
|
||||
#define PIPE_BULK 3
|
||||
|
||||
#define usb_maxpacket(dev, pipe, out) (out \
|
||||
? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
|
||||
: (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )
|
||||
|
||||
#define usb_pipein(pipe) ((pipe) & USB_DIR_IN)
|
||||
#define usb_pipeout(pipe) (!usb_pipein(pipe))
|
||||
|
||||
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
|
||||
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
|
||||
|
||||
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
|
||||
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
|
||||
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
|
||||
@@ -980,12 +1104,8 @@ void usb_sg_wait (struct usb_sg_request *io);
|
||||
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
|
||||
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
|
||||
|
||||
/* Endpoint halt control/status ... likewise USE WITH CAUTION */
|
||||
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
|
||||
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
|
||||
|
||||
|
||||
static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
|
||||
static __inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
|
||||
{
|
||||
return (dev->devnum << 8) | (endpoint << 15);
|
||||
}
|
||||
@@ -1000,35 +1120,50 @@ static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int en
|
||||
#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
|
||||
#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static __inline __u16
|
||||
usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
|
||||
{
|
||||
struct usb_host_endpoint *ep;
|
||||
unsigned epnum = usb_pipeendpoint(pipe);
|
||||
|
||||
if (is_out) {
|
||||
WARN_ON(usb_pipein(pipe));
|
||||
ep = udev->ep_out[epnum];
|
||||
} else {
|
||||
WARN_ON(usb_pipeout(pipe));
|
||||
ep = udev->ep_in[epnum];
|
||||
}
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
/* NOTE: only 0x07ff bits are for packet size... */
|
||||
return le16_to_cpu(ep->desc.wMaxPacketSize);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Debugging and troubleshooting/diagnostic helpers.
|
||||
*/
|
||||
void usb_show_device_descriptor(struct usb_device_descriptor *);
|
||||
void usb_show_config_descriptor(struct usb_config_descriptor *);
|
||||
void usb_show_interface_descriptor(struct usb_interface_descriptor *);
|
||||
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *);
|
||||
void usb_show_device(struct usb_device *);
|
||||
void usb_show_string(struct usb_device *dev, char *id, int index);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
|
||||
#else
|
||||
#define dbg(format, arg...) do {} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
|
||||
#if defined(__GNUC__)
|
||||
#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
|
||||
#elif defined(_MSC_VER)
|
||||
#define dbg DPRINT
|
||||
#define err(...) DPRINT1(__VA_ARGS__)
|
||||
#define info DPRINT
|
||||
#define warn DPRINT1
|
||||
#else
|
||||
#error Unrecognized compiler!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MODE
|
||||
#define info(format, arg...) do {} while (0)
|
||||
#define dbg(format, arg...) do {} while (0)
|
||||
#define err(format, arg...) do {} while (0)
|
||||
#define info(format, arg...) do {} while (0)
|
||||
#define warn(format, arg...) do {} while (0)
|
||||
#endif
|
||||
|
||||
|
@@ -6,11 +6,14 @@
|
||||
*
|
||||
* - the master/host side Linux-USB kernel driver API;
|
||||
* - the "usbfs" user space API; and
|
||||
* - (eventually) a Linux "gadget" slave/device side driver API.
|
||||
* - the Linux "gadget" slave/device/peripheral side driver API.
|
||||
*
|
||||
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
|
||||
* act either as a USB master/host or as a USB slave/device. That means
|
||||
* the master and slave side APIs will benefit from working well together.
|
||||
* the master and slave side APIs benefit from working well together.
|
||||
*
|
||||
* There's also "Wireless USB", using low power short range radios for
|
||||
* peripheral interconnection but otherwise building on the USB framework.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CH9_H
|
||||
@@ -68,6 +71,35 @@
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
|
||||
#define USB_REQ_GET_ENCRYPTION 0x0E
|
||||
#define USB_REQ_SET_HANDSHAKE 0x0F
|
||||
#define USB_REQ_GET_HANDSHAKE 0x10
|
||||
#define USB_REQ_SET_CONNECTION 0x11
|
||||
#define USB_REQ_SET_SECURITY_DATA 0x12
|
||||
#define USB_REQ_GET_SECURITY_DATA 0x13
|
||||
#define USB_REQ_SET_WUSB_DATA 0x14
|
||||
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
|
||||
#define USB_REQ_LOOPBACK_DATA_READ 0x16
|
||||
#define USB_REQ_SET_INTERFACE_DS 0x17
|
||||
|
||||
/*
|
||||
* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
|
||||
* are read as a bit array returned by USB_REQ_GET_STATUS. (So there
|
||||
* are at most sixteen features of each type.)
|
||||
*/
|
||||
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
|
||||
#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
|
||||
#define USB_DEVICE_BATTERY 2 /* (wireless) */
|
||||
#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
|
||||
#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
|
||||
#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
|
||||
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
|
||||
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
|
||||
|
||||
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
|
||||
|
||||
|
||||
/**
|
||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||
@@ -86,14 +118,15 @@
|
||||
* For most devices, interfaces don't coordinate with each other, so
|
||||
* such requests may be made at any time.
|
||||
*/
|
||||
#include <pshpack1.h>
|
||||
struct usb_ctrlrequest {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
__le16 wValue;
|
||||
__le16 wIndex;
|
||||
__le16 wLength;
|
||||
};
|
||||
#include <poppack.h>
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -116,12 +149,31 @@ struct usb_ctrlrequest {
|
||||
#define USB_DT_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_INTERFACE_POWER 0x08
|
||||
/* these are from a minor usb 2.0 revision (ECN) */
|
||||
#define USB_DT_OTG 0x09
|
||||
#define USB_DT_DEBUG 0x0a
|
||||
#define USB_DT_INTERFACE_ASSOCIATION 0x0b
|
||||
/* these are from the Wireless USB spec */
|
||||
#define USB_DT_SECURITY 0x0c
|
||||
#define USB_DT_KEY 0x0d
|
||||
#define USB_DT_ENCRYPTION_TYPE 0x0e
|
||||
#define USB_DT_BOS 0x0f
|
||||
#define USB_DT_DEVICE_CAPABILITY 0x10
|
||||
#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
|
||||
|
||||
/* conventional codes for class-specific descriptors */
|
||||
#define USB_DT_CS_DEVICE 0x21
|
||||
#define USB_DT_CS_CONFIG 0x22
|
||||
#define USB_DT_CS_STRING 0x23
|
||||
#define USB_DT_CS_INTERFACE 0x24
|
||||
#define USB_DT_CS_ENDPOINT 0x25
|
||||
|
||||
/* All standard descriptors have these 2 fields at the beginning */
|
||||
#include <pshpack1.h>
|
||||
struct usb_descriptor_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -131,19 +183,19 @@ struct usb_device_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__le16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u16 bcdDevice;
|
||||
__le16 idVendor;
|
||||
__le16 idProduct;
|
||||
__le16 bcdDevice;
|
||||
__u8 iManufacturer;
|
||||
__u8 iProduct;
|
||||
__u8 iSerialNumber;
|
||||
__u8 bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
|
||||
@@ -165,6 +217,8 @@ struct usb_device_descriptor {
|
||||
#define USB_CLASS_CDC_DATA 0x0a
|
||||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
|
||||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
|
||||
#define USB_CLASS_VIDEO 0x0e
|
||||
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
@@ -182,13 +236,13 @@ struct usb_config_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wTotalLength;
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumInterfaces;
|
||||
__u8 bConfigurationValue;
|
||||
__u8 iConfiguration;
|
||||
__u8 bmAttributes;
|
||||
__u8 bMaxPower;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
|
||||
@@ -196,6 +250,7 @@ struct usb_config_descriptor {
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
|
||||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
|
||||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
|
||||
#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -204,8 +259,8 @@ struct usb_string_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wData[1]; /* UTF-16LE encoded */
|
||||
} __attribute__ ((packed));
|
||||
__le16 wData[1]; /* UTF-16LE encoded */
|
||||
};
|
||||
|
||||
/* note that "string" zero is special, it holds language codes that
|
||||
* the device supports, not Unicode characters.
|
||||
@@ -225,7 +280,7 @@ struct usb_interface_descriptor {
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
__u8 iInterface;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
|
||||
@@ -238,14 +293,14 @@ struct usb_endpoint_descriptor {
|
||||
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmAttributes;
|
||||
__u16 wMaxPacketSize;
|
||||
__le16 wMaxPacketSize;
|
||||
__u8 bInterval;
|
||||
|
||||
// NOTE: these two are _only_ in audio endpoints.
|
||||
// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
|
||||
/* NOTE: these two are _only_ in audio endpoints. */
|
||||
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
|
||||
__u8 bRefresh;
|
||||
__u8 bSynchAddress;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
@@ -262,6 +317,7 @@ struct usb_endpoint_descriptor {
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -271,16 +327,199 @@ struct usb_qualifier_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__le16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u8 bNumConfigurations;
|
||||
__u8 bRESERVED;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_OTG (from OTG 1.0a supplement) */
|
||||
struct usb_otg_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bmAttributes; /* support for HNP, SRP, etc */
|
||||
};
|
||||
#include <poppack.h>
|
||||
/* from usb_otg_descriptor.bmAttributes */
|
||||
#define USB_OTG_SRP (1 << 0)
|
||||
#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
|
||||
struct usb_debug_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
/* bulk endpoints with 8 byte maxpacket */
|
||||
__u8 bDebugInEndpoint;
|
||||
__u8 bDebugOutEndpoint;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#include <pshpack1.h>
|
||||
/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
|
||||
struct usb_interface_assoc_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bFirstInterface;
|
||||
__u8 bInterfaceCount;
|
||||
__u8 bFunctionClass;
|
||||
__u8 bFunctionSubClass;
|
||||
__u8 bFunctionProtocol;
|
||||
__u8 iFunction;
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_SECURITY: group of wireless security descriptors, including
|
||||
* encryption types available for setting up a CC/association.
|
||||
*/
|
||||
struct usb_security_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumEncryptionTypes;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys
|
||||
* may be retrieved.
|
||||
*/
|
||||
struct usb_key_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 tTKID[3];
|
||||
__u8 bReserved;
|
||||
__u8 bKeyData[0];
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */
|
||||
struct usb_encryption_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEncryptionType;
|
||||
#define USB_ENC_TYPE_UNSECURE 0
|
||||
#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */
|
||||
#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */
|
||||
#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */
|
||||
__u8 bEncryptionValue; /* use in SET_ENCRYPTION */
|
||||
__u8 bAuthKeyIndex;
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_BOS: group of wireless capabilities */
|
||||
struct usb_bos_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__le16 wTotalLength;
|
||||
__u8 bNumDeviceCaps;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */
|
||||
struct usb_dev_cap_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
};
|
||||
|
||||
#define USB_CAP_TYPE_WIRELESS_USB 1
|
||||
|
||||
struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDevCapabilityType;
|
||||
|
||||
__u8 bmAttributes;
|
||||
#define USB_WIRELESS_P2P_DRD (1 << 1)
|
||||
#define USB_WIRELESS_BEACON_MASK (3 << 2)
|
||||
#define USB_WIRELESS_BEACON_SELF (1 << 2)
|
||||
#define USB_WIRELESS_BEACON_DIRECTED (2 << 2)
|
||||
#define USB_WIRELESS_BEACON_NONE (3 << 2)
|
||||
__le16 wPHYRates; /* bit rates, Mbps */
|
||||
#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */
|
||||
#define USB_WIRELESS_PHY_80 (1 << 1)
|
||||
#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */
|
||||
#define USB_WIRELESS_PHY_160 (1 << 3)
|
||||
#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */
|
||||
#define USB_WIRELESS_PHY_320 (1 << 5)
|
||||
#define USB_WIRELESS_PHY_400 (1 << 6)
|
||||
#define USB_WIRELESS_PHY_480 (1 << 7)
|
||||
__u8 bmTFITXPowerInfo; /* TFI power levels */
|
||||
__u8 bmFFITXPowerInfo; /* FFI power levels */
|
||||
__le16 bmBandGroup;
|
||||
__u8 bReserved;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
|
||||
* each endpoint descriptor for a wireless device
|
||||
*/
|
||||
struct usb_wireless_ep_comp_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bMaxBurst;
|
||||
__u8 bMaxSequence;
|
||||
__le16 wMaxStreamDelay;
|
||||
__le16 wOverTheAirPacketSize;
|
||||
__u8 bOverTheAirInterval;
|
||||
__u8 bmCompAttributes;
|
||||
#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */
|
||||
#define USB_ENDPOINT_SWITCH_NO 0
|
||||
#define USB_ENDPOINT_SWITCH_SWITCH 1
|
||||
#define USB_ENDPOINT_SWITCH_SCALE 2
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
|
||||
* host and a device for connection set up, mutual authentication, and
|
||||
* exchanging short lived session keys. The handshake depends on a CC.
|
||||
*/
|
||||
struct usb_handshake {
|
||||
__u8 bMessageNumber;
|
||||
__u8 bStatus;
|
||||
__u8 tTKID[3];
|
||||
__u8 bReserved;
|
||||
__u8 CDID[16];
|
||||
__u8 nonce[16];
|
||||
__u8 MIC[8];
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
|
||||
* A CC may also be set up using non-wireless secure channels (including
|
||||
* wired USB!), and some devices may support CCs with multiple hosts.
|
||||
*/
|
||||
struct usb_connection_context {
|
||||
__u8 CHID[16]; /* persistent host id */
|
||||
__u8 CDID[16]; /* device id (unique w/in host context) */
|
||||
__u8 CK[16]; /* connection key */
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB 2.0 defines three speeds, here's how Linux identifies them */
|
||||
@@ -288,7 +527,8 @@ struct usb_qualifier_descriptor {
|
||||
enum usb_device_speed {
|
||||
USB_SPEED_UNKNOWN = 0, /* enumerating */
|
||||
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
|
||||
USB_SPEED_HIGH /* usb 2.0 */
|
||||
USB_SPEED_HIGH, /* usb 2.0 */
|
||||
USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
|
||||
};
|
||||
|
||||
enum usb_device_state {
|
||||
|
@@ -32,6 +32,7 @@ int need_wakeup;
|
||||
int my_jiffies;
|
||||
|
||||
struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
PKDEFERRED_ROUTINE timer_dpcs[MAX_TIMERS];
|
||||
struct dummy_process act_cur={0};
|
||||
struct dummy_process *my_current;
|
||||
|
||||
@@ -58,6 +59,13 @@ void init_wrapper(struct pci_dev *probe_dev)
|
||||
main_timer_list[n]=NULL;
|
||||
}
|
||||
|
||||
// FIXME: Change if more than 5 timers
|
||||
timer_dpcs[0] = (PKDEFERRED_ROUTINE)_TimerDpc0;
|
||||
timer_dpcs[1] = (PKDEFERRED_ROUTINE)_TimerDpc1;
|
||||
timer_dpcs[2] = (PKDEFERRED_ROUTINE)_TimerDpc2;
|
||||
timer_dpcs[3] = (PKDEFERRED_ROUTINE)_TimerDpc3;
|
||||
timer_dpcs[4] = (PKDEFERRED_ROUTINE)_TimerDpc4;
|
||||
|
||||
my_jiffies=0;
|
||||
num_irqs=0;
|
||||
my_current=&act_cur;
|
||||
@@ -117,7 +125,7 @@ void do_all_timers(void)
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Purpose: Remember thread procedure and data in global var
|
||||
// ReactOS Purpose: Create real kernel thread
|
||||
int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags)
|
||||
int my_kernel_thread(int (STDCALL *handler)(void*), void* parm, int flags)
|
||||
{
|
||||
HANDLE hThread = NULL;
|
||||
//thread_handler=handler;
|
||||
@@ -160,11 +168,12 @@ int my_kill_proc(int pid, int signal, int unk)
|
||||
|
||||
|
||||
/* calls probe function for hotplug (which does device matching), this is the
|
||||
only link between usbcore and the registered device drivers! */
|
||||
only link between usbcore and the registered device drivers! */
|
||||
int my_device_add(struct device *dev)
|
||||
{
|
||||
int n,found=0;
|
||||
printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe);
|
||||
//printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe);
|
||||
printk("drv_num %i %p\n",drvs_num,m_drivers[0]->probe);
|
||||
|
||||
if (dev->driver)
|
||||
{
|
||||
@@ -179,7 +188,6 @@ int my_device_add(struct device *dev)
|
||||
{
|
||||
dev->driver=m_drivers[n];
|
||||
printk("probe%i %p\n",n,m_drivers[n]->probe);
|
||||
|
||||
if (m_drivers[n]->probe(dev) == 0)
|
||||
{
|
||||
// return 0;
|
||||
@@ -225,6 +233,7 @@ void my_device_initialize(struct device *dev)
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wake_up(PKEVENT evnt)
|
||||
{
|
||||
//DPRINT1("wake_up(), evnt=%p\n", evnt);
|
||||
need_wakeup=1;
|
||||
|
||||
KeSetEvent(evnt, 0, FALSE); // Signal event
|
||||
@@ -234,6 +243,7 @@ void my_init_waitqueue_head(PKEVENT evnt)
|
||||
{
|
||||
// this is used only in core/message.c, and it isn't needed there
|
||||
//KeInitializeEvent(evnt, NotificationEvent, TRUE); // signalled state
|
||||
DPRINT1("init_waitqueue_head(), evnt=%p\n", evnt);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* wait until woken up (only one wait allowed!) */
|
||||
@@ -242,12 +252,7 @@ extern unsigned int LAST_USB_IRQ;
|
||||
int my_schedule_timeout(int x)
|
||||
{
|
||||
LONGLONG HH;
|
||||
//LONGLONG temp;
|
||||
LARGE_INTEGER delay;
|
||||
//PULONG tmp_debug=NULL;
|
||||
//extern unsigned int LAST_USB_EVENT_TICK;
|
||||
|
||||
//*tmp_debug = 0xFFAAFFAA;
|
||||
|
||||
printk("schedule_timeout: %d ms\n", x);
|
||||
|
||||
@@ -263,14 +268,8 @@ int my_schedule_timeout(int x)
|
||||
while(x>0)
|
||||
{
|
||||
KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008);
|
||||
//temp = HH - LAST_USB_EVENT_TICK;
|
||||
|
||||
//if (temp>(3579)) { //3579 = 1ms!
|
||||
//if (temp>1000) {
|
||||
do_all_timers();
|
||||
// LAST_USB_EVENT_TICK = HH;
|
||||
//}
|
||||
|
||||
do_all_timers();
|
||||
handle_irqs(-1);
|
||||
|
||||
if (need_wakeup)
|
||||
@@ -290,49 +289,35 @@ int my_schedule_timeout(int x)
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wait_for_completion(struct completion *x)
|
||||
{
|
||||
// LONGLONG HH;
|
||||
// LONGLONG temp;
|
||||
LARGE_INTEGER delay;
|
||||
|
||||
//extern unsigned int LAST_USB_EVENT_TICK;
|
||||
|
||||
printk("wait for completion, x=0x%08x\n", (DWORD)x);
|
||||
|
||||
int n=10;
|
||||
n = n*1000; // to us format
|
||||
|
||||
while(!x->done && (n>0))
|
||||
{
|
||||
//KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008);
|
||||
//temp = HH - LAST_USB_EVENT_TICK;
|
||||
|
||||
//if (temp>(3579)) {
|
||||
//if (temp>(1000)) {
|
||||
do_all_timers();
|
||||
// LAST_USB_EVENT_TICK = HH;
|
||||
//}
|
||||
|
||||
handle_irqs(-1);
|
||||
|
||||
delay.QuadPart = -10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1);
|
||||
n--;
|
||||
}
|
||||
printk("wait for completion done %i\n",x->done);
|
||||
|
||||
//printk("wait for completion, x=0x%08x, x->done=%d\n", (DWORD)x, x->done);
|
||||
KeWaitForSingleObject(&x->wait, Executive, KernelMode, FALSE, NULL);
|
||||
KeClearEvent(&x->wait);
|
||||
x->done--;
|
||||
//printk("wait for completion done %i\n",x->done);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_init_completion(struct completion *x)
|
||||
{
|
||||
//DPRINT1("init_completion(), x=%p\n", x);
|
||||
x->done=0;
|
||||
KeInitializeEvent(&x->wait, NotificationEvent, FALSE);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_interruptible_sleep_on(PKEVENT evnt)
|
||||
{
|
||||
DPRINT1("interruptible_sleep_on(), evnt=%p\n", evnt);
|
||||
KeWaitForSingleObject(evnt, Executive, KernelMode, FALSE, NULL);
|
||||
KeClearEvent(evnt); // reset to not-signalled
|
||||
}
|
||||
|
||||
// Some kind of a hack currently
|
||||
void my_try_to_freeze()
|
||||
{
|
||||
LARGE_INTEGER delay;
|
||||
delay.QuadPart = -100000; // 0.1 seconds
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &delay);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Helper for pci_module_init
|
||||
/*------------------------------------------------------------------------*/
|
||||
@@ -354,16 +339,6 @@ struct pci_dev *my_pci_find_slot(int a,int b)
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
|
||||
{
|
||||
//dev->bus, dev->devfn, where, val
|
||||
PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
//FIXME: Is returning this value correct?
|
||||
//FIXME: Mixing pci_dev and win structs isn't a good thing at all
|
||||
return HalSetBusDataByOffset(PCIConfiguration, dev->bus->number, dev_ext->SystemIoSlotNumber, &val, where, sizeof(val));
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_request_irq(unsigned int irq,
|
||||
int (*handler)(int,void *, struct pt_regs *),
|
||||
unsigned long mode, const char *desc, void *data)
|
||||
@@ -444,11 +419,6 @@ init_dma(PUSBMP_DEVICE_EXTENSION pDevExt)
|
||||
{
|
||||
// Prepare device descriptor structure
|
||||
DEVICE_DESCRIPTION dd;
|
||||
#ifdef USB_DMA_SINGLE_SUPPORT
|
||||
KEVENT DMAEvent;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status;
|
||||
#endif
|
||||
|
||||
RtlZeroMemory( &dd, sizeof(dd) );
|
||||
dd.Version = DEVICE_DESCRIPTION_VERSION;
|
||||
@@ -482,89 +452,57 @@ init_dma(PUSBMP_DEVICE_EXTENSION pDevExt)
|
||||
if (pDevExt->pDmaAdapter == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
#ifdef USB_DMA_SINGLE_SUPPORT
|
||||
/* Allocate buffer now */
|
||||
pDevExt->BufferSize = pDevExt->mapRegisterCount * PAGE_SIZE;
|
||||
DPRINT1("Bufsize = %u\n", pDevExt->BufferSize);
|
||||
pDevExt->VirtualBuffer = pDevExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer(
|
||||
pDevExt->pDmaAdapter, pDevExt->BufferSize, &pDevExt->Buffer, FALSE);
|
||||
DPRINT1("Bufsize = %u, Buffer = 0x%x", pDevExt->BufferSize, pDevExt->Buffer.LowPart);
|
||||
|
||||
if (!pDevExt->VirtualBuffer)
|
||||
{
|
||||
DPRINT1("Could not allocate buffer\n");
|
||||
// should try again with smaller buffer...
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
DPRINT1("Calling IoAllocateMdl()\n");
|
||||
pDevExt->Mdl = IoAllocateMdl(pDevExt->VirtualBuffer, pDevExt->BufferSize, FALSE, FALSE, NULL);
|
||||
DPRINT1("Bufsize == %u\n", pDevExt->BufferSize);
|
||||
|
||||
if (!pDevExt->Mdl)
|
||||
{
|
||||
DPRINT1("IoAllocateMdl() FAILED\n");
|
||||
//TODO: Free the HAL buffer
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
DPRINT1("VBuffer == 0x%x Mdl == %u Bufsize == %u\n", pDevExt->VirtualBuffer, pDevExt->Mdl, pDevExt->BufferSize);
|
||||
|
||||
DPRINT1("Calling MmBuildMdlForNonPagedPool\n");
|
||||
MmBuildMdlForNonPagedPool(pDevExt->Mdl);
|
||||
|
||||
|
||||
/* Get map registers for DMA */
|
||||
KeInitializeEvent(&DMAEvent, SynchronizationEvent, FALSE);
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
// TODO: Free adapter channel somewhere
|
||||
Status = pDevExt->pDmaAdapter->DmaOperations->AllocateAdapterChannel(pDevExt->pDmaAdapter,
|
||||
pDevExt->PhysicalDeviceObject, pDevExt->mapRegisterCount, MapRegisterCallback, &DMAEvent);
|
||||
KeLowerIrql(OldIrql);
|
||||
|
||||
DPRINT1("VBuffer == 0x%x Bufsize == %u\n", pDevExt->VirtualBuffer, pDevExt->BufferSize);
|
||||
KeWaitForSingleObject(&DMAEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT("init_dma(): unable to allocate adapter channels\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
#endif
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Acquire map registers in prep for DMA
|
||||
* ARGUMENTS:
|
||||
* DeviceObject: unused
|
||||
* Irp: unused
|
||||
* MapRegisterBase: returned to blocked thread via a member var
|
||||
* Context: contains a pointer to the right ControllerInfo
|
||||
* struct
|
||||
* RETURNS:
|
||||
* KeepObject, because that's what the DDK says to do
|
||||
*/
|
||||
#ifdef USB_DMA_SINGLE_SUPPORT
|
||||
static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID MapRegisterBase,
|
||||
PVOID Context)
|
||||
Timer DPCs
|
||||
*/
|
||||
void STDCALL _TimerDpc0(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
|
||||
{
|
||||
PUSBMP_DEVICE_EXTENSION pDevExt = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
UNREFERENCED_PARAMETER(Irp);
|
||||
|
||||
DPRINT("usb_linuxwrapper: MapRegisterCallback Called, base=0x%08x\n", MapRegisterBase);
|
||||
|
||||
pDevExt->MapRegisterBase = MapRegisterBase;
|
||||
|
||||
// signal that we are finished
|
||||
KeSetEvent(Context, 0, FALSE);
|
||||
|
||||
return KeepObject;//DeallocateObjectKeepRegisters;
|
||||
int n = 0;
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
//printk("TimerDpc0\n");
|
||||
function(data);
|
||||
//handle_irqs(-1);
|
||||
}
|
||||
|
||||
void STDCALL _TimerDpc1(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
|
||||
{
|
||||
int n = 1;
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
printk("TimerDpc1\n");
|
||||
function(data);
|
||||
}
|
||||
|
||||
void STDCALL _TimerDpc2(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
|
||||
{
|
||||
int n = 2;
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
printk("TimerDpc2\n");
|
||||
//function(data);
|
||||
}
|
||||
|
||||
void STDCALL _TimerDpc3(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
|
||||
{
|
||||
int n = 3;
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
printk("TimerDpc3\n");
|
||||
//function(data);
|
||||
}
|
||||
|
||||
void STDCALL _TimerDpc4(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
|
||||
{
|
||||
int n = 4;
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
printk("TimerDpc4\n");
|
||||
//function(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *my_dma_pool_alloc(struct dma_pool *pool, int gfp_flags, dma_addr_t *dma_handle)
|
||||
{
|
||||
@@ -597,7 +535,7 @@ If allocation is nonzero, objects returned from pci_pool_alloc won't cross that
|
||||
This is useful for devices which have addressing restrictions on individual DMA transfers, such
|
||||
as not crossing boundaries of 4KBytes.
|
||||
*/
|
||||
struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, size_t size, size_t align, size_t allocation)
|
||||
struct pci_pool *my_pci_pool_create(const char * name, struct device * pdev, size_t size, size_t align, size_t allocation)
|
||||
{
|
||||
struct pci_pool *retval;
|
||||
|
||||
@@ -637,7 +575,7 @@ struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, si
|
||||
retval->blocks_allocated = 0;
|
||||
|
||||
DPRINT("pci_pool_create(): %s/%s size %d, %d/page (%d alloc)\n",
|
||||
pdev ? pdev->slot_name : NULL, retval->name, size,
|
||||
pdev ? pdev->name : NULL, retval->name, size,
|
||||
retval->blocks_per_page, allocation);
|
||||
|
||||
return retval;
|
||||
@@ -664,7 +602,7 @@ address through the handle. If such a memory block can't be allocated, null is r
|
||||
void * my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_handle)
|
||||
{
|
||||
PVOID result;
|
||||
PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)pool->pdev->dev_ext;
|
||||
PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)to_pci_dev(pool->pdev)->dev_ext;
|
||||
int page=0, offset;
|
||||
int map, i, block;
|
||||
|
||||
@@ -763,7 +701,7 @@ void my_pci_pool_free (struct pci_pool * pool, void * vaddr, dma_addr_t dma)
|
||||
set_bit (block, &pool->pages[page].bitmap[map]);
|
||||
|
||||
pool->blocks_allocated--;
|
||||
//DPRINT("pci_pool_free(): alloc'd: %d\n", pool->blocks_allocated);
|
||||
DPRINT("pci_pool_free(): alloc'd: %d\n", pool->blocks_allocated);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -780,17 +718,18 @@ Description
|
||||
Caller guarantees that no more memory from the pool is in use, and that nothing will try to
|
||||
use the pool after this call.
|
||||
*/
|
||||
void __inline__ my_pci_pool_destroy (struct pci_pool * pool)
|
||||
void my_pci_pool_destroy (struct pci_pool * pool)
|
||||
{
|
||||
DPRINT1("pci_pool_destroy(): alloc'd: %d, UNIMPLEMENTED\n", pool->blocks_allocated);
|
||||
|
||||
ExFreePool(pool);
|
||||
}
|
||||
|
||||
// the code here is identical to dma_alloc_coherent
|
||||
void *my_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
|
||||
{
|
||||
PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)hwdev->dev_ext;
|
||||
DPRINT1("pci_alloc_consistent() size=%d\n", size);
|
||||
DPRINT1("pci_alloc_consistent() size=%d, dma_handle=%p\n", size, (PPHYSICAL_ADDRESS)dma_handle);
|
||||
|
||||
return devExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer(devExt->pDmaAdapter, size, (PPHYSICAL_ADDRESS)dma_handle, FALSE); //FIXME: Cache-enabled?
|
||||
}
|
||||
@@ -881,26 +820,198 @@ void my_pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size
|
||||
my_dma_unmap_single(&hwdev->dev, dma_addr, size, direction);
|
||||
}
|
||||
|
||||
// the code here is very similar to pci_alloc_consistent()
|
||||
void *my_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
//struct pci_dev *pdev = to_pci_dev(dev);
|
||||
//return my_pci_alloc_consistent(pdev, sz, dma_handle);
|
||||
|
||||
PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
DPRINT1("dma_alloc_coherent() size=%d, dev=%p, dev_ext=%p, dma_handle=%p, DmaAdapter=%p\n", size, dev, dev->dev_ext, (PPHYSICAL_ADDRESS)dma_handle, devExt->pDmaAdapter);
|
||||
|
||||
return devExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer(devExt->pDmaAdapter, size, (PPHYSICAL_ADDRESS)dma_handle, FALSE); //FIXME: Cache-enabled?
|
||||
|
||||
}
|
||||
/*
|
||||
void dma_free_coherent(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle); */
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SPINLOCK routines */
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_spin_lock_init(spinlock_t *sl)
|
||||
{
|
||||
//DPRINT("spin_lock_init: %p\n", sl);
|
||||
KeInitializeSpinLock(&sl->SpinLock);
|
||||
}
|
||||
|
||||
void my_spin_lock(spinlock_t *sl)
|
||||
{
|
||||
//KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql);
|
||||
//DPRINT("spin_lock_: %p\n", sl);
|
||||
KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_unlock(spinlock_t *sl)
|
||||
{
|
||||
//KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql);
|
||||
//DPRINT("spin_unlock: %p\n", sl);
|
||||
KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_lock_irqsave(spinlock_t *sl, int flags)
|
||||
{
|
||||
my_spin_lock(sl);
|
||||
//DPRINT("spin_lock_irqsave: %p\n", sl);
|
||||
//my_spin_lock(sl);
|
||||
KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_unlock_irqrestore(spinlock_t *sl, int flags)
|
||||
{
|
||||
//DPRINT("spin_unlock_irqrestore: %p\n", sl);
|
||||
//my_spin_unlock(sl);
|
||||
KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_lock_irq(spinlock_t *sl)
|
||||
{
|
||||
//DPRINT("spin_lock_irq: %p\n", sl);
|
||||
//my_spin_lock(sl);
|
||||
KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_unlock_irq(spinlock_t *sl)
|
||||
{
|
||||
//DPRINT("spin_unlock_irq: %p\n", sl);
|
||||
//my_spin_unlock(sl);
|
||||
KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Misc routines */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/**
|
||||
* strlcpy - Copy a %NUL terminated string into a sized buffer
|
||||
* @dest: Where to copy the string to
|
||||
* @src: Where to copy the string from
|
||||
* @size: size of destination buffer
|
||||
*
|
||||
* Compatible with *BSD: the result is always a valid
|
||||
* NUL-terminated string that fits in the buffer (unless,
|
||||
* of course, the buffer size is zero). It does not pad
|
||||
* out the result like strncpy() does.
|
||||
*/
|
||||
size_t strlcpy(char *dest, const char *src, size_t size)
|
||||
{
|
||||
size_t ret = strlen(src);
|
||||
|
||||
if (size) {
|
||||
size_t len = (ret >= size) ? size-1 : ret;
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* kzalloc - allocate memory. The memory is set to zero.
|
||||
* @size: how many bytes of memory are required.
|
||||
* @flags: the type of memory to allocate.
|
||||
*/
|
||||
void *my_kzalloc(size_t size/*, gfp_t flags*/)
|
||||
{
|
||||
void *ret = kmalloc(size, flags);
|
||||
if (ret)
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* memcmp - Compare two areas of memory
|
||||
* @cs: One area of memory
|
||||
* @ct: Another area of memory
|
||||
* @count: The size of the area.
|
||||
*/
|
||||
int __cdecl memcmp(const void * cs,const void * ct,size_t count)
|
||||
{
|
||||
const unsigned char *su1, *su2;
|
||||
int res = 0;
|
||||
|
||||
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
if ((res = *su1 - *su2) != 0)
|
||||
break;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
|
||||
{
|
||||
//dev->bus, dev->devfn, where, val
|
||||
PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
//FIXME: Is returning this value correct?
|
||||
//FIXME: Mixing pci_dev and win structs isn't a good thing at all (though I doubt it wants to access device in another slot/bus)
|
||||
DPRINT1("pci_write_config_word: BusNum: %d, SlotNum: 0x%x, value: 0x%x, where: 0x%x\n",
|
||||
dev_ext->SystemIoBusNumber, dev_ext->SystemIoSlotNumber.u.AsULONG, val, where);
|
||||
return HalSetBusDataByOffset(PCIConfiguration, dev_ext->SystemIoBusNumber, dev_ext->SystemIoSlotNumber.u.AsULONG, &val, where, sizeof(val));
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
|
||||
{
|
||||
ULONG result;
|
||||
|
||||
//dev->bus, dev->devfn, where, val
|
||||
PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
//FIXME: Is returning this value correct?
|
||||
//FIXME: Mixing pci_dev and win structs isn't a good thing at all
|
||||
result = HalGetBusDataByOffset(PCIConfiguration, dev_ext->SystemIoBusNumber, dev_ext->SystemIoSlotNumber.u.AsULONG, val, where, sizeof(*val));
|
||||
DPRINT1("pci_read_config_word: BusNum: %d, SlotNum: 0x%x, value: 0x%x, where: 0x%x\n",
|
||||
dev_ext->SystemIoBusNumber, dev_ext->SystemIoSlotNumber.u.AsULONG, *val, where);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For compatibility with Windows XP */
|
||||
NTSTATUS
|
||||
_RtlDuplicateUnicodeString(
|
||||
IN ULONG Flags,
|
||||
IN PCUNICODE_STRING SourceString,
|
||||
OUT PUNICODE_STRING DestinationString)
|
||||
{
|
||||
if (SourceString == NULL || DestinationString == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
|
||||
if ((SourceString->Length == 0) &&
|
||||
(Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
|
||||
RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
|
||||
{
|
||||
DestinationString->Length = 0;
|
||||
DestinationString->MaximumLength = 0;
|
||||
DestinationString->Buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG DestMaxLength = SourceString->Length;
|
||||
|
||||
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
|
||||
DestMaxLength += sizeof(UNICODE_NULL);
|
||||
|
||||
DestinationString->Buffer = ExAllocatePool(PagedPool, DestMaxLength);
|
||||
if (DestinationString->Buffer == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
|
||||
DestinationString->Length = SourceString->Length;
|
||||
DestinationString->MaximumLength = DestMaxLength;
|
||||
|
||||
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
|
||||
DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<module name="sys_base" type="objectlibrary">
|
||||
<module name="sys_base" type="objectlibrary" allowwarnings="true">
|
||||
<define name="__USE_W32API" />
|
||||
<define name="DEBUG_MODE" />
|
||||
<include base="ntoskrnl">include</include>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include <ntos/types.h>
|
||||
//#include <extypes.h>
|
||||
|
||||
@@ -7,11 +9,46 @@
|
||||
Lots of definitions should go to corresponding files
|
||||
*/
|
||||
|
||||
#include <ntifs.h>
|
||||
//#include <ntifs.h>
|
||||
#include "ntddk.h"
|
||||
#include <kbdmou.h>
|
||||
#include <debug.h>
|
||||
|
||||
// a couple of defines
|
||||
#define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE 1
|
||||
#define RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING 2
|
||||
|
||||
// Define bit scan intrinsics, so we can use them without the need to include wnet ddk
|
||||
#if defined(_MSC_VER)
|
||||
#define BitScanForward _BitScanForward
|
||||
#define BitScanReverse _BitScanReverse
|
||||
#define InterlockedBitTestAndSet _interlockedbittestandset
|
||||
#define InterlockedBitTestAndReset _interlockedbittestandreset
|
||||
|
||||
BOOLEAN _BitScanForward (OUT ULONG *Index, IN ULONG Mask);
|
||||
BOOLEAN _BitScanReverse (OUT ULONG *Index, IN ULONG Mask);
|
||||
BOOLEAN _interlockedbittestandset (IN LONG *Base, IN LONG Offset);
|
||||
BOOLEAN _interlockedbittestandreset (IN LONG *Base, IN LONG Offset);
|
||||
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
#pragma intrinsic(_interlockedbittestandset)
|
||||
#pragma intrinsic(_interlockedbittestandreset)
|
||||
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
|
||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||
/*
|
||||
* FUNCTION: Assert a maximum value for the current irql
|
||||
* ARGUMENTS:
|
||||
* x = Maximum irql
|
||||
*/
|
||||
#define ASSERT_IRQL_LESS_OR_EQUAL(x) ASSERT(KeGetCurrentIrql()<=(x))
|
||||
#define ASSERT_IRQL_EQUAL(x) ASSERT(KeGetCurrentIrql()==(x))
|
||||
#define ASSERT_IRQL_LESS(x) ASSERT(KeGetCurrentIrql()<(x))
|
||||
|
||||
|
||||
void wait_ms(int mils);
|
||||
void my_udelay(int us);
|
||||
|
@@ -144,7 +144,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
|
||||
out += sprintf(out, "%*s Element != First TD\n", space, "");
|
||||
|
||||
while (tmp != head) {
|
||||
struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
|
||||
/*struct uhci_td **/td = list_entry(tmp, struct uhci_td, list);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
#define USBFRNUM 6
|
||||
#define USBFLBASEADD 8
|
||||
#define USBSOF 12
|
||||
#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */
|
||||
|
||||
/* USB port status and control registers */
|
||||
#define USBPORTSC1 16
|
||||
@@ -51,16 +52,25 @@
|
||||
#define USBPORTSC_CSC 0x0002 /* Connect Status Change */
|
||||
#define USBPORTSC_PE 0x0004 /* Port Enable */
|
||||
#define USBPORTSC_PEC 0x0008 /* Port Enable Change */
|
||||
#define USBPORTSC_LS 0x0030 /* Line Status */
|
||||
#define USBPORTSC_DPLUS 0x0010 /* D+ high (line status) */
|
||||
#define USBPORTSC_DMINUS 0x0020 /* D- high (line status) */
|
||||
#define USBPORTSC_RD 0x0040 /* Resume Detect */
|
||||
#define USBPORTSC_RES1 0x0080 /* reserved, always 1 */
|
||||
#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */
|
||||
#define USBPORTSC_PR 0x0200 /* Port Reset */
|
||||
/* OC and OCC from Intel 430TX and later (not UHCI 1.1d spec) */
|
||||
#define USBPORTSC_OC 0x0400 /* Over Current condition */
|
||||
#define USBPORTSC_OCC 0x0800 /* Over Current Change R/WC */
|
||||
#define USBPORTSC_SUSP 0x1000 /* Suspend */
|
||||
#define USBPORTSC_RES2 0x2000 /* reserved, write zeroes */
|
||||
#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */
|
||||
#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */
|
||||
|
||||
/* Legacy support register */
|
||||
#define USBLEGSUP 0xc0
|
||||
#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
|
||||
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
|
||||
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
|
||||
|
||||
#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
|
||||
|
||||
@@ -75,7 +85,7 @@
|
||||
#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */
|
||||
|
||||
struct uhci_frame_list {
|
||||
__u32 frame[UHCI_NUMFRAMES];
|
||||
__le32 frame[UHCI_NUMFRAMES];
|
||||
|
||||
void *frame_cpu[UHCI_NUMFRAMES];
|
||||
|
||||
@@ -98,25 +108,36 @@ struct urb_priv;
|
||||
* In the frame list, qh->link maintains a list of QHs seen by the HC:
|
||||
* skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ...
|
||||
*/
|
||||
#include <pshpck16.h>
|
||||
struct uhci_qh {
|
||||
/* Hardware fields */
|
||||
__u32 link; /* Next queue */
|
||||
__u32 element; /* Queue element pointer */
|
||||
__le32 link; /* Next queue */
|
||||
__le32 element; /* Queue element pointer */
|
||||
|
||||
/* Software fields */
|
||||
dma_addr_t dma_handle;
|
||||
|
||||
struct usb_device *dev;
|
||||
struct urb_priv *urbp;
|
||||
|
||||
struct list_head list; /* P: uhci->frame_list_lock */
|
||||
struct list_head remove_list; /* P: uhci->remove_list_lock */
|
||||
} __attribute__((aligned(16)));
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
/*
|
||||
* We need a special accessor for the element pointer because it is
|
||||
* subject to asynchronous updates by the controller
|
||||
*/
|
||||
static __le32 inline qh_element(struct uhci_qh *qh) {
|
||||
__le32 element = qh->element;
|
||||
|
||||
barrier();
|
||||
return element;
|
||||
}
|
||||
|
||||
/*
|
||||
* for TD <status>:
|
||||
*/
|
||||
#define td_status(td) le32_to_cpu((td)->status)
|
||||
#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */
|
||||
#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */
|
||||
#define TD_CTRL_C_ERR_SHIFT 27
|
||||
@@ -136,7 +157,7 @@ struct uhci_qh {
|
||||
TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
|
||||
|
||||
#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT)
|
||||
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xFE0000)
|
||||
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000)
|
||||
#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
|
||||
|
||||
/*
|
||||
@@ -178,31 +199,45 @@ struct uhci_qh {
|
||||
* td->link points to either another TD (not necessarily for the same urb or
|
||||
* even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs)
|
||||
*/
|
||||
#include <pshpck16.h>
|
||||
struct uhci_td {
|
||||
/* Hardware fields */
|
||||
__u32 link;
|
||||
__u32 status;
|
||||
__u32 token;
|
||||
__u32 buffer;
|
||||
__le32 link;
|
||||
__le32 status;
|
||||
__le32 token;
|
||||
__le32 buffer;
|
||||
|
||||
/* Software fields */
|
||||
dma_addr_t dma_handle;
|
||||
|
||||
struct usb_device *dev;
|
||||
struct urb *urb;
|
||||
|
||||
struct list_head list; /* P: urb->lock */
|
||||
struct list_head remove_list; /* P: uhci->td_remove_list_lock */
|
||||
|
||||
int frame; /* for iso: what frame? */
|
||||
struct list_head fl_list; /* P: uhci->frame_list_lock */
|
||||
} __attribute__((aligned(16)));
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
/*
|
||||
* We need a special accessor for the control/status word because it is
|
||||
* subject to asynchronous updates by the controller
|
||||
*/
|
||||
static u32 inline td_status(struct uhci_td *td) {
|
||||
__le32 status = td->status;
|
||||
|
||||
barrier();
|
||||
return le32_to_cpu(status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The UHCI driver places Interrupt, Control and Bulk into QH's both
|
||||
* to group together TD's for one transfer, and also to faciliate queuing
|
||||
* of URB's. To make it easy to insert entries into the schedule, we have
|
||||
* a skeleton of QH's for each predefined Interrupt latency, low speed
|
||||
* control, high speed control and terminating QH (see explanation for
|
||||
* a skeleton of QH's for each predefined Interrupt latency, low-speed
|
||||
* control, full-speed control and terminating QH (see explanation for
|
||||
* the terminating QH below).
|
||||
*
|
||||
* When we want to add a new QH, we add it to the end of the list for the
|
||||
@@ -217,9 +252,9 @@ struct uhci_td {
|
||||
* skel int32 QH
|
||||
* ...
|
||||
* skel int1 QH
|
||||
* skel low speed control QH
|
||||
* skel low-speed control QH
|
||||
* dev 5 control QH
|
||||
* skel high speed control QH
|
||||
* skel full-speed control QH
|
||||
* skel bulk QH
|
||||
* dev 1 bulk QH
|
||||
* dev 2 bulk QH
|
||||
@@ -228,7 +263,7 @@ struct uhci_td {
|
||||
* The terminating QH is used for 2 reasons:
|
||||
* - To place a terminating TD which is used to workaround a PIIX bug
|
||||
* (see Intel errata for explanation)
|
||||
* - To loop back to the high speed control queue for full speed bandwidth
|
||||
* - To loop back to the full-speed control queue for full-speed bandwidth
|
||||
* reclamation
|
||||
*
|
||||
* Isochronous transfers are stored before the start of the skeleton
|
||||
@@ -248,7 +283,7 @@ struct uhci_td {
|
||||
#define skel_int2_qh skelqh[6]
|
||||
#define skel_int1_qh skelqh[7]
|
||||
#define skel_ls_control_qh skelqh[8]
|
||||
#define skel_hs_control_qh skelqh[9]
|
||||
#define skel_fs_control_qh skelqh[9]
|
||||
#define skel_bulk_qh skelqh[10]
|
||||
#define skel_term_qh skelqh[11]
|
||||
|
||||
@@ -286,134 +321,155 @@ static inline int __interval_to_skel(int interval)
|
||||
}
|
||||
|
||||
/*
|
||||
* Device states for the host controller.
|
||||
* States for the root hub.
|
||||
*
|
||||
* To prevent "bouncing" in the presence of electrical noise,
|
||||
* we insist on a 1-second "grace" period, before switching to
|
||||
* the RUNNING or SUSPENDED states, during which the state is
|
||||
* not allowed to change.
|
||||
*
|
||||
* The resume process is divided into substates in order to avoid
|
||||
* potentially length delays during the timer handler.
|
||||
*
|
||||
* States in which the host controller is halted must have values <= 0.
|
||||
* when there are no devices attached we delay for 1 second in the
|
||||
* RUNNING_NODEVS state before switching to the AUTO_STOPPED state.
|
||||
*
|
||||
* (Note that the AUTO_STOPPED state won't be necessary once the hub
|
||||
* driver learns to autosuspend.)
|
||||
*/
|
||||
enum uhci_state {
|
||||
UHCI_RESET,
|
||||
UHCI_RUNNING_GRACE, /* Before RUNNING */
|
||||
UHCI_RUNNING, /* The normal state */
|
||||
UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */
|
||||
UHCI_SUSPENDED = -10, /* When no devices are attached */
|
||||
UHCI_RESUMING_1,
|
||||
UHCI_RESUMING_2
|
||||
};
|
||||
enum uhci_rh_state {
|
||||
/* In the following states the HC must be halted.
|
||||
* These two must come first */
|
||||
UHCI_RH_RESET,
|
||||
UHCI_RH_SUSPENDED,
|
||||
|
||||
#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
|
||||
UHCI_RH_AUTO_STOPPED,
|
||||
UHCI_RH_RESUMING,
|
||||
|
||||
/* In this state the HC changes from running to halted,
|
||||
* so it can legally appear either way. */
|
||||
UHCI_RH_SUSPENDING,
|
||||
|
||||
/* In the following states it's an error if the HC is halted.
|
||||
* These two must come last */
|
||||
UHCI_RH_RUNNING, /* The normal state */
|
||||
UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
|
||||
};
|
||||
|
||||
/*
|
||||
* This describes the full uhci information.
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs.
|
||||
*/
|
||||
struct uhci_hcd {
|
||||
struct usb_hcd hcd;
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
/* procfs */
|
||||
struct proc_dir_entry *proc_entry;
|
||||
#endif
|
||||
void *dentry;
|
||||
|
||||
/* Grabbed from PCI */
|
||||
unsigned long io_addr;
|
||||
|
||||
struct pci_pool *qh_pool;
|
||||
struct pci_pool *td_pool;
|
||||
|
||||
struct usb_bus *bus;
|
||||
struct dma_pool *qh_pool;
|
||||
struct dma_pool *td_pool;
|
||||
|
||||
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
|
||||
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
|
||||
|
||||
spinlock_t frame_list_lock;
|
||||
struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */
|
||||
int fsbr; /* Full speed bandwidth reclamation */
|
||||
spinlock_t lock;
|
||||
struct uhci_frame_list *fl; /* P: uhci->lock */
|
||||
int fsbr; /* Full-speed bandwidth reclamation */
|
||||
unsigned long fsbrtimeout; /* FSBR delay */
|
||||
|
||||
enum uhci_state state; /* FIXME: needs a spinlock */
|
||||
unsigned long state_end; /* Time of next transition */
|
||||
int resume_detect; /* Need a Global Resume */
|
||||
enum uhci_rh_state rh_state;
|
||||
unsigned long auto_stop_time; /* When to AUTO_STOP */
|
||||
|
||||
unsigned int frame_number; /* As of last check */
|
||||
unsigned int is_stopped;
|
||||
#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */
|
||||
|
||||
unsigned int scan_in_progress:1; /* Schedule scan is running */
|
||||
unsigned int need_rescan:1; /* Redo the schedule scan */
|
||||
unsigned int hc_inaccessible:1; /* HC is suspended or dead */
|
||||
unsigned int working_RD:1; /* Suspended root hub doesn't
|
||||
need to be polled */
|
||||
|
||||
/* Support for port suspend/resume/reset */
|
||||
unsigned long port_c_suspend; /* Bit-arrays of ports */
|
||||
unsigned long suspended_ports;
|
||||
unsigned long resuming_ports;
|
||||
unsigned long ports_timeout; /* Time to stop signalling */
|
||||
|
||||
/* Main list of URB's currently controlled by this HC */
|
||||
spinlock_t urb_list_lock;
|
||||
struct list_head urb_list; /* P: uhci->urb_list_lock */
|
||||
struct list_head urb_list; /* P: uhci->lock */
|
||||
|
||||
/* List of QH's that are done, but waiting to be unlinked (race) */
|
||||
spinlock_t qh_remove_list_lock;
|
||||
struct list_head qh_remove_list; /* P: uhci->qh_remove_list_lock */
|
||||
struct list_head qh_remove_list; /* P: uhci->lock */
|
||||
unsigned int qh_remove_age; /* Age in frames */
|
||||
|
||||
/* List of TD's that are done, but waiting to be freed (race) */
|
||||
struct list_head td_remove_list; /* P: uhci->lock */
|
||||
unsigned int td_remove_age; /* Age in frames */
|
||||
|
||||
/* List of asynchronously unlinked URB's */
|
||||
spinlock_t urb_remove_list_lock;
|
||||
struct list_head urb_remove_list; /* P: uhci->urb_remove_list_lock */
|
||||
struct list_head urb_remove_list; /* P: uhci->lock */
|
||||
unsigned int urb_remove_age; /* Age in frames */
|
||||
|
||||
/* List of URB's awaiting completion callback */
|
||||
spinlock_t complete_list_lock;
|
||||
struct list_head complete_list; /* P: uhci->complete_list_lock */
|
||||
struct list_head complete_list; /* P: uhci->lock */
|
||||
|
||||
int rh_numports;
|
||||
int rh_numports; /* Number of root-hub ports */
|
||||
|
||||
struct timer_list stall_timer;
|
||||
wait_queue_head_t waitqh; /* endpoint_disable waiters */
|
||||
};
|
||||
|
||||
/* Convert between a usb_hcd pointer and the corresponding uhci_hcd */
|
||||
static inline struct uhci_hcd *hcd_to_uhci(struct usb_hcd *hcd)
|
||||
{
|
||||
return (struct uhci_hcd *) (hcd->hcd_priv);
|
||||
}
|
||||
static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
|
||||
{
|
||||
return container_of((void *) uhci, struct usb_hcd, hcd_priv);
|
||||
}
|
||||
|
||||
//#define uhci_dev(u) (uhci_to_hcd(u)->self.controller)
|
||||
static struct device *uhci_dev(struct uhci_hcd *uhci)
|
||||
{
|
||||
//struct uhci_hcd *uhci = (struct uhci_hcd *) (hcd->hcd_priv);//hcd_to_uhci(hcd);
|
||||
struct usb_hcd *new_hcd = container_of((void *) uhci, struct usb_hcd, hcd_priv); // uhci_to_hcd(uhci)
|
||||
|
||||
return new_hcd->self.controller; //uhci_dev(uhci);
|
||||
}
|
||||
|
||||
struct urb_priv {
|
||||
struct list_head urb_list;
|
||||
|
||||
struct urb *urb;
|
||||
struct usb_device *dev;
|
||||
|
||||
struct uhci_qh *qh; /* QH for this URB */
|
||||
struct list_head td_list; /* P: urb->lock */
|
||||
|
||||
int fsbr : 1; /* URB turned on FSBR */
|
||||
int fsbr_timeout : 1; /* URB timed out on FSBR */
|
||||
int queued : 1; /* QH was queued (not linked in) */
|
||||
int short_control_packet : 1; /* If we get a short packet during */
|
||||
/* a control transfer, retrigger */
|
||||
/* the status phase */
|
||||
|
||||
int status; /* Final status */
|
||||
unsigned fsbr : 1; /* URB turned on FSBR */
|
||||
unsigned fsbr_timeout : 1; /* URB timed out on FSBR */
|
||||
unsigned queued : 1; /* QH was queued (not linked in) */
|
||||
unsigned short_control_packet : 1; /* If we get a short packet during */
|
||||
/* a control transfer, retrigger */
|
||||
/* the status phase */
|
||||
|
||||
unsigned long inserttime; /* In jiffies */
|
||||
unsigned long fsbrtime; /* In jiffies */
|
||||
|
||||
struct list_head queue_list; /* P: uhci->frame_list_lock */
|
||||
struct list_head complete_list; /* P: uhci->complete_list_lock */
|
||||
};
|
||||
|
||||
/*
|
||||
* Locking in uhci.c
|
||||
*
|
||||
* spinlocks are used extensively to protect the many lists and data
|
||||
* structures we have. It's not that pretty, but it's necessary. We
|
||||
* need to be done with all of the locks (except complete_list_lock) when
|
||||
* we call urb->complete. I've tried to make it simple enough so I don't
|
||||
* have to spend hours racking my brain trying to figure out if the
|
||||
* locking is safe.
|
||||
* Almost everything relating to the hardware schedule and processing
|
||||
* of URBs is protected by uhci->lock. urb->status is protected by
|
||||
* urb->lock; that's the one exception.
|
||||
*
|
||||
* Here's the safe locking order to prevent deadlocks:
|
||||
* To prevent deadlocks, never lock uhci->lock while holding urb->lock.
|
||||
* The safe order of locking is:
|
||||
*
|
||||
* #1 uhci->urb_list_lock
|
||||
* #1 uhci->lock
|
||||
* #2 urb->lock
|
||||
* #3 uhci->urb_remove_list_lock, uhci->frame_list_lock,
|
||||
* uhci->qh_remove_list_lock
|
||||
* #4 uhci->complete_list_lock
|
||||
*
|
||||
* If you're going to grab 2 or more locks at once, ALWAYS grab the lock
|
||||
* at the lowest level FIRST and NEVER grab locks at the same level at the
|
||||
* same time.
|
||||
*
|
||||
* So, if you need uhci->urb_list_lock, grab it before you grab urb->lock
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
/* Some special IDs */
|
||||
|
||||
#define PCI_VENDOR_ID_GENESYS 0x17a0
|
||||
#define PCI_DEVICE_ID_GL880S_UHCI 0x8083
|
||||
#define PCI_DEVICE_ID_GL880S_EHCI 0x8084
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Universal Host Controller Interface driver for USB.
|
||||
*
|
||||
* Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
|
||||
* Maintainer: Alan Stern <stern@rowland.harvard.edu>
|
||||
*
|
||||
* (C) Copyright 1999 Linus Torvalds
|
||||
* (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
|
||||
@@ -9,6 +9,7 @@
|
||||
* (C) Copyright 1999 Georg Acher, acher@in.tum.de
|
||||
* (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
|
||||
* (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
|
||||
* (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
|
||||
*/
|
||||
|
||||
static __u8 root_hub_hub_des[] =
|
||||
@@ -16,160 +17,350 @@ static __u8 root_hub_hub_des[] =
|
||||
0x09, /* __u8 bLength; */
|
||||
0x29, /* __u8 bDescriptorType; Hub-descriptor */
|
||||
0x02, /* __u8 bNbrPorts; */
|
||||
0x00, /* __u16 wHubCharacteristics; */
|
||||
0x00,
|
||||
0x0a, /* __u16 wHubCharacteristics; */
|
||||
0x00, /* (per-port OC, no power switching) */
|
||||
0x01, /* __u8 bPwrOn2pwrGood; 2ms */
|
||||
0x00, /* __u8 bHubContrCurrent; 0 mA */
|
||||
0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
|
||||
0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
|
||||
};
|
||||
|
||||
static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
||||
#define UHCI_RH_MAXCHILD 7
|
||||
|
||||
/* must write as zeroes */
|
||||
#define WZ_BITS (USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4)
|
||||
|
||||
/* status change bits: nonzero writes will clear */
|
||||
#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
|
||||
|
||||
/* A port that either is connected or has a changed-bit set will prevent
|
||||
* us from AUTO_STOPPING.
|
||||
*/
|
||||
static int any_ports_active(struct uhci_hcd *uhci)
|
||||
{
|
||||
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
||||
unsigned int io_addr = uhci->io_addr;
|
||||
int i, len = 1;
|
||||
int port;
|
||||
|
||||
for (port = 0; port < uhci->rh_numports; ++port) {
|
||||
if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
|
||||
(USBPORTSC_CCS | RWC_BITS)) ||
|
||||
test_bit(port, &uhci->port_c_suspend))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
|
||||
{
|
||||
int port;
|
||||
|
||||
*buf = 0;
|
||||
for (i = 0; i < uhci->rh_numports; i++) {
|
||||
*buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
|
||||
len = (i + 1) / 8 + 1;
|
||||
for (port = 0; port < uhci->rh_numports; ++port) {
|
||||
if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
|
||||
test_bit(port, &uhci->port_c_suspend))
|
||||
*buf |= (1 << (port + 1));
|
||||
}
|
||||
|
||||
return !!*buf;
|
||||
}
|
||||
|
||||
#define OK(x) len = (x); break
|
||||
|
||||
#define CLR_RH_PORTSTAT(x) \
|
||||
status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
|
||||
status = (status & 0xfff5) & ~(x); \
|
||||
outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
|
||||
status = inw(port_addr); \
|
||||
status &= ~(RWC_BITS|WZ_BITS); \
|
||||
status &= ~(x); \
|
||||
status |= RWC_BITS & (x); \
|
||||
outw(status, port_addr)
|
||||
|
||||
#define SET_RH_PORTSTAT(x) \
|
||||
status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
|
||||
status = (status & 0xfff5) | (x); \
|
||||
outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
|
||||
status = inw(port_addr); \
|
||||
status |= (x); \
|
||||
status &= ~(RWC_BITS|WZ_BITS); \
|
||||
outw(status, port_addr)
|
||||
|
||||
/* UHCI controllers don't automatically stop resume signalling after 20 msec,
|
||||
* so we have to poll and check timeouts in order to take care of it.
|
||||
*/
|
||||
static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
|
||||
unsigned long port_addr)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (test_bit(port, &uhci->suspended_ports)) {
|
||||
CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
|
||||
clear_bit(port, &uhci->suspended_ports);
|
||||
clear_bit(port, &uhci->resuming_ports);
|
||||
set_bit(port, &uhci->port_c_suspend);
|
||||
|
||||
/* The controller won't actually turn off the RD bit until
|
||||
* it has had a chance to send a low-speed EOP sequence,
|
||||
* which takes 3 bit times (= 2 microseconds). We'll delay
|
||||
* slightly longer for good luck. */
|
||||
udelay(4);
|
||||
}
|
||||
}
|
||||
|
||||
static void uhci_check_ports(struct uhci_hcd *uhci)
|
||||
{
|
||||
unsigned int port;
|
||||
unsigned long port_addr;
|
||||
int status;
|
||||
|
||||
for (port = 0; port < uhci->rh_numports; ++port) {
|
||||
port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
|
||||
status = inw(port_addr);
|
||||
if (unlikely(status & USBPORTSC_PR)) {
|
||||
if (time_after_eq(jiffies, uhci->ports_timeout)) {
|
||||
CLR_RH_PORTSTAT(USBPORTSC_PR);
|
||||
udelay(10);
|
||||
|
||||
/* If the port was enabled before, turning
|
||||
* reset on caused a port enable change.
|
||||
* Turning reset off causes a port connect
|
||||
* status change. Clear these changes. */
|
||||
CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
|
||||
SET_RH_PORTSTAT(USBPORTSC_PE);
|
||||
}
|
||||
}
|
||||
if (unlikely(status & USBPORTSC_RD)) {
|
||||
if (!test_bit(port, &uhci->resuming_ports)) {
|
||||
|
||||
/* Port received a wakeup request */
|
||||
set_bit(port, &uhci->resuming_ports);
|
||||
uhci->ports_timeout = jiffies +
|
||||
msecs_to_jiffies(20);
|
||||
|
||||
/* Make sure we see the port again
|
||||
* after the resuming period is over. */
|
||||
mod_timer(&uhci_to_hcd(uhci)->rh_timer,
|
||||
uhci->ports_timeout);
|
||||
} else if (time_after_eq(jiffies,
|
||||
uhci->ports_timeout)) {
|
||||
uhci_finish_suspend(uhci, port, port_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
|
||||
spin_lock_irqsave(&uhci->lock, flags);
|
||||
|
||||
uhci_scan_schedule(uhci, NULL);
|
||||
if (uhci->hc_inaccessible)
|
||||
goto done;
|
||||
check_fsbr(uhci);
|
||||
uhci_check_ports(uhci);
|
||||
|
||||
status = get_hub_status_data(uhci, buf);
|
||||
|
||||
switch (uhci->rh_state) {
|
||||
case UHCI_RH_SUSPENDING:
|
||||
case UHCI_RH_SUSPENDED:
|
||||
/* if port change, ask to be resumed */
|
||||
if (status)
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
break;
|
||||
|
||||
case UHCI_RH_AUTO_STOPPED:
|
||||
/* if port change, auto start */
|
||||
if (status)
|
||||
wakeup_rh(uhci);
|
||||
break;
|
||||
|
||||
case UHCI_RH_RUNNING:
|
||||
/* are any devices attached? */
|
||||
if (!any_ports_active(uhci)) {
|
||||
uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
|
||||
uhci->auto_stop_time = jiffies + HZ;
|
||||
}
|
||||
break;
|
||||
|
||||
case UHCI_RH_RUNNING_NODEVS:
|
||||
/* auto-stop if nothing connected for 1 second */
|
||||
if (any_ports_active(uhci))
|
||||
uhci->rh_state = UHCI_RH_RUNNING;
|
||||
else if (time_after_eq(jiffies, uhci->auto_stop_time))
|
||||
suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&uhci->lock, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* size of returned buffer is part of USB spec */
|
||||
static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
u16 wIndex, u8 *buf, u16 wLength)
|
||||
u16 wIndex, char *buf, u16 wLength)
|
||||
{
|
||||
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
||||
int i, status, retval = 0, len = 0;
|
||||
unsigned int io_addr = uhci->io_addr;
|
||||
__u16 cstatus;
|
||||
char c_p_r[8];
|
||||
int status, lstatus, retval = 0, len = 0;
|
||||
unsigned int port = wIndex - 1;
|
||||
unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
|
||||
u16 wPortChange, wPortStatus;
|
||||
unsigned long flags;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
c_p_r[i] = 0;
|
||||
if (uhci->hc_inaccessible)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
spin_lock_irqsave(&uhci->lock, flags);
|
||||
switch (typeReq) {
|
||||
/* Request Destination:
|
||||
without flags: Device,
|
||||
RH_INTERFACE: interface,
|
||||
RH_ENDPOINT: endpoint,
|
||||
RH_CLASS means HUB here,
|
||||
RH_OTHER | RH_CLASS almost ever means HUB_PORT here
|
||||
*/
|
||||
|
||||
case GetHubStatus:
|
||||
*(__u32 *)buf = cpu_to_le32(0);
|
||||
*(__le32 *)buf = cpu_to_le32(0);
|
||||
OK(4); /* hub power */
|
||||
case GetPortStatus:
|
||||
status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1));
|
||||
cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
|
||||
((status & USBPORTSC_PEC) >> (3 - 1)) |
|
||||
(c_p_r[wIndex - 1] << (0 + 4));
|
||||
status = (status & USBPORTSC_CCS) |
|
||||
((status & USBPORTSC_PE) >> (2 - 1)) |
|
||||
((status & USBPORTSC_SUSP) >> (12 - 2)) |
|
||||
((status & USBPORTSC_PR) >> (9 - 4)) |
|
||||
(1 << 8) | /* power on */
|
||||
((status & USBPORTSC_LSDA) << (-8 + 9));
|
||||
|
||||
*(__u16 *)buf = cpu_to_le16(status);
|
||||
*(__u16 *)(buf + 2) = cpu_to_le16(cstatus);
|
||||
OK(4);
|
||||
case SetHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
if (port >= uhci->rh_numports)
|
||||
goto err;
|
||||
|
||||
uhci_check_ports(uhci);
|
||||
status = inw(port_addr);
|
||||
|
||||
/* Intel controllers report the OverCurrent bit active on.
|
||||
* VIA controllers report it active off, so we'll adjust the
|
||||
* bit value. (It's not standardized in the UHCI spec.)
|
||||
*/
|
||||
if (to_pci_dev(hcd->self.controller)->vendor ==
|
||||
PCI_VENDOR_ID_VIA)
|
||||
status ^= USBPORTSC_OC;
|
||||
|
||||
/* UHCI doesn't support C_RESET (always false) */
|
||||
wPortChange = lstatus = 0;
|
||||
if (status & USBPORTSC_CSC)
|
||||
wPortChange |= USB_PORT_STAT_C_CONNECTION;
|
||||
if (status & USBPORTSC_PEC)
|
||||
wPortChange |= USB_PORT_STAT_C_ENABLE;
|
||||
if (status & USBPORTSC_OCC)
|
||||
wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
|
||||
|
||||
if (test_bit(port, &uhci->port_c_suspend)) {
|
||||
wPortChange |= USB_PORT_STAT_C_SUSPEND;
|
||||
lstatus |= 1;
|
||||
}
|
||||
break;
|
||||
if (test_bit(port, &uhci->suspended_ports))
|
||||
lstatus |= 2;
|
||||
if (test_bit(port, &uhci->resuming_ports))
|
||||
lstatus |= 4;
|
||||
|
||||
/* UHCI has no power switching (always on) */
|
||||
wPortStatus = USB_PORT_STAT_POWER;
|
||||
if (status & USBPORTSC_CCS)
|
||||
wPortStatus |= USB_PORT_STAT_CONNECTION;
|
||||
if (status & USBPORTSC_PE) {
|
||||
wPortStatus |= USB_PORT_STAT_ENABLE;
|
||||
if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
|
||||
wPortStatus |= USB_PORT_STAT_SUSPEND;
|
||||
}
|
||||
if (status & USBPORTSC_OC)
|
||||
wPortStatus |= USB_PORT_STAT_OVERCURRENT;
|
||||
if (status & USBPORTSC_PR)
|
||||
wPortStatus |= USB_PORT_STAT_RESET;
|
||||
if (status & USBPORTSC_LSDA)
|
||||
wPortStatus |= USB_PORT_STAT_LOW_SPEED;
|
||||
|
||||
if (wPortChange)
|
||||
dev_dbg(uhci_dev(uhci), "port %d portsc %04x,%02x\n",
|
||||
wIndex, status, lstatus);
|
||||
|
||||
*(__le16 *)buf = cpu_to_le16(wPortStatus);
|
||||
*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
|
||||
OK(4);
|
||||
case SetHubFeature: /* We don't implement these */
|
||||
case ClearHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
OK(0); /* hub power over current */
|
||||
case C_HUB_LOCAL_POWER:
|
||||
OK(0);
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (!wIndex || wIndex > uhci->rh_numports)
|
||||
if (port >= uhci->rh_numports)
|
||||
goto err;
|
||||
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
set_bit(port, &uhci->suspended_ports);
|
||||
SET_RH_PORTSTAT(USBPORTSC_SUSP);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_RESET:
|
||||
SET_RH_PORTSTAT(USBPORTSC_PR);
|
||||
mdelay(50); /* USB v1.1 7.1.7.3 */
|
||||
c_p_r[wIndex - 1] = 1;
|
||||
CLR_RH_PORTSTAT(USBPORTSC_PR);
|
||||
udelay(10);
|
||||
SET_RH_PORTSTAT(USBPORTSC_PE);
|
||||
mdelay(10);
|
||||
SET_RH_PORTSTAT(0xa);
|
||||
|
||||
/* Reset terminates Resume signalling */
|
||||
uhci_finish_suspend(uhci, port, port_addr);
|
||||
|
||||
/* USB v2.0 7.1.7.5 */
|
||||
uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_POWER:
|
||||
OK(0); /* port power ** */
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
SET_RH_PORTSTAT(USBPORTSC_PE);
|
||||
/* UHCI has no power switching */
|
||||
OK(0);
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (!wIndex || wIndex > uhci->rh_numports)
|
||||
if (port >= uhci->rh_numports)
|
||||
goto err;
|
||||
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
CLR_RH_PORTSTAT(USBPORTSC_PE);
|
||||
|
||||
/* Disable terminates Resume signalling */
|
||||
uhci_finish_suspend(uhci, port, port_addr);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
SET_RH_PORTSTAT(USBPORTSC_PEC);
|
||||
CLR_RH_PORTSTAT(USBPORTSC_PEC);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
CLR_RH_PORTSTAT(USBPORTSC_SUSP);
|
||||
if (test_bit(port, &uhci->suspended_ports) &&
|
||||
!test_and_set_bit(port,
|
||||
&uhci->resuming_ports)) {
|
||||
SET_RH_PORTSTAT(USBPORTSC_RD);
|
||||
|
||||
/* The controller won't allow RD to be set
|
||||
* if the port is disabled. When this happens
|
||||
* just skip the Resume signalling.
|
||||
*/
|
||||
if (!(inw(port_addr) & USBPORTSC_RD))
|
||||
uhci_finish_suspend(uhci, port,
|
||||
port_addr);
|
||||
else
|
||||
/* USB v2.0 7.1.7.7 */
|
||||
uhci->ports_timeout = jiffies +
|
||||
msecs_to_jiffies(20);
|
||||
}
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_C_SUSPEND:
|
||||
/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
|
||||
clear_bit(port, &uhci->port_c_suspend);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_POWER:
|
||||
OK(0); /* port power */
|
||||
/* UHCI has no power switching */
|
||||
goto err;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
SET_RH_PORTSTAT(USBPORTSC_CSC);
|
||||
CLR_RH_PORTSTAT(USBPORTSC_CSC);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
OK(0); /* port power over current */
|
||||
CLR_RH_PORTSTAT(USBPORTSC_OCC);
|
||||
OK(0);
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
c_p_r[wIndex - 1] = 0;
|
||||
/* this driver won't report these */
|
||||
OK(0);
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
len = min_t(unsigned int, wLength,
|
||||
min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
|
||||
len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
|
||||
memcpy(buf, root_hub_hub_des, len);
|
||||
if (len > 2)
|
||||
buf[2] = uhci->rh_numports;
|
||||
@@ -178,7 +369,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
err:
|
||||
retval = -EPIPE;
|
||||
}
|
||||
spin_unlock_irqrestore(&uhci->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
1557
reactos/drivers/usb/miniport/usbuhci/uhci-q.c
Normal file
1557
reactos/drivers/usb/miniport/usbuhci/uhci-q.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
and Herv<72> Poussineau (hpoussin@reactos.org)
|
||||
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
|
||||
*/
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include "uhci.h"
|
||||
|
||||
extern struct pci_driver uhci_pci_driver;
|
||||
@@ -25,8 +25,11 @@ InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
/* Initialize generic linux structure */
|
||||
dev->irq = DeviceExtension->InterruptVector;
|
||||
dev->dev_ext = (PVOID)DeviceExtension;
|
||||
dev->dev.dev_ext = DeviceObject;
|
||||
dev->dev.dev_ext = (PVOID)DeviceExtension; /*DeviceObject*/
|
||||
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
|
||||
dev->bus = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct usb_bus), USB_UHCI_TAG); //FIXME: Remove all this
|
||||
// small allocations from non-paged pool, move them to big device extension struct
|
||||
RtlZeroMemory(dev->bus, sizeof(struct usb_bus));
|
||||
|
||||
/* Init wrapper */
|
||||
init_wrapper(dev);
|
||||
@@ -38,18 +41,33 @@ InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
Status = uhci_hcd_init();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("UHCI: uhci_hcd_init() failed with status 0x%08lx\n", Status);
|
||||
DPRINT1("UHCI: uhci_hcd_init() failed with status 0x%08lx\n", Status);
|
||||
/* FIXME: deinitialize linux wrapper */
|
||||
ExFreePoolWithTag(dev->slot_name, USB_UHCI_TAG);
|
||||
ExFreePoolWithTag(dev->bus, USB_UHCI_TAG);
|
||||
ExFreePoolWithTag(dev, USB_UHCI_TAG);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("uhci_hcd_init() done\n");
|
||||
|
||||
/* Init core usb */
|
||||
usb_init();
|
||||
DPRINT("usb_init() done\n");
|
||||
|
||||
{
|
||||
/* Test code by Fireball */
|
||||
struct device dev;
|
||||
dma_addr_t dma_handle;
|
||||
void *res;
|
||||
|
||||
dev.dev_ext = DeviceExtension;
|
||||
res = dma_alloc_coherent(&dev, 12, &dma_handle, 0);
|
||||
}
|
||||
|
||||
/* Probe device with real id now */
|
||||
uhci_pci_driver.probe(dev, uhci_pci_ids);
|
||||
|
||||
DPRINT("InitLinuxWrapper() done\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -74,6 +92,7 @@ DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
uhci_pci_driver.remove(dev);
|
||||
|
||||
ExFreePool(dev->slot_name);
|
||||
ExFreePool(dev->bus);
|
||||
ExFreePool(dev);
|
||||
|
||||
// Perform some cleanup
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<module name="usbuhci" type="kernelmodedriver" installbase="system32/drivers" installname="usbuhci.sys">
|
||||
<module name="usbuhci" type="kernelmodedriver" installbase="system32/drivers" installname="usbuhci.sys" allowwarnings="true">
|
||||
<define name="DEBUG_MODE" />
|
||||
<define name="__USE_W32API" />
|
||||
<include>../linux</include>
|
||||
<include base="usbminiportcommon"></include>
|
||||
|
@@ -153,7 +153,8 @@ UsbhubFdoQueryBusRelations(
|
||||
else
|
||||
{
|
||||
/* Use values specified in the interface descriptor */
|
||||
struct usb_host_interface *itf = PdoExtension->dev->actconfig->interface->altsetting;
|
||||
#if 0
|
||||
struct usb_host_interface *itf = PdoExtension->dev->actconfig->interface;
|
||||
sprintf(Buffer[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
|
||||
itf->desc.bInterfaceClass,
|
||||
itf->desc.bInterfaceSubClass,
|
||||
@@ -163,6 +164,7 @@ UsbhubFdoQueryBusRelations(
|
||||
itf->desc.bInterfaceSubClass);
|
||||
sprintf(Buffer[2], "USB\\Class_%02x",
|
||||
itf->desc.bInterfaceClass);
|
||||
#endif
|
||||
}
|
||||
Status = UsbhubInitMultiSzString(
|
||||
&PdoExtension->CompatibleIds,
|
||||
@@ -319,10 +321,10 @@ UsbhubDeviceControlFdo(
|
||||
NodeInformation = (PUSB_NODE_INFORMATION)BufferOut;
|
||||
dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev;
|
||||
NodeInformation->NodeType = UsbHub;
|
||||
RtlCopyMemory(
|
||||
/*RtlCopyMemory(
|
||||
&NodeInformation->u.HubInformation.HubDescriptor,
|
||||
((struct usb_hub *)usb_get_intfdata(to_usb_interface(&dev->actconfig->interface[0].dev)))->descriptor,
|
||||
sizeof(USB_HUB_DESCRIPTOR));
|
||||
sizeof(USB_HUB_DESCRIPTOR));*/
|
||||
NodeInformation->u.HubInformation.HubIsBusPowered = dev->actconfig->desc.bmAttributes & 0x80;
|
||||
Information = sizeof(USB_NODE_INFORMATION);
|
||||
Status = STATUS_SUCCESS;
|
||||
@@ -378,7 +380,7 @@ UsbhubDeviceControlFdo(
|
||||
case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
|
||||
{
|
||||
PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation;
|
||||
ULONG i, j, k;
|
||||
//ULONG i, j, k;
|
||||
struct usb_device* dev;
|
||||
ULONG NumberOfOpenPipes = 0;
|
||||
ULONG SizeOfOpenPipesArray;
|
||||
@@ -417,7 +419,7 @@ UsbhubDeviceControlFdo(
|
||||
ConnectionInformation->DeviceIsHub = dev->descriptor.bDeviceClass == USB_CLASS_HUB;
|
||||
ConnectionInformation->DeviceAddress = dev->devnum;
|
||||
ConnectionInformation->ConnectionStatus = DeviceConnected;
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++)
|
||||
for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)
|
||||
for (k = 0; k < dev->actconfig->interface[i].altsetting[j].desc.bNumEndpoints; k++)
|
||||
@@ -434,6 +436,7 @@ UsbhubDeviceControlFdo(
|
||||
}
|
||||
NumberOfOpenPipes++;
|
||||
}
|
||||
#endif
|
||||
ConnectionInformation->NumberOfOpenPipes = NumberOfOpenPipes;
|
||||
|
||||
Information = sizeof(USB_NODE_CONNECTION_INFORMATION);
|
||||
|
@@ -179,7 +179,7 @@ DriverEntry(
|
||||
|
||||
DriverObject->DriverExtension->AddDevice = UsbhubAddDevice;
|
||||
|
||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
DriverObject->MajorFunction[i] = IrpStub;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbhubCreate;
|
||||
|
@@ -23,7 +23,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
|
||||
void *hcd_buffer_alloc (
|
||||
struct usb_bus *bus,
|
||||
size_t size,
|
||||
int mem_flags,
|
||||
unsigned mem_flags,
|
||||
dma_addr_t *dma
|
||||
)
|
||||
{
|
||||
|
@@ -11,333 +11,370 @@
|
||||
#define USB_MAXALTSETTING 128 /* Hard limit */
|
||||
#define USB_MAXENDPOINTS 30 /* Hard limit */
|
||||
|
||||
/* these maximums are arbitrary */
|
||||
#define USB_MAXCONFIG 8
|
||||
#define USB_ALTSETTINGALLOC 4
|
||||
#define USB_MAXINTERFACES 32
|
||||
#define USB_MAXCONFIG 8 /* Arbitrary limit */
|
||||
|
||||
static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, char *buffer, int size)
|
||||
|
||||
static inline const char *plural(int n)
|
||||
{
|
||||
struct usb_descriptor_header *header;
|
||||
char *begin;
|
||||
int parsed = 0, len, numskipped;
|
||||
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
|
||||
/* Everything should be fine being passed into here, but we sanity */
|
||||
/* check JIC */
|
||||
if (header->bLength > size) {
|
||||
err("ran out of descriptors parsing");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header->bDescriptorType != USB_DT_ENDPOINT) {
|
||||
warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X",
|
||||
header->bDescriptorType, USB_DT_ENDPOINT);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
|
||||
memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
|
||||
else
|
||||
memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE);
|
||||
|
||||
le16_to_cpus(&endpoint->desc.wMaxPacketSize);
|
||||
|
||||
buffer += header->bLength;
|
||||
size -= header->bLength;
|
||||
parsed += header->bLength;
|
||||
|
||||
/* Skip over the rest of the Class Specific or Vendor Specific */
|
||||
/* descriptors */
|
||||
begin = buffer;
|
||||
numskipped = 0;
|
||||
while (size >= sizeof(struct usb_descriptor_header)) {
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
|
||||
if (header->bLength < 2) {
|
||||
err("invalid descriptor length of %d", header->bLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we find another "proper" descriptor then we're done */
|
||||
if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
|
||||
(header->bDescriptorType == USB_DT_INTERFACE) ||
|
||||
(header->bDescriptorType == USB_DT_CONFIG) ||
|
||||
(header->bDescriptorType == USB_DT_DEVICE))
|
||||
break;
|
||||
|
||||
dbg("skipping descriptor 0x%X",
|
||||
header->bDescriptorType);
|
||||
numskipped++;
|
||||
|
||||
buffer += header->bLength;
|
||||
size -= header->bLength;
|
||||
parsed += header->bLength;
|
||||
}
|
||||
if (numskipped)
|
||||
dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
|
||||
|
||||
/* Copy any unknown descriptors into a storage area for drivers */
|
||||
/* to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (!len) {
|
||||
endpoint->extra = NULL;
|
||||
endpoint->extralen = 0;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
endpoint->extra = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
if (!endpoint->extra) {
|
||||
err("couldn't allocate memory for endpoint extra descriptors");
|
||||
endpoint->extralen = 0;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
memcpy(endpoint->extra, begin, len);
|
||||
endpoint->extralen = len;
|
||||
|
||||
return parsed;
|
||||
return (n == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
static int usb_parse_interface(struct usb_interface *interface, char *buffer, int size)
|
||||
static int find_next_descriptor(unsigned char *buffer, int size,
|
||||
int dt1, int dt2, int *num_skipped)
|
||||
{
|
||||
int i, len, numskipped, retval, parsed = 0;
|
||||
struct usb_descriptor_header *header;
|
||||
struct usb_host_interface *ifp;
|
||||
char *begin;
|
||||
|
||||
interface->act_altsetting = 0;
|
||||
interface->num_altsetting = 0;
|
||||
interface->max_altsetting = USB_ALTSETTINGALLOC;
|
||||
device_initialize(&interface->dev);
|
||||
|
||||
interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!interface->altsetting) {
|
||||
err("couldn't kmalloc interface->altsetting");
|
||||
return -1;
|
||||
}
|
||||
struct usb_descriptor_header *h;
|
||||
int n = 0;
|
||||
unsigned char *buffer0 = buffer;
|
||||
|
||||
/* Find the next descriptor of type dt1 or dt2 */
|
||||
while (size > 0) {
|
||||
struct usb_interface_descriptor *d;
|
||||
|
||||
if (interface->num_altsetting >= interface->max_altsetting) {
|
||||
struct usb_host_interface *ptr;
|
||||
int oldmas;
|
||||
|
||||
oldmas = interface->max_altsetting;
|
||||
interface->max_altsetting += USB_ALTSETTINGALLOC;
|
||||
if (interface->max_altsetting > USB_MAXALTSETTING) {
|
||||
warn("too many alternate settings (incr %d max %d)\n",
|
||||
USB_ALTSETTINGALLOC, USB_MAXALTSETTING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
err("couldn't kmalloc interface->altsetting");
|
||||
return -1;
|
||||
}
|
||||
memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas);
|
||||
kfree(interface->altsetting);
|
||||
interface->altsetting = ptr;
|
||||
}
|
||||
|
||||
ifp = interface->altsetting + interface->num_altsetting;
|
||||
ifp->endpoint = NULL;
|
||||
ifp->extra = NULL;
|
||||
ifp->extralen = 0;
|
||||
interface->num_altsetting++;
|
||||
|
||||
memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
|
||||
|
||||
/* Skip over the interface */
|
||||
buffer += ifp->desc.bLength;
|
||||
parsed += ifp->desc.bLength;
|
||||
size -= ifp->desc.bLength;
|
||||
|
||||
begin = buffer;
|
||||
numskipped = 0;
|
||||
|
||||
/* Skip over any interface, class or vendor descriptors */
|
||||
while (size >= sizeof(struct usb_descriptor_header)) {
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
|
||||
if (header->bLength < 2) {
|
||||
err("invalid descriptor length of %d", header->bLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we find another "proper" descriptor then we're done */
|
||||
if ((header->bDescriptorType == USB_DT_INTERFACE) ||
|
||||
(header->bDescriptorType == USB_DT_ENDPOINT) ||
|
||||
(header->bDescriptorType == USB_DT_CONFIG) ||
|
||||
(header->bDescriptorType == USB_DT_DEVICE))
|
||||
break;
|
||||
|
||||
numskipped++;
|
||||
|
||||
buffer += header->bLength;
|
||||
parsed += header->bLength;
|
||||
size -= header->bLength;
|
||||
}
|
||||
|
||||
if (numskipped)
|
||||
dbg("skipped %d class/vendor specific interface descriptors", numskipped);
|
||||
|
||||
/* Copy any unknown descriptors into a storage area for */
|
||||
/* drivers to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (len) {
|
||||
ifp->extra = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
if (!ifp->extra) {
|
||||
err("couldn't allocate memory for interface extra descriptors");
|
||||
ifp->extralen = 0;
|
||||
return -1;
|
||||
}
|
||||
memcpy(ifp->extra, begin, len);
|
||||
ifp->extralen = len;
|
||||
}
|
||||
|
||||
/* Did we hit an unexpected descriptor? */
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
if ((size >= sizeof(struct usb_descriptor_header)) &&
|
||||
((header->bDescriptorType == USB_DT_CONFIG) ||
|
||||
(header->bDescriptorType == USB_DT_DEVICE)))
|
||||
return parsed;
|
||||
|
||||
if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
|
||||
warn("too many endpoints");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifp->endpoint = (struct usb_host_endpoint *)
|
||||
kmalloc(ifp->desc.bNumEndpoints *
|
||||
sizeof(struct usb_host_endpoint), GFP_KERNEL);
|
||||
if (!ifp->endpoint) {
|
||||
err("out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints *
|
||||
sizeof(struct usb_host_endpoint));
|
||||
|
||||
for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
|
||||
if (header->bLength > size) {
|
||||
err("ran out of descriptors parsing");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
buffer += retval;
|
||||
parsed += retval;
|
||||
size -= retval;
|
||||
}
|
||||
|
||||
/* We check to see if it's an alternate to this one */
|
||||
d = (struct usb_interface_descriptor *)buffer;
|
||||
if (size < USB_DT_INTERFACE_SIZE
|
||||
|| d->bDescriptorType != USB_DT_INTERFACE
|
||||
|| !d->bAlternateSetting)
|
||||
return parsed;
|
||||
h = (struct usb_descriptor_header *) buffer;
|
||||
if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2)
|
||||
break;
|
||||
buffer += h->bLength;
|
||||
size -= h->bLength;
|
||||
++n;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
/* Store the number of descriptors skipped and return the
|
||||
* number of bytes skipped */
|
||||
if (num_skipped)
|
||||
*num_skipped = n;
|
||||
return buffer - buffer0;
|
||||
}
|
||||
|
||||
int usb_parse_configuration(struct usb_host_config *config, char *buffer)
|
||||
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||
int asnum, struct usb_host_interface *ifp, int num_ep,
|
||||
unsigned char *buffer, int size)
|
||||
{
|
||||
int i, retval, size;
|
||||
unsigned char *buffer0 = buffer;
|
||||
struct usb_endpoint_descriptor *d;
|
||||
struct usb_host_endpoint *endpoint;
|
||||
int n, i;
|
||||
|
||||
d = (struct usb_endpoint_descriptor *) buffer;
|
||||
buffer += d->bLength;
|
||||
size -= d->bLength;
|
||||
|
||||
if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
|
||||
n = USB_DT_ENDPOINT_AUDIO_SIZE;
|
||||
else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
|
||||
n = USB_DT_ENDPOINT_SIZE;
|
||||
else {
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d has an "
|
||||
"invalid endpoint descriptor of length %d, skipping\n",
|
||||
cfgno, inum, asnum, d->bLength);
|
||||
goto skip_to_next_endpoint_or_interface_descriptor;
|
||||
}
|
||||
|
||||
i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
|
||||
if (i >= 16 || i == 0) {
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d has an "
|
||||
"invalid endpoint with address 0x%X, skipping\n",
|
||||
cfgno, inum, asnum, d->bEndpointAddress);
|
||||
goto skip_to_next_endpoint_or_interface_descriptor;
|
||||
}
|
||||
|
||||
/* Only store as many endpoints as we have room for */
|
||||
if (ifp->desc.bNumEndpoints >= num_ep)
|
||||
goto skip_to_next_endpoint_or_interface_descriptor;
|
||||
|
||||
endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
|
||||
++ifp->desc.bNumEndpoints;
|
||||
|
||||
memcpy(&endpoint->desc, d, n);
|
||||
INIT_LIST_HEAD(&endpoint->urb_list);
|
||||
|
||||
/* Skip over any Class Specific or Vendor Specific descriptors;
|
||||
* find the next endpoint or interface descriptor */
|
||||
endpoint->extra = buffer;
|
||||
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
|
||||
USB_DT_INTERFACE, &n);
|
||||
endpoint->extralen = i;
|
||||
if (n > 0)
|
||||
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
|
||||
n, plural(n), "endpoint");
|
||||
return buffer - buffer0 + i;
|
||||
|
||||
skip_to_next_endpoint_or_interface_descriptor:
|
||||
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
|
||||
USB_DT_INTERFACE, NULL);
|
||||
return buffer - buffer0 + i;
|
||||
}
|
||||
|
||||
void usb_release_interface_cache(struct kref *ref)
|
||||
{
|
||||
struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
|
||||
int j;
|
||||
|
||||
for (j = 0; j < intfc->num_altsetting; j++)
|
||||
kfree(intfc->altsetting[j].endpoint);
|
||||
kfree(intfc);
|
||||
}
|
||||
|
||||
static int usb_parse_interface(struct device *ddev, int cfgno,
|
||||
struct usb_host_config *config, unsigned char *buffer, int size,
|
||||
u8 inums[], u8 nalts[])
|
||||
{
|
||||
unsigned char *buffer0 = buffer;
|
||||
struct usb_interface_descriptor *d;
|
||||
int inum, asnum;
|
||||
struct usb_interface_cache *intfc;
|
||||
struct usb_host_interface *alt;
|
||||
int i, n;
|
||||
int len, retval;
|
||||
int num_ep, num_ep_orig;
|
||||
|
||||
d = (struct usb_interface_descriptor *) buffer;
|
||||
buffer += d->bLength;
|
||||
size -= d->bLength;
|
||||
|
||||
if (d->bLength < USB_DT_INTERFACE_SIZE)
|
||||
goto skip_to_next_interface_descriptor;
|
||||
|
||||
/* Which interface entry is this? */
|
||||
intfc = NULL;
|
||||
inum = d->bInterfaceNumber;
|
||||
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
||||
if (inums[i] == inum) {
|
||||
intfc = config->intf_cache[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!intfc || intfc->num_altsetting >= nalts[i])
|
||||
goto skip_to_next_interface_descriptor;
|
||||
|
||||
/* Check for duplicate altsetting entries */
|
||||
asnum = d->bAlternateSetting;
|
||||
for ((i = 0, alt = &intfc->altsetting[0]);
|
||||
i < intfc->num_altsetting;
|
||||
(++i, ++alt)) {
|
||||
if (alt->desc.bAlternateSetting == asnum) {
|
||||
dev_warn(ddev, "Duplicate descriptor for config %d "
|
||||
"interface %d altsetting %d, skipping\n",
|
||||
cfgno, inum, asnum);
|
||||
goto skip_to_next_interface_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
++intfc->num_altsetting;
|
||||
memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);
|
||||
|
||||
/* Skip over any Class Specific or Vendor Specific descriptors;
|
||||
* find the first endpoint or interface descriptor */
|
||||
alt->extra = buffer;
|
||||
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
|
||||
USB_DT_INTERFACE, &n);
|
||||
alt->extralen = i;
|
||||
if (n > 0)
|
||||
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
|
||||
n, plural(n), "interface");
|
||||
buffer += i;
|
||||
size -= i;
|
||||
|
||||
/* Allocate space for the right(?) number of endpoints */
|
||||
num_ep = num_ep_orig = alt->desc.bNumEndpoints;
|
||||
alt->desc.bNumEndpoints = 0; // Use as a counter
|
||||
if (num_ep > USB_MAXENDPOINTS) {
|
||||
dev_warn(ddev, "too many endpoints for config %d interface %d "
|
||||
"altsetting %d: %d, using maximum allowed: %d\n",
|
||||
cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
|
||||
num_ep = USB_MAXENDPOINTS;
|
||||
}
|
||||
|
||||
len = sizeof(struct usb_host_endpoint) * num_ep;
|
||||
alt->endpoint = kmalloc(len, GFP_KERNEL);
|
||||
if (!alt->endpoint)
|
||||
return -ENOMEM;
|
||||
memset(alt->endpoint, 0, len);
|
||||
|
||||
/* Parse all the endpoint descriptors */
|
||||
n = 0;
|
||||
while (size > 0) {
|
||||
if (((struct usb_descriptor_header *) buffer)->bDescriptorType
|
||||
== USB_DT_INTERFACE)
|
||||
break;
|
||||
retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
|
||||
num_ep, buffer, size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
++n;
|
||||
|
||||
buffer += retval;
|
||||
size -= retval;
|
||||
}
|
||||
|
||||
if (n != num_ep_orig)
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d has %d "
|
||||
"endpoint descriptor%s, different from the interface "
|
||||
"descriptor's value: %d\n",
|
||||
cfgno, inum, asnum, n, plural(n), num_ep_orig);
|
||||
return buffer - buffer0;
|
||||
|
||||
skip_to_next_interface_descriptor:
|
||||
i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
|
||||
USB_DT_INTERFACE, NULL);
|
||||
return buffer - buffer0 + i;
|
||||
}
|
||||
|
||||
static int usb_parse_configuration(struct device *ddev, int cfgidx,
|
||||
struct usb_host_config *config, unsigned char *buffer, int size)
|
||||
{
|
||||
unsigned char *buffer0 = buffer;
|
||||
int cfgno;
|
||||
int nintf, nintf_orig;
|
||||
int i, j, n;
|
||||
struct usb_interface_cache *intfc;
|
||||
unsigned char *buffer2;
|
||||
int size2;
|
||||
struct usb_descriptor_header *header;
|
||||
int len, retval;
|
||||
u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
|
||||
|
||||
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
|
||||
le16_to_cpus(&config->desc.wTotalLength);
|
||||
size = config->desc.wTotalLength;
|
||||
|
||||
if (config->desc.bNumInterfaces > USB_MAXINTERFACES) {
|
||||
warn("too many interfaces");
|
||||
return -1;
|
||||
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
|
||||
config->desc.bLength < USB_DT_CONFIG_SIZE) {
|
||||
dev_err(ddev, "invalid descriptor for config index %d: "
|
||||
"type = 0x%X, length = %d\n", cfgidx,
|
||||
config->desc.bDescriptorType, config->desc.bLength);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
config->interface = (struct usb_interface *)
|
||||
kmalloc(config->desc.bNumInterfaces *
|
||||
sizeof(struct usb_interface), GFP_KERNEL);
|
||||
dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces);
|
||||
if (!config->interface) {
|
||||
err("out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(config->interface, 0,
|
||||
config->desc.bNumInterfaces * sizeof(struct usb_interface));
|
||||
cfgno = config->desc.bConfigurationValue;
|
||||
|
||||
buffer += config->desc.bLength;
|
||||
size -= config->desc.bLength;
|
||||
|
||||
config->extra = NULL;
|
||||
config->extralen = 0;
|
||||
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
int numskipped, len;
|
||||
char *begin;
|
||||
nintf = nintf_orig = config->desc.bNumInterfaces;
|
||||
if (nintf > USB_MAXINTERFACES) {
|
||||
dev_warn(ddev, "config %d has too many interfaces: %d, "
|
||||
"using maximum allowed: %d\n",
|
||||
cfgno, nintf, USB_MAXINTERFACES);
|
||||
nintf = USB_MAXINTERFACES;
|
||||
}
|
||||
|
||||
/* Skip over the rest of the Class Specific or Vendor */
|
||||
/* Specific descriptors */
|
||||
begin = buffer;
|
||||
numskipped = 0;
|
||||
while (size >= sizeof(struct usb_descriptor_header)) {
|
||||
header = (struct usb_descriptor_header *)buffer;
|
||||
/* Go through the descriptors, checking their length and counting the
|
||||
* number of altsettings for each interface */
|
||||
n = 0;
|
||||
for ((buffer2 = buffer, size2 = size);
|
||||
size2 > 0;
|
||||
(buffer2 += header->bLength, size2 -= header->bLength)) {
|
||||
|
||||
if ((header->bLength > size) || (header->bLength < 2)) {
|
||||
err("invalid descriptor length of %d", header->bLength);
|
||||
return -1;
|
||||
if (size2 < sizeof(struct usb_descriptor_header)) {
|
||||
dev_warn(ddev, "config %d descriptor has %d excess "
|
||||
"byte%s, ignoring\n",
|
||||
cfgno, size2, plural(size2));
|
||||
break;
|
||||
}
|
||||
|
||||
header = (struct usb_descriptor_header *) buffer2;
|
||||
if ((header->bLength > size2) || (header->bLength < 2)) {
|
||||
dev_warn(ddev, "config %d has an invalid descriptor "
|
||||
"of length %d, skipping remainder of the config\n",
|
||||
cfgno, header->bLength);
|
||||
break;
|
||||
}
|
||||
|
||||
if (header->bDescriptorType == USB_DT_INTERFACE) {
|
||||
struct usb_interface_descriptor *d;
|
||||
int inum;
|
||||
|
||||
d = (struct usb_interface_descriptor *) header;
|
||||
if (d->bLength < USB_DT_INTERFACE_SIZE) {
|
||||
dev_warn(ddev, "config %d has an invalid "
|
||||
"interface descriptor of length %d, "
|
||||
"skipping\n", cfgno, d->bLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we find another "proper" descriptor then we're done */
|
||||
if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
|
||||
(header->bDescriptorType == USB_DT_INTERFACE) ||
|
||||
(header->bDescriptorType == USB_DT_CONFIG) ||
|
||||
(header->bDescriptorType == USB_DT_DEVICE))
|
||||
inum = d->bInterfaceNumber;
|
||||
if (inum >= nintf_orig)
|
||||
dev_warn(ddev, "config %d has an invalid "
|
||||
"interface number: %d but max is %d\n",
|
||||
cfgno, inum, nintf_orig - 1);
|
||||
|
||||
/* Have we already encountered this interface?
|
||||
* Count its altsettings */
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (inums[i] == inum)
|
||||
break;
|
||||
}
|
||||
if (i < n) {
|
||||
if (nalts[i] < 255)
|
||||
++nalts[i];
|
||||
} else if (n < USB_MAXINTERFACES) {
|
||||
inums[n] = inum;
|
||||
nalts[n] = 1;
|
||||
++n;
|
||||
}
|
||||
|
||||
} else if (header->bDescriptorType == USB_DT_DEVICE ||
|
||||
header->bDescriptorType == USB_DT_CONFIG)
|
||||
dev_warn(ddev, "config %d contains an unexpected "
|
||||
"descriptor of type 0x%X, skipping\n",
|
||||
cfgno, header->bDescriptorType);
|
||||
|
||||
} /* for ((buffer2 = buffer, size2 = size); ...) */
|
||||
size = buffer2 - buffer;
|
||||
config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
|
||||
|
||||
if (n != nintf)
|
||||
{
|
||||
dev_warn(ddev, "config %d has %d interface%s, different from "
|
||||
"the descriptor's value: %d\n",
|
||||
cfgno, n, plural(n), nintf_orig);
|
||||
}
|
||||
else if (n == 0)
|
||||
{
|
||||
dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
|
||||
config->desc.bNumInterfaces = nintf = n;
|
||||
}
|
||||
|
||||
/* Check for missing interface numbers */
|
||||
for (i = 0; i < nintf; ++i) {
|
||||
for (j = 0; j < nintf; ++j) {
|
||||
if (inums[j] == i)
|
||||
break;
|
||||
|
||||
dbg("skipping descriptor 0x%X", header->bDescriptorType);
|
||||
numskipped++;
|
||||
|
||||
buffer += header->bLength;
|
||||
size -= header->bLength;
|
||||
}
|
||||
if (numskipped)
|
||||
dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
|
||||
if (j >= nintf)
|
||||
dev_warn(ddev, "config %d has no interface number "
|
||||
"%d\n", cfgno, i);
|
||||
}
|
||||
|
||||
/* Copy any unknown descriptors into a storage area for */
|
||||
/* drivers to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (len) {
|
||||
if (config->extralen) {
|
||||
warn("extra config descriptor");
|
||||
} else {
|
||||
config->extra = kmalloc(len, GFP_KERNEL);
|
||||
if (!config->extra) {
|
||||
err("couldn't allocate memory for config extra descriptors");
|
||||
config->extralen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(config->extra, begin, len);
|
||||
config->extralen = len;
|
||||
}
|
||||
/* Allocate the usb_interface_caches and altsetting arrays */
|
||||
for (i = 0; i < nintf; ++i) {
|
||||
j = nalts[i];
|
||||
if (j > USB_MAXALTSETTING) {
|
||||
dev_warn(ddev, "too many alternate settings for "
|
||||
"config %d interface %d: %d, "
|
||||
"using maximum allowed: %d\n",
|
||||
cfgno, inums[i], j, USB_MAXALTSETTING);
|
||||
nalts[i] = j = USB_MAXALTSETTING;
|
||||
}
|
||||
|
||||
retval = usb_parse_interface(config->interface + i, buffer, size);
|
||||
len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
|
||||
config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
|
||||
if (!intfc)
|
||||
return -ENOMEM;
|
||||
memset(intfc, 0, len);
|
||||
kref_init(&intfc->ref);
|
||||
}
|
||||
|
||||
/* Skip over any Class Specific or Vendor Specific descriptors;
|
||||
* find the first interface descriptor */
|
||||
config->extra = buffer;
|
||||
i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
|
||||
USB_DT_INTERFACE, &n);
|
||||
config->extralen = i;
|
||||
if (n > 0)
|
||||
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
|
||||
n, plural(n), "configuration");
|
||||
buffer += i;
|
||||
size -= i;
|
||||
|
||||
/* Parse all the interface/altsetting descriptors */
|
||||
while (size > 0) {
|
||||
retval = usb_parse_interface(ddev, cfgno, config,
|
||||
buffer, size, inums, nalts);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -345,15 +382,30 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer)
|
||||
size -= retval;
|
||||
}
|
||||
|
||||
return size;
|
||||
/* Check for missing altsettings */
|
||||
for (i = 0; i < nintf; ++i) {
|
||||
intfc = config->intf_cache[i];
|
||||
for (j = 0; j < intfc->num_altsetting; ++j) {
|
||||
for (n = 0; n < intfc->num_altsetting; ++n) {
|
||||
if (intfc->altsetting[n].desc.
|
||||
bAlternateSetting == j)
|
||||
break;
|
||||
}
|
||||
if (n >= intfc->num_altsetting)
|
||||
dev_warn(ddev, "config %d interface %d has no "
|
||||
"altsetting %d\n", cfgno, inums[i], j);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// hub-only!! ... and only exported for reset/reinit path.
|
||||
// otherwise used internally on disconnect/destroy path
|
||||
void usb_destroy_configuration(struct usb_device *dev)
|
||||
{
|
||||
int c, i, j, k;
|
||||
|
||||
int c, i;
|
||||
|
||||
if (!dev->config)
|
||||
return;
|
||||
|
||||
@@ -362,45 +414,23 @@ void usb_destroy_configuration(struct usb_device *dev)
|
||||
kfree(dev->rawdescriptors[i]);
|
||||
|
||||
kfree(dev->rawdescriptors);
|
||||
dev->rawdescriptors = NULL;
|
||||
}
|
||||
|
||||
for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
|
||||
struct usb_host_config *cf = &dev->config[c];
|
||||
|
||||
if (!cf->interface)
|
||||
break;
|
||||
kfree(cf->string);
|
||||
cf->string = NULL;
|
||||
|
||||
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *ifp =
|
||||
&cf->interface[i];
|
||||
|
||||
if (!ifp->altsetting)
|
||||
break;
|
||||
|
||||
for (j = 0; j < ifp->num_altsetting; j++) {
|
||||
struct usb_host_interface *as =
|
||||
&ifp->altsetting[j];
|
||||
|
||||
if(as->extra) {
|
||||
kfree(as->extra);
|
||||
}
|
||||
|
||||
if (!as->endpoint)
|
||||
break;
|
||||
|
||||
for(k = 0; k < as->desc.bNumEndpoints; k++) {
|
||||
if(as->endpoint[k].extra) {
|
||||
kfree(as->endpoint[k].extra);
|
||||
}
|
||||
}
|
||||
kfree(as->endpoint);
|
||||
}
|
||||
|
||||
kfree(ifp->altsetting);
|
||||
if (cf->intf_cache[i])
|
||||
kref_put(&cf->intf_cache[i]->ref,
|
||||
usb_release_interface_cache);
|
||||
}
|
||||
kfree(cf->interface);
|
||||
}
|
||||
kfree(dev->config);
|
||||
dev->config = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -408,102 +438,97 @@ void usb_destroy_configuration(struct usb_device *dev)
|
||||
// (used by real hubs and virtual root hubs)
|
||||
int usb_get_configuration(struct usb_device *dev)
|
||||
{
|
||||
int result;
|
||||
struct device *ddev = &dev->dev;
|
||||
int ncfg = dev->descriptor.bNumConfigurations;
|
||||
int result = -ENOMEM;
|
||||
unsigned int cfgno, length;
|
||||
char *buffer;
|
||||
char *bigbuffer;
|
||||
unsigned char *buffer;
|
||||
unsigned char *bigbuffer;
|
||||
struct usb_config_descriptor *desc;
|
||||
|
||||
if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
|
||||
warn("too many configurations");
|
||||
if (ncfg > USB_MAXCONFIG) {
|
||||
dev_warn(ddev, "too many configurations: %d, "
|
||||
"using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
|
||||
dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
|
||||
}
|
||||
|
||||
if (ncfg < 1) {
|
||||
dev_err(ddev, "no configurations\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev->descriptor.bNumConfigurations < 1) {
|
||||
warn("not enough configurations");
|
||||
return -EINVAL;
|
||||
}
|
||||
length = ncfg * sizeof(struct usb_host_config);
|
||||
dev->config = kmalloc(length, GFP_KERNEL);
|
||||
if (!dev->config)
|
||||
goto err2;
|
||||
memset(dev->config, 0, length);
|
||||
|
||||
dev->config = (struct usb_host_config *)
|
||||
kmalloc(dev->descriptor.bNumConfigurations *
|
||||
sizeof(struct usb_host_config), GFP_KERNEL);
|
||||
if (!dev->config) {
|
||||
err("out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(dev->config, 0, dev->descriptor.bNumConfigurations *
|
||||
sizeof(struct usb_host_config));
|
||||
length = ncfg * sizeof(char *);
|
||||
dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
|
||||
if (!dev->rawdescriptors)
|
||||
goto err2;
|
||||
memset(dev->rawdescriptors, 0, length);
|
||||
|
||||
dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
|
||||
dev->descriptor.bNumConfigurations, GFP_KERNEL);
|
||||
if (!dev->rawdescriptors) {
|
||||
err("out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buffer = kmalloc(8, GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
err("unable to allocate memory for configuration descriptors");
|
||||
return -ENOMEM;
|
||||
}
|
||||
buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
goto err2;
|
||||
desc = (struct usb_config_descriptor *)buffer;
|
||||
|
||||
for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
|
||||
/* We grab the first 8 bytes so we know how long the whole */
|
||||
/* configuration is */
|
||||
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
|
||||
if (result < 8) {
|
||||
if (result < 0) {
|
||||
err("unable to get descriptor");
|
||||
}
|
||||
else {
|
||||
err("config descriptor too short (expected %i, got %i)", 8, result);
|
||||
result = -EINVAL;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the full buffer */
|
||||
length = le16_to_cpu(desc->wTotalLength);
|
||||
|
||||
bigbuffer = kmalloc(length, GFP_KERNEL);
|
||||
if (!bigbuffer) {
|
||||
err("unable to allocate memory for configuration descriptors");
|
||||
result = -ENOMEM;
|
||||
goto err;
|
||||
for (cfgno = 0; cfgno < ncfg; cfgno++) {
|
||||
/* We grab just the first descriptor so we know how long
|
||||
* the whole configuration is */
|
||||
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
|
||||
buffer, USB_DT_CONFIG_SIZE);
|
||||
if (result < 0) {
|
||||
dev_err(ddev, "unable to read config index %d "
|
||||
"descriptor/%s\n", cfgno, "start");
|
||||
goto err_;
|
||||
} else if (result < 4) {
|
||||
dev_err(ddev, "config index %d descriptor too short "
|
||||
"(expected %i, got %i)\n", cfgno,
|
||||
USB_DT_CONFIG_SIZE, result);
|
||||
result = -EINVAL;
|
||||
goto err_;
|
||||
}
|
||||
length = max((int) le16_to_cpu(desc->wTotalLength),
|
||||
USB_DT_CONFIG_SIZE);
|
||||
|
||||
/* Now that we know the length, get the whole thing */
|
||||
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
|
||||
bigbuffer = kmalloc(length, GFP_KERNEL);
|
||||
if (!bigbuffer) {
|
||||
result = -ENOMEM;
|
||||
goto err_;
|
||||
}
|
||||
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
|
||||
bigbuffer, length);
|
||||
if (result < 0) {
|
||||
err("couldn't get all of config descriptors");
|
||||
dev_err(ddev, "unable to read config index %d "
|
||||
"descriptor/%s\n", cfgno, "all");
|
||||
kfree(bigbuffer);
|
||||
goto err;
|
||||
}
|
||||
|
||||
goto err_;
|
||||
}
|
||||
if (result < length) {
|
||||
err("config descriptor too short (expected %i, got %i)", length, result);
|
||||
result = -EINVAL;
|
||||
kfree(bigbuffer);
|
||||
goto err;
|
||||
dev_warn(ddev, "config index %d descriptor too short "
|
||||
"(expected %i, got %i)\n", cfgno, length, result);
|
||||
length = result;
|
||||
}
|
||||
|
||||
dev->rawdescriptors[cfgno] = bigbuffer;
|
||||
|
||||
result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
|
||||
if (result > 0)
|
||||
dbg("descriptor data left");
|
||||
else if (result < 0) {
|
||||
result = -EINVAL;
|
||||
goto err;
|
||||
result = usb_parse_configuration(&dev->dev, cfgno,
|
||||
&dev->config[cfgno], bigbuffer, length);
|
||||
if (result < 0) {
|
||||
++cfgno;
|
||||
goto err_;
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
|
||||
kfree(buffer);
|
||||
return 0;
|
||||
err:
|
||||
err_:
|
||||
kfree(buffer);
|
||||
dev->descriptor.bNumConfigurations = cfgno;
|
||||
err2:
|
||||
if (result == -ENOMEM)
|
||||
dev_err(ddev, "out of memory\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -207,16 +207,19 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
|
||||
|
||||
static struct usb_device_id usb_kbd_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 1) },
|
||||
{ } /* Terminating entry */
|
||||
{ 0 } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver usb_kbd_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "keyboard",
|
||||
.probe = usb_kbd_probe,
|
||||
.disconnect = usb_kbd_disconnect,
|
||||
.id_table = usb_kbd_id_table,
|
||||
/*.owner =*/ THIS_MODULE,
|
||||
/*.name =*/ "keyboard",
|
||||
/*.probe =*/ usb_kbd_probe,
|
||||
/*.disconnect =*/ usb_kbd_disconnect,
|
||||
/*.ioctl =*/ NULL,
|
||||
/*.suspend =*/ NULL,
|
||||
/*.resume =*/ NULL,
|
||||
/*.id_table =*/ usb_kbd_id_table
|
||||
};
|
||||
|
||||
void UsbKeyBoardInit(void)
|
||||
|
@@ -1,59 +1,59 @@
|
||||
/*
|
||||
This driver is based on Linux 2.5.75 usbmouse driver by Vojtech Pavlik
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
|
||||
#define NDEBUG
|
||||
#include "../../miniport/usb_wrapper.h"
|
||||
|
||||
|
||||
extern USBPORT_INTERFACE UsbPortInterface;
|
||||
|
||||
struct usb_mouse {
|
||||
char name[128];
|
||||
char phys[64];
|
||||
struct usb_device *usbdev;
|
||||
char btn_old;
|
||||
//struct input_dev dev;
|
||||
struct urb *irq;
|
||||
int open;
|
||||
|
||||
signed char *data;
|
||||
dma_addr_t data_dma;
|
||||
};
|
||||
|
||||
static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct usb_mouse *mouse = urb->context;
|
||||
signed char *data = mouse->data;
|
||||
int status;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0: /* success */
|
||||
break;
|
||||
case -ECONNRESET: /* unlink */
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
return;
|
||||
/* -EPIPE: should clear the halt */
|
||||
default: /* error */
|
||||
goto resubmit;
|
||||
}
|
||||
/*
|
||||
input_regs(dev, regs);
|
||||
|
||||
input_report_key(dev, BTN_LEFT, data[0] & 0x01);
|
||||
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
|
||||
input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
|
||||
input_report_key(dev, BTN_SIDE, data[0] & 0x08);
|
||||
input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
|
||||
|
||||
input_report_rel(dev, REL_X, data[1]);
|
||||
input_report_rel(dev, REL_Y, data[2]);
|
||||
input_report_rel(dev, REL_WHEEL, data[3]);
|
||||
|
||||
input_sync(dev);
|
||||
*/
|
||||
|
||||
{
|
||||
|
||||
struct usb_mouse {
|
||||
char name[128];
|
||||
char phys[64];
|
||||
struct usb_device *usbdev;
|
||||
char btn_old;
|
||||
//struct input_dev dev;
|
||||
struct urb *irq;
|
||||
int open;
|
||||
|
||||
signed char *data;
|
||||
dma_addr_t data_dma;
|
||||
};
|
||||
|
||||
static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct usb_mouse *mouse = urb->context;
|
||||
signed char *data = mouse->data;
|
||||
int status;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0: /* success */
|
||||
break;
|
||||
case -ECONNRESET: /* unlink */
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
return;
|
||||
/* -EPIPE: should clear the halt */
|
||||
default: /* error */
|
||||
goto resubmit;
|
||||
}
|
||||
/*
|
||||
input_regs(dev, regs);
|
||||
|
||||
input_report_key(dev, BTN_LEFT, data[0] & 0x01);
|
||||
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
|
||||
input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
|
||||
input_report_key(dev, BTN_SIDE, data[0] & 0x08);
|
||||
input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
|
||||
|
||||
input_report_rel(dev, REL_X, data[1]);
|
||||
input_report_rel(dev, REL_Y, data[2]);
|
||||
input_report_rel(dev, REL_WHEEL, data[3]);
|
||||
|
||||
input_sync(dev);
|
||||
*/
|
||||
|
||||
{
|
||||
MOUSE_INPUT_DATA MouseInputData;
|
||||
ULONG InputDataConsumed;
|
||||
|
||||
@@ -113,157 +113,161 @@ static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
|
||||
// debug info
|
||||
printk("MouseInputData.Buttons=0x%03x\n", MouseInputData.Buttons);
|
||||
}
|
||||
|
||||
printk("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0]);
|
||||
|
||||
resubmit:
|
||||
status = usb_submit_urb (urb, SLAB_ATOMIC);
|
||||
if (status)
|
||||
err ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
mouse->usbdev->bus->bus_name,
|
||||
mouse->usbdev->devpath, status);
|
||||
}
|
||||
/*
|
||||
static int usb_mouse_open(struct input_dev *dev)
|
||||
{
|
||||
struct usb_mouse *mouse = dev->private;
|
||||
|
||||
if (mouse->open++)
|
||||
return 0;
|
||||
|
||||
mouse->irq->dev = mouse->usbdev;
|
||||
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
|
||||
mouse->open--;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_mouse_close(struct input_dev *dev)
|
||||
{
|
||||
struct usb_mouse *mouse = dev->private;
|
||||
|
||||
if (!--mouse->open)
|
||||
usb_unlink_urb(mouse->irq);
|
||||
}
|
||||
*/
|
||||
|
||||
static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
|
||||
{
|
||||
struct usb_device * dev = interface_to_usbdev(intf);
|
||||
struct usb_host_interface *interface;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct usb_mouse *mouse;
|
||||
int pipe, maxp;
|
||||
char path[64];
|
||||
char *buf;
|
||||
|
||||
interface = &intf->altsetting[intf->act_altsetting];
|
||||
|
||||
if (interface->desc.bNumEndpoints != 1)
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & 0x80))
|
||||
return -ENODEV;
|
||||
if ((endpoint->bmAttributes & 3) != 3)
|
||||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
|
||||
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset(mouse, 0, sizeof(struct usb_mouse));
|
||||
|
||||
mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
|
||||
if (!mouse->data) {
|
||||
kfree(mouse);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!mouse->irq) {
|
||||
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mouse->usbdev = dev;
|
||||
|
||||
usb_make_path(dev, path, 64);
|
||||
sprintf(mouse->phys, "%s/input0", path);
|
||||
|
||||
if (!(buf = kmalloc(63, GFP_KERNEL))) {
|
||||
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dev->descriptor.iManufacturer &&
|
||||
usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
|
||||
strcat(mouse->name, buf);
|
||||
if (dev->descriptor.iProduct &&
|
||||
usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
|
||||
sprintf(mouse->name, "%s %s", mouse->name, buf);
|
||||
|
||||
if (!strlen(mouse->name))
|
||||
sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
|
||||
dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
|
||||
(maxp > 8 ? 8 : maxp),
|
||||
usb_mouse_irq, mouse, endpoint->bInterval);
|
||||
//mouse->irq->transfer_dma = mouse->data_dma;
|
||||
//mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
|
||||
|
||||
usb_set_intfdata(intf, mouse);
|
||||
|
||||
// Open device
|
||||
mouse->irq->dev = mouse->usbdev;
|
||||
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mouse->btn_old = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_mouse_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_mouse *mouse = usb_get_intfdata (intf);
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
||||
printk("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0]);
|
||||
|
||||
resubmit:
|
||||
status = usb_submit_urb (urb, SLAB_ATOMIC);
|
||||
if (status)
|
||||
err ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
mouse->usbdev->bus->bus_name,
|
||||
mouse->usbdev->devpath, status);
|
||||
}
|
||||
/*
|
||||
static int usb_mouse_open(struct input_dev *dev)
|
||||
{
|
||||
struct usb_mouse *mouse = dev->private;
|
||||
|
||||
if (mouse->open++)
|
||||
return 0;
|
||||
|
||||
mouse->irq->dev = mouse->usbdev;
|
||||
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
|
||||
mouse->open--;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_mouse_close(struct input_dev *dev)
|
||||
{
|
||||
struct usb_mouse *mouse = dev->private;
|
||||
|
||||
if (!--mouse->open)
|
||||
usb_unlink_urb(mouse->irq);
|
||||
}
|
||||
*/
|
||||
|
||||
static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
|
||||
{
|
||||
struct usb_device * dev = interface_to_usbdev(intf);
|
||||
struct usb_host_interface *interface;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct usb_mouse *mouse;
|
||||
int pipe, maxp;
|
||||
char path[64];
|
||||
char *buf;
|
||||
|
||||
interface = intf->cur_altsetting;//&intf->altsetting[intf->act_altsetting];
|
||||
|
||||
if (interface->desc.bNumEndpoints != 1)
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & 0x80))
|
||||
return -ENODEV;
|
||||
if ((endpoint->bmAttributes & 3) != 3)
|
||||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
|
||||
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset(mouse, 0, sizeof(struct usb_mouse));
|
||||
|
||||
mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
|
||||
if (!mouse->data) {
|
||||
kfree(mouse);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!mouse->irq) {
|
||||
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mouse->usbdev = dev;
|
||||
|
||||
usb_make_path(dev, path, 64);
|
||||
sprintf(mouse->phys, "%s/input0", path);
|
||||
|
||||
if (!(buf = kmalloc(63, GFP_KERNEL))) {
|
||||
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dev->descriptor.iManufacturer &&
|
||||
usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
|
||||
strcat(mouse->name, buf);
|
||||
if (dev->descriptor.iProduct &&
|
||||
usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
|
||||
sprintf(mouse->name, "%s %s", mouse->name, buf);
|
||||
|
||||
if (!strlen(mouse->name))
|
||||
sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
|
||||
dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
|
||||
(maxp > 8 ? 8 : maxp),
|
||||
usb_mouse_irq, mouse, endpoint->bInterval);
|
||||
//mouse->irq->transfer_dma = mouse->data_dma;
|
||||
//mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
|
||||
|
||||
usb_set_intfdata(intf, mouse);
|
||||
|
||||
// Open device
|
||||
mouse->irq->dev = mouse->usbdev;
|
||||
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mouse->btn_old = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_mouse_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_mouse *mouse = usb_get_intfdata (intf);
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usbprintk("Mouse disconnected\n ");
|
||||
if (mouse) {
|
||||
usb_unlink_urb(mouse->irq);
|
||||
usb_free_urb(mouse->irq);
|
||||
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_mouse_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 2) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
|
||||
|
||||
static struct usb_driver usb_mouse_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "usbmouse",
|
||||
.probe = usb_mouse_probe,
|
||||
.disconnect = usb_mouse_disconnect,
|
||||
.id_table = usb_mouse_id_table,
|
||||
};
|
||||
|
||||
if (mouse) {
|
||||
usb_unlink_urb(mouse->irq);
|
||||
usb_free_urb(mouse->irq);
|
||||
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
|
||||
kfree(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_mouse_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 2) },
|
||||
{ 0 } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
|
||||
|
||||
static struct usb_driver usb_mouse_driver = {
|
||||
/*.owner =*/ THIS_MODULE,
|
||||
/*.name =*/ "usbmouse",
|
||||
/*.probe =*/ usb_mouse_probe,
|
||||
/*.disconnect =*/ usb_mouse_disconnect,
|
||||
/*.ioctl =*/ NULL,
|
||||
/*.suspend =*/ NULL,
|
||||
/*.resume =*/ NULL,
|
||||
/*.id_table =*/ usb_mouse_id_table
|
||||
};
|
||||
|
||||
|
||||
void UsbMouseInit(void)
|
||||
{
|
||||
if (usb_register(&usb_mouse_driver) < 0) {
|
||||
|
@@ -38,8 +38,7 @@
|
||||
#include "hcd.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* PCI-based HCs are normal, but custom bus glue should be ok */
|
||||
/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -63,16 +62,21 @@ int STDCALL
|
||||
usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
struct hc_driver *driver;
|
||||
PHYSICAL_ADDRESS resource;
|
||||
unsigned long len;
|
||||
void *base;
|
||||
struct usb_hcd *hcd;
|
||||
int retval, region;
|
||||
char buf [8];
|
||||
//char *bufp = buf;
|
||||
int retval;
|
||||
|
||||
printk("usbcore: usb_hcd_pci_probe() called\n");
|
||||
|
||||
{
|
||||
/* Test code by Fireball */
|
||||
struct device dv;
|
||||
dma_addr_t dma_handle;
|
||||
void *res;
|
||||
|
||||
dv.dev_ext = dev->dev_ext;
|
||||
res = dma_alloc_coherent(&dv, 12, &dma_handle, 0);
|
||||
}
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
@@ -81,123 +85,96 @@ usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
if (pci_enable_device (dev) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev->current_state = PCI_D0;
|
||||
//dev->dev.power.power_state = PMSG_ON;
|
||||
|
||||
if (!dev->irq) {
|
||||
err ("Found HC with no IRQ. Check BIOS/PCI %s setup!",
|
||||
dev->slot_name);
|
||||
return -ENODEV;
|
||||
retval = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
|
||||
if (!hcd) {
|
||||
retval = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
|
||||
region = 0;
|
||||
resource = pci_resource_start (dev, 0);
|
||||
len = pci_resource_len (dev, 0);
|
||||
if (!request_mem_region (resource, len, driver->description)) {
|
||||
dbg ("controller already in use");
|
||||
return -EBUSY;
|
||||
hcd->rsrc_start = pci_resource_start (dev, 0);
|
||||
hcd->rsrc_len = pci_resource_len (dev, 0);
|
||||
if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,
|
||||
driver->description)) {
|
||||
dev_dbg (&dev->dev, "controller already in use\n");
|
||||
retval = -EBUSY;
|
||||
goto err2;
|
||||
}
|
||||
base = ioremap_nocache (resource, len);
|
||||
if (base == NULL) {
|
||||
dbg ("error mapping memory");
|
||||
hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (hcd->regs == NULL) {
|
||||
dev_dbg (&dev->dev, "error mapping memory\n");
|
||||
retval = -EFAULT;
|
||||
clean_1:
|
||||
release_mem_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
} else { // UHCI
|
||||
//resource = 0;
|
||||
len = 0;
|
||||
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
|
||||
if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
|
||||
continue;
|
||||
int region;
|
||||
|
||||
resource = pci_resource_start (dev, region);
|
||||
len = pci_resource_len (dev, region);
|
||||
if (request_region (resource, len,
|
||||
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
|
||||
//if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
|
||||
// continue;
|
||||
|
||||
hcd->rsrc_start = pci_resource_start (dev, region);
|
||||
hcd->rsrc_len = pci_resource_len (dev, region);
|
||||
if (request_region (hcd->rsrc_start, hcd->rsrc_len,
|
||||
driver->description))
|
||||
break;
|
||||
}
|
||||
if (region == PCI_ROM_RESOURCE) {
|
||||
dbg ("no i/o regions available");
|
||||
return -EBUSY;
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
base = (void *) (ULONG_PTR)resource.u.LowPart;
|
||||
}
|
||||
|
||||
// driver->start(), later on, will transfer device from
|
||||
// control by SMM/BIOS to control by Linux (if needed)
|
||||
|
||||
pci_set_drvdata (dev, hcd); // ReactOS-specific, needed in order to get pointer to usb_hcd in any place.
|
||||
pci_set_master (dev);
|
||||
|
||||
hcd = driver->hcd_alloc ();
|
||||
if (hcd == NULL){
|
||||
dbg ("hcd alloc fail");
|
||||
retval = -ENOMEM;
|
||||
clean_2:
|
||||
if (driver->flags & HCD_MEMORY) {
|
||||
iounmap (base);
|
||||
goto clean_1;
|
||||
} else {
|
||||
release_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
pci_set_drvdata (dev, hcd);
|
||||
hcd->driver = driver;
|
||||
hcd->description = driver->description;
|
||||
hcd->pdev = dev;
|
||||
hcd->self.bus_name = dev->slot_name;
|
||||
hcd->product_desc = dev->dev.name;
|
||||
hcd->self.controller = &dev->dev;
|
||||
hcd->controller = hcd->self.controller;
|
||||
{
|
||||
/* Test code by Fireball */
|
||||
struct device dv;
|
||||
dma_addr_t dma_handle;
|
||||
void *res;
|
||||
|
||||
if ((retval = hcd_buffer_create (hcd)) != 0) {
|
||||
clean_3:
|
||||
driver->hcd_free (hcd);
|
||||
goto clean_2;
|
||||
dv.dev_ext = dev->dev_ext;
|
||||
res = dma_alloc_coherent(&dv, 12, &dma_handle, 0);
|
||||
}
|
||||
|
||||
dev_info (hcd->controller, "%s\n", hcd->product_desc);
|
||||
|
||||
#ifndef __sparc__
|
||||
sprintf (buf, "%d", dev->irq);
|
||||
#else
|
||||
bufp = __irq_itoa(dev->irq);
|
||||
#endif
|
||||
if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd)
|
||||
!= 0) {
|
||||
dev_err (hcd->controller,
|
||||
"request interrupt %s failed\n", buf);
|
||||
retval = -EBUSY;
|
||||
goto clean_3;
|
||||
}
|
||||
hcd->irq = dev->irq;
|
||||
|
||||
hcd->regs = base;
|
||||
hcd->region = region;
|
||||
dev_info (hcd->controller, "irq %s, %s %p\n", buf,
|
||||
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
|
||||
base);
|
||||
|
||||
usb_bus_init (&hcd->self);
|
||||
hcd->self.op = &usb_hcd_operations;
|
||||
hcd->self.hcpriv = (void *) hcd;
|
||||
|
||||
INIT_LIST_HEAD (&hcd->dev_list);
|
||||
|
||||
usb_register_bus (&hcd->self);
|
||||
|
||||
if ((retval = driver->start (hcd)) < 0)
|
||||
usb_hcd_pci_remove (dev);
|
||||
retval = usb_add_hcd (hcd, dev->irq, SA_SHIRQ);
|
||||
if (retval != 0)
|
||||
goto err4;
|
||||
|
||||
//ReactOS-specific: Init core drivers here
|
||||
UsbKeyBoardInit();
|
||||
UsbMouseInit();
|
||||
|
||||
return retval;
|
||||
|
||||
err4:
|
||||
if (driver->flags & HCD_MEMORY) {
|
||||
iounmap (hcd->regs);
|
||||
err3:
|
||||
release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
|
||||
} else
|
||||
release_region (hcd->rsrc_start, hcd->rsrc_len);
|
||||
err2:
|
||||
usb_put_hcd (hcd);
|
||||
err1:
|
||||
pci_disable_device (dev);
|
||||
dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_probe);
|
||||
|
||||
@@ -224,98 +201,121 @@ void STDCALL usb_hcd_pci_remove (struct pci_dev *dev)
|
||||
hcd = pci_get_drvdata(dev);
|
||||
if (!hcd)
|
||||
return;
|
||||
dev_info (hcd->controller, "remove, state %x\n", hcd->state);
|
||||
|
||||
if (in_interrupt ())
|
||||
BUG ();
|
||||
|
||||
hub = hcd->self.root_hub;
|
||||
hcd->state = USB_STATE_QUIESCING;
|
||||
|
||||
dev_dbg (hcd->controller, "roothub graceful disconnect\n");
|
||||
usb_disconnect (&hub);
|
||||
|
||||
hcd->driver->stop (hcd);
|
||||
hcd_buffer_destroy (hcd);
|
||||
hcd->state = USB_STATE_HALT;
|
||||
pci_set_drvdata (dev, 0);
|
||||
|
||||
free_irq (hcd->irq, hcd);
|
||||
usb_remove_hcd (hcd);
|
||||
if (hcd->driver->flags & HCD_MEMORY) {
|
||||
iounmap (hcd->regs);
|
||||
release_mem_region (pci_resource_start (dev, 0),
|
||||
pci_resource_len (dev, 0));
|
||||
release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
|
||||
} else {
|
||||
release_region (pci_resource_start (dev, hcd->region),
|
||||
pci_resource_len (dev, hcd->region));
|
||||
release_region (hcd->rsrc_start, hcd->rsrc_len);
|
||||
}
|
||||
|
||||
usb_deregister_bus (&hcd->self);
|
||||
if (atomic_read (&hcd->self.refcnt) != 1) {
|
||||
dev_warn (hcd->controller,
|
||||
"dangling refs (%d) to bus %d!\n",
|
||||
atomic_read (&hcd->self.refcnt) - 1,
|
||||
hcd->self.busnum);
|
||||
}
|
||||
hcd->driver->hcd_free (hcd);
|
||||
usb_put_hcd (hcd);
|
||||
pci_disable_device(dev);
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_remove);
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
* Some "sleep" power levels imply updating struct usb_driver
|
||||
* to include a callback asking hcds to do their bit by checking
|
||||
* if all the drivers can suspend. Gets involved with remote wakeup.
|
||||
*
|
||||
* If there are pending urbs, then HCs will need to access memory,
|
||||
* causing extra power drain. New sleep()/wakeup() PM calls might
|
||||
* be needed, beyond PCI suspend()/resume(). The root hub timer
|
||||
* still be accessing memory though ...
|
||||
*
|
||||
* FIXME: USB should have some power budgeting support working with
|
||||
* all kinds of hubs.
|
||||
*
|
||||
* FIXME: This assumes only D0->D3 suspend and D3->D0 resume.
|
||||
* D1 and D2 states should do something, yes?
|
||||
*
|
||||
* FIXME: Should provide generic enable_wake(), calling pci_enable_wake()
|
||||
* for all supported states, so that USB remote wakeup can work for any
|
||||
* devices that support it (and are connected via powered hubs).
|
||||
*
|
||||
* FIXME: resume doesn't seem to work right any more...
|
||||
*/
|
||||
|
||||
|
||||
// 2.4 kernels have issued concurrent resumes (w/APM)
|
||||
// we defend against that error; PCI doesn't yet.
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
|
||||
* @dev: USB Host Controller being suspended
|
||||
* @message: semantics in flux
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as suspend().
|
||||
*/
|
||||
int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
|
||||
int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
int retval = 0;
|
||||
int has_pci_pm;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "suspend to state %d\n", state);
|
||||
|
||||
pci_save_state (dev, hcd->pci_state);
|
||||
/* FIXME until the generic PM interfaces change a lot more, this
|
||||
* can't use PCI D1 and D2 states. For example, the confusion
|
||||
* between messages and states will need to vanish, and messages
|
||||
* will need to provide a target system state again.
|
||||
*
|
||||
* It'll be important to learn characteristics of the target state,
|
||||
* especially on embedded hardware where the HCD will often be in
|
||||
* charge of an external VBUS power supply and one or more clocks.
|
||||
* Some target system states will leave them active; others won't.
|
||||
* (With PCI, that's often handled by platform BIOS code.)
|
||||
*/
|
||||
|
||||
// FIXME for all connected devices, leaf-to-root:
|
||||
// driver->suspend()
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
/* even when the PCI layer rejects some of the PCI calls
|
||||
* below, HCs can try global suspend and reduce DMA traffic.
|
||||
* PM-sensitive HCDs may already have done this.
|
||||
*/
|
||||
has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
|
||||
|
||||
/* driver may want to disable DMA etc */
|
||||
retval = hcd->driver->suspend (hcd, state);
|
||||
hcd->state = USB_STATE_SUSPENDED;
|
||||
switch (hcd->state) {
|
||||
|
||||
pci_set_power_state (dev, state);
|
||||
/* entry if root hub wasn't yet suspended ... from sysfs,
|
||||
* without autosuspend, or if USB_SUSPEND isn't configured.
|
||||
*/
|
||||
case HC_STATE_RUNNING:
|
||||
hcd->state = HC_STATE_QUIESCING;
|
||||
retval = hcd->driver->suspend (hcd, message);
|
||||
if (retval) {
|
||||
dev_dbg (hcd->self.controller,
|
||||
"suspend fail, retval %d\n",
|
||||
retval);
|
||||
break;
|
||||
}
|
||||
hcd->state = HC_STATE_SUSPENDED;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
|
||||
* controller and/or root hub will already have been suspended,
|
||||
* but it won't be ready for a PCI resume call.
|
||||
*
|
||||
* FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
|
||||
* have been called, otherwise root hub timers still run ...
|
||||
*/
|
||||
case HC_STATE_SUSPENDED:
|
||||
/* no DMA or IRQs except when HC is active */
|
||||
if (dev->current_state == PCI_D0) {
|
||||
pci_save_state (dev);
|
||||
pci_disable_device (dev);
|
||||
}
|
||||
|
||||
if (!has_pci_pm) {
|
||||
dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* NOTE: dev->current_state becomes nonzero only here, and
|
||||
* only for devices that support PCI PM. Also, exiting
|
||||
* PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
|
||||
* some device state (e.g. as part of clock reinit).
|
||||
*/
|
||||
retval = pci_set_power_state (dev, PCI_D3hot);
|
||||
if (retval == 0) {
|
||||
dev_dbg (hcd->self.controller, "--> PCI D3\n");
|
||||
retval = pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
|
||||
if (retval)
|
||||
break;
|
||||
retval = pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
|
||||
} else if (retval < 0) {
|
||||
dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
|
||||
retval);
|
||||
(void) usb_hcd_pci_resume (dev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
|
||||
hcd->state);
|
||||
WARN_ON(1);
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* update power_state **ONLY** to make sysfs happier */
|
||||
if (retval == 0)
|
||||
dev->dev.power.power_state = message;
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_suspend);
|
||||
@@ -332,39 +332,91 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
|
||||
int retval;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "resume\n");
|
||||
|
||||
/* guard against multiple resumes (APM bug?) */
|
||||
atomic_inc (&hcd->resume_count);
|
||||
if (atomic_read (&hcd->resume_count) != 1) {
|
||||
dev_err (hcd->controller, "concurrent PCI resumes\n");
|
||||
retval = 0;
|
||||
goto done;
|
||||
if (hcd->state != HC_STATE_SUSPENDED) {
|
||||
dev_dbg (hcd->self.controller,
|
||||
"can't resume, not suspended!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = -EBUSY;
|
||||
if (hcd->state != USB_STATE_SUSPENDED) {
|
||||
dev_dbg (hcd->controller, "can't resume, not suspended!\n");
|
||||
goto done;
|
||||
}
|
||||
hcd->state = USB_STATE_RESUMING;
|
||||
/* NOTE: chip docs cover clean "real suspend" cases (what Linux
|
||||
* calls "standby", "suspend to RAM", and so on). There are also
|
||||
* dirty cases when swsusp fakes a suspend in "shutdown" mode.
|
||||
*/
|
||||
if (dev->current_state != PCI_D0) {
|
||||
#ifdef DEBUG
|
||||
int pci_pm;
|
||||
u16 pmcr;
|
||||
|
||||
pci_set_power_state (dev, 0);
|
||||
pci_restore_state (dev, hcd->pci_state);
|
||||
pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
|
||||
pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr);
|
||||
pmcr &= PCI_PM_CTRL_STATE_MASK;
|
||||
if (pmcr) {
|
||||
/* Clean case: power to USB and to HC registers was
|
||||
* maintained; remote wakeup is easy.
|
||||
*/
|
||||
dev_dbg(hcd->self.controller, "resume from PCI D%d\n",
|
||||
pmcr);
|
||||
} else {
|
||||
/* Clean: HC lost Vcc power, D0 uninitialized
|
||||
* + Vaux may have preserved port and transceiver
|
||||
* state ... for remote wakeup from D3cold
|
||||
* + or not; HCD must reinit + re-enumerate
|
||||
*
|
||||
* Dirty: D0 semi-initialized cases with swsusp
|
||||
* + after BIOS init
|
||||
* + after Linux init (HCD statically linked)
|
||||
*/
|
||||
dev_dbg(hcd->self.controller,
|
||||
"PCI D0, from previous PCI D%d\n",
|
||||
dev->current_state);
|
||||
}
|
||||
#endif
|
||||
retval = pci_enable_wake (dev, dev->current_state, 0);
|
||||
if (retval) {
|
||||
dev_err(hcd->self.controller,
|
||||
"can't enable_wake to %d, %d!\n",
|
||||
dev->current_state, retval);
|
||||
return retval;
|
||||
}
|
||||
retval = pci_enable_wake (dev, PCI_D3cold, 0);
|
||||
if (retval) {
|
||||
dev_err(hcd->self.controller,
|
||||
"can't enable_wake to %d, %d!\n",
|
||||
PCI_D3cold, retval);
|
||||
return retval;
|
||||
}
|
||||
} else {
|
||||
/* Same basic cases: clean (powered/not), dirty */
|
||||
dev_dbg(hcd->self.controller, "PCI legacy resume\n");
|
||||
}
|
||||
|
||||
/* NOTE: the PCI API itself is asymmetric here. We don't need to
|
||||
* pci_set_power_state(PCI_D0) since that's part of re-enabling;
|
||||
* but that won't re-enable bus mastering. Yet pci_disable_device()
|
||||
* explicitly disables bus mastering...
|
||||
*/
|
||||
retval = pci_enable_device (dev);
|
||||
if (retval < 0) {
|
||||
dev_err (hcd->self.controller,
|
||||
"can't re-enable after resume, %d!\n", retval);
|
||||
return retval;
|
||||
}
|
||||
pci_set_master (dev);
|
||||
pci_restore_state (dev);
|
||||
|
||||
dev->dev.power.power_state = PMSG_ON;
|
||||
|
||||
hcd->state = HC_STATE_RESUMING;
|
||||
hcd->saw_irq = 0;
|
||||
|
||||
retval = hcd->driver->resume (hcd);
|
||||
if (!HCD_IS_RUNNING (hcd->state)) {
|
||||
dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
|
||||
if (!HC_IS_RUNNING (hcd->state)) {
|
||||
dev_dbg (hcd->self.controller,
|
||||
"resume fail, retval %d\n", retval);
|
||||
usb_hc_died (hcd);
|
||||
// FIXME: recover, reset etc.
|
||||
} else {
|
||||
// FIXME for all connected devices, root-to-leaf:
|
||||
// driver->resume ();
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
}
|
||||
|
||||
done:
|
||||
atomic_dec (&hcd->resume_count);
|
||||
retval = pci_enable_device(dev);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_resume);
|
||||
@@ -372,3 +424,4 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -63,52 +63,60 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
|
||||
struct usb_bus self; /* hcd is-a bus */
|
||||
|
||||
const char *product_desc; /* product/vendor string */
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
char irq_descr[24]; /* driver + bus # */
|
||||
|
||||
struct timer_list rh_timer; /* drives root hub */
|
||||
struct list_head dev_list; /* devices on this bus */
|
||||
struct work_struct work;
|
||||
struct timer_list rh_timer; /* drives root-hub polling */
|
||||
struct urb *status_urb; /* the current status urb */
|
||||
|
||||
/*
|
||||
* hardware info/state
|
||||
*/
|
||||
struct hc_driver *driver; /* hw-specific hooks */
|
||||
int irq; /* irq allocated */
|
||||
void *regs; /* device memory/io */
|
||||
struct device *controller; /* handle to hardware */
|
||||
const struct hc_driver *driver; /* hw-specific hooks */
|
||||
unsigned saw_irq : 1;
|
||||
unsigned can_wakeup:1; /* hw supports wakeup? */
|
||||
unsigned remote_wakeup:1;/* sw should use wakeup? */
|
||||
unsigned rh_registered:1;/* is root hub registered? */
|
||||
|
||||
/* a few non-PCI controllers exist, mostly for OHCI */
|
||||
struct pci_dev *pdev; /* pci is typical */
|
||||
#ifdef CONFIG_PCI
|
||||
int region; /* pci region for regs */
|
||||
u32 pci_state [16]; /* for PM state save */
|
||||
atomic_t resume_count; /* multiple resumes issue */
|
||||
#endif
|
||||
/* The next flag is a stopgap, to be removed when all the HCDs
|
||||
* support the new root-hub polling mechanism. */
|
||||
unsigned uses_new_polling:1;
|
||||
unsigned poll_rh:1; /* poll for rh status? */
|
||||
unsigned poll_pending:1; /* status has changed? */
|
||||
|
||||
int irq; /* irq allocated */
|
||||
void __iomem *regs; /* device memory/io */
|
||||
PHYSICAL_ADDRESS rsrc_start; /* memory/io resource start */
|
||||
u32 rsrc_len; /* memory/io resource length */
|
||||
unsigned power_budget; /* in mA, 0 = no limit */
|
||||
|
||||
#define HCD_BUFFER_POOLS 4
|
||||
struct pci_pool *pool [HCD_BUFFER_POOLS];
|
||||
struct dma_pool *pool [HCD_BUFFER_POOLS];
|
||||
|
||||
int state;
|
||||
# define __ACTIVE 0x01
|
||||
# define __SLEEPY 0x02
|
||||
# define __SUSPEND 0x04
|
||||
# define __TRANSIENT 0x80
|
||||
|
||||
# define USB_STATE_HALT 0
|
||||
# define USB_STATE_RUNNING (__ACTIVE)
|
||||
# define USB_STATE_READY (__ACTIVE|__SLEEPY)
|
||||
# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
||||
# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
||||
# define USB_STATE_SUSPENDED (__SUSPEND)
|
||||
# define HC_STATE_HALT 0
|
||||
# define HC_STATE_RUNNING (__ACTIVE)
|
||||
# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
||||
# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
||||
# define HC_STATE_SUSPENDED (__SUSPEND)
|
||||
|
||||
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
|
||||
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
||||
#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
|
||||
#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
||||
|
||||
/* more shared queuing code would be good; it should support
|
||||
* smarter scheduling, handle transaction translators, etc;
|
||||
* input size of periodic table to an interrupt scheduler.
|
||||
* (ohci 32, uhci 1024, ehci 256/512/1024).
|
||||
*/
|
||||
|
||||
/* The HC driver's private data is stored at the end of
|
||||
* this structure.
|
||||
*/
|
||||
unsigned long hcd_priv[0];
|
||||
//__attribute__ ((aligned (sizeof(unsigned long))));
|
||||
};
|
||||
|
||||
/* 2.4 does this a bit differently ... */
|
||||
@@ -118,14 +126,6 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
|
||||
}
|
||||
|
||||
|
||||
struct hcd_dev { /* usb_device.hcpriv points to this */
|
||||
struct list_head dev_list; /* on this hcd */
|
||||
struct list_head urb_list; /* pending on this dev */
|
||||
|
||||
/* per-configuration HC/HCD state, such as QH or ED */
|
||||
void *ep[32];
|
||||
};
|
||||
|
||||
// urb.hcpriv is really hardware-specific
|
||||
|
||||
struct hcd_timeout { /* timeouts we allocate */
|
||||
@@ -141,29 +141,33 @@ struct hcd_timeout { /* timeouts we allocate */
|
||||
*/
|
||||
|
||||
struct usb_operations {
|
||||
int (*allocate)(struct usb_device *);
|
||||
int (*deallocate)(struct usb_device *);
|
||||
int (*get_frame_number) (struct usb_device *usb_dev);
|
||||
int (*submit_urb) (struct urb *urb, int mem_flags);
|
||||
int (*unlink_urb) (struct urb *urb);
|
||||
int (*submit_urb) (struct urb *urb, unsigned mem_flags);
|
||||
int (*unlink_urb) (struct urb *urb, int status);
|
||||
|
||||
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
|
||||
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
|
||||
int mem_flags,
|
||||
unsigned mem_flags,
|
||||
dma_addr_t *dma);
|
||||
void (*buffer_free)(struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
void (*disable)(struct usb_device *udev, int bEndpointAddress);
|
||||
void (*disable)(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep);
|
||||
|
||||
/* global suspend/resume of bus */
|
||||
int (*hub_suspend)(struct usb_bus *);
|
||||
int (*hub_resume)(struct usb_bus *);
|
||||
};
|
||||
|
||||
/* each driver provides one of these, and hardware init support */
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
// new struct from 2.6
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
const char *product_desc; /* product/vendor string */
|
||||
size_t hcd_priv_size; /* size of private data */
|
||||
|
||||
/* irq handler */
|
||||
irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
@@ -177,8 +181,11 @@ struct hc_driver {
|
||||
int (*reset) (struct usb_hcd *hcd);
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* NOTE: these suspend/resume calls relate to the HC as
|
||||
* a whole, not just the root hub; they're for bus glue.
|
||||
*/
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
int (*suspend) (struct usb_hcd *hcd, pm_message_t message);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
@@ -189,78 +196,36 @@ struct hc_driver {
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep,
|
||||
struct urb *urb,
|
||||
unsigned mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
u8 *buf, u16 wLength);
|
||||
};
|
||||
|
||||
// old version, "just in case"
|
||||
#if 0
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
int (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
struct usb_host_endpoint *ep);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
int (*hub_suspend)(struct usb_hcd *);
|
||||
int (*hub_resume)(struct usb_hcd *);
|
||||
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
|
||||
void (*hub_irq_enable)(struct usb_hcd *);
|
||||
/* Needed only if port-change IRQs are level-triggered */
|
||||
};
|
||||
#endif
|
||||
|
||||
extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
|
||||
extern void STDCALL usb_bus_init (struct usb_bus *bus);
|
||||
extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
|
||||
extern struct usb_hcd* STDCALL usb_create_hcd (const struct hc_driver *driver,
|
||||
struct device *dev, char *bus_name);
|
||||
extern void STDCALL usb_put_hcd (struct usb_hcd *hcd);
|
||||
extern int STDCALL usb_add_hcd(struct usb_hcd *hcd,
|
||||
unsigned int irqnum, unsigned long irqflags);
|
||||
extern void STDCALL usb_remove_hcd(struct usb_hcd *hcd);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev;
|
||||
@@ -270,11 +235,8 @@ extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev,
|
||||
extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
|
||||
// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
|
||||
extern int usb_hcd_pci_resume (struct pci_dev *dev);
|
||||
// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
@@ -284,31 +246,26 @@ int hcd_buffer_create (struct usb_hcd *hcd);
|
||||
void hcd_buffer_destroy (struct usb_hcd *hcd);
|
||||
|
||||
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
|
||||
int mem_flags, dma_addr_t *dma);
|
||||
unsigned mem_flags, dma_addr_t *dma);
|
||||
void hcd_buffer_free (struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
/* generic bus glue, needed for host controllers that don't use PCI */
|
||||
extern struct usb_operations usb_hcd_operations;
|
||||
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
|
||||
|
||||
extern void STDCALL usb_hc_died (struct usb_hcd *hcd);
|
||||
extern void STDCALL usb_hcd_poll_rh_status(struct usb_hcd *hcd);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
|
||||
extern int usb_new_device(struct usb_device *dev, struct device *parent);
|
||||
extern void STDCALL usb_connect(struct usb_device *dev);
|
||||
extern struct usb_device* STDCALL usb_alloc_dev(struct usb_device *parent,
|
||||
struct usb_bus *, unsigned port);
|
||||
extern int usb_new_device(struct usb_device *dev);
|
||||
extern void usb_disconnect(struct usb_device **);
|
||||
|
||||
/* exported to hub driver ONLY to support usb_reset_device () */
|
||||
extern int usb_get_configuration(struct usb_device *dev);
|
||||
extern void usb_set_maxpacket(struct usb_device *dev);
|
||||
extern void usb_destroy_configuration(struct usb_device *dev);
|
||||
extern int usb_set_address(struct usb_device *dev);
|
||||
|
||||
/* use these only before the device's address has been set */
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -332,10 +289,6 @@ extern int usb_set_address(struct usb_device *dev);
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
/* table 9.6 standard features */
|
||||
#define DEVICE_REMOTE_WAKEUP 1
|
||||
#define ENDPOINT_HALT 0
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
|
||||
@@ -380,38 +333,31 @@ extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *u
|
||||
extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
|
||||
|
||||
/*
|
||||
* Ceiling microseconds (typical) for that many bytes at high speed
|
||||
* Ceiling [nano/micro]seconds (typical) for that many bytes at high speed
|
||||
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
||||
* to preallocate bandwidth)
|
||||
*/
|
||||
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
||||
#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
#define HS_NSECS(bytes) ( ((55 * 8 * 2083) \
|
||||
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
|
||||
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
|
||||
|
||||
extern long STDCALL usb_calc_bus_time (int speed, int is_input,
|
||||
int isoc, int bytecount);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *);
|
||||
extern void STDCALL usb_free_bus (struct usb_bus *);
|
||||
extern struct usb_bus* STDCALL usb_alloc_bus (struct usb_operations *);
|
||||
|
||||
extern void STDCALL usb_register_bus (struct usb_bus *);
|
||||
extern void STDCALL usb_deregister_bus (struct usb_bus *);
|
||||
extern void STDCALL usb_hcd_resume_root_hub (struct usb_hcd *hcd);
|
||||
|
||||
extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev,
|
||||
struct device *parent_dev);
|
||||
|
||||
/* for portability to 2.4, hcds should call this */
|
||||
static inline int hcd_register_root (struct usb_hcd *hcd)
|
||||
{
|
||||
return usb_register_root_hub (
|
||||
hcd_to_bus (hcd)->root_hub, hcd->controller);
|
||||
}
|
||||
extern void usb_set_device_state(struct usb_device *udev,
|
||||
enum usb_device_state new_state);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -419,15 +365,16 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
|
||||
|
||||
extern struct list_head usb_bus_list;
|
||||
extern struct semaphore usb_bus_list_lock;
|
||||
extern wait_queue_head_t usb_kill_urb_queue;
|
||||
|
||||
extern void usb_bus_get (struct usb_bus *bus);
|
||||
extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
|
||||
extern void usb_bus_put (struct usb_bus *bus);
|
||||
|
||||
extern void usb_enable_root_hub_irq (struct usb_bus *bus);
|
||||
|
||||
extern int usb_find_interface_driver (struct usb_device *dev,
|
||||
struct usb_interface *interface);
|
||||
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
|
||||
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
|
||||
|
||||
/*
|
||||
@@ -474,6 +421,66 @@ static inline void usbfs_cleanup(void) { }
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_USB_MON)
|
||||
|
||||
struct usb_mon_operations {
|
||||
void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
|
||||
void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
|
||||
void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
|
||||
/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
|
||||
void (*bus_add)(struct usb_bus *bus);
|
||||
void (*bus_remove)(struct usb_bus *bus);
|
||||
};
|
||||
|
||||
extern struct usb_mon_operations *mon_ops;
|
||||
|
||||
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
|
||||
{
|
||||
if (bus->monitored)
|
||||
(*mon_ops->urb_submit)(bus, urb);
|
||||
}
|
||||
|
||||
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
|
||||
int error)
|
||||
{
|
||||
if (bus->monitored)
|
||||
(*mon_ops->urb_submit_error)(bus, urb, error);
|
||||
}
|
||||
|
||||
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
|
||||
{
|
||||
if (bus->monitored)
|
||||
(*mon_ops->urb_complete)(bus, urb);
|
||||
}
|
||||
|
||||
static inline void usbmon_notify_bus_add(struct usb_bus *bus)
|
||||
{
|
||||
if (mon_ops)
|
||||
(*mon_ops->bus_add)(bus);
|
||||
}
|
||||
|
||||
static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
|
||||
{
|
||||
if (mon_ops)
|
||||
(*mon_ops->bus_remove)(bus);
|
||||
}
|
||||
|
||||
int usb_mon_register(struct usb_mon_operations *ops);
|
||||
void usb_mon_deregister(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
|
||||
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
|
||||
int error) {}
|
||||
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
|
||||
static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
|
||||
static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
|
||||
|
||||
#endif /* CONFIG_USB_MON */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
|
||||
// bleech -- resurfaced in 2.4.11 or 2.4.12
|
||||
#define bitmap DeviceRemovable
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -59,10 +59,11 @@
|
||||
* Hub Status and Hub Change results
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
*/
|
||||
#include <pshpack1.h>
|
||||
struct usb_port_status {
|
||||
__u16 wPortStatus;
|
||||
__u16 wPortChange;
|
||||
} __attribute__ ((packed));
|
||||
__le16 wPortStatus;
|
||||
__le16 wPortChange;
|
||||
};
|
||||
|
||||
/*
|
||||
* wPortStatus bit field
|
||||
@@ -103,9 +104,9 @@ struct usb_port_status {
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* D7 */
|
||||
|
||||
struct usb_hub_status {
|
||||
__u16 wHubStatus;
|
||||
__u16 wHubChange;
|
||||
} __attribute__ ((packed));
|
||||
__le16 wHubStatus;
|
||||
__le16 wHubChange;
|
||||
};
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
@@ -137,10 +138,33 @@ struct usb_hub_descriptor {
|
||||
/* add 1 bit for hub status change; round to bytes */
|
||||
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
__u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
/* port indicator status selectors, tables 11-7 and 11-25 */
|
||||
#define HUB_LED_AUTO 0
|
||||
#define HUB_LED_AMBER 1
|
||||
#define HUB_LED_GREEN 2
|
||||
#define HUB_LED_OFF 3
|
||||
|
||||
enum hub_led_mode {
|
||||
INDICATOR_AUTO = 0,
|
||||
INDICATOR_CYCLE,
|
||||
/* software blinks for attention: software, hardware, reserved */
|
||||
INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF,
|
||||
INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF,
|
||||
INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
struct usb_device;
|
||||
|
||||
/* Transaction Translator Think Times, in bits */
|
||||
#define HUB_TTTT_8_BITS 0x00
|
||||
#define HUB_TTTT_16_BITS 0x20
|
||||
#define HUB_TTTT_24_BITS 0x40
|
||||
#define HUB_TTTT_32_BITS 0x60
|
||||
|
||||
/*
|
||||
* As of USB 2.0, full/low speed devices are segregated into trees.
|
||||
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
||||
@@ -154,6 +178,7 @@ struct usb_device;
|
||||
struct usb_tt {
|
||||
struct usb_device *hub; /* upstream highspeed hub */
|
||||
int multi; /* true means one TT per port */
|
||||
unsigned think_time; /* think time in ns */
|
||||
|
||||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
@@ -170,11 +195,12 @@ struct usb_tt_clear {
|
||||
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
|
||||
|
||||
struct usb_hub {
|
||||
struct usb_interface *intf; /* the "real" device */
|
||||
struct device *intfdev; /* the "interface" device */
|
||||
struct usb_device *hdev;
|
||||
struct urb *urb; /* for interrupt polling pipe */
|
||||
|
||||
/* buffer for urb ... 1 bit each for hub and children, rounded up */
|
||||
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
/* buffer for urb ... with extra space in case of babble */
|
||||
char (*buffer)[8];
|
||||
dma_addr_t buffer_dma; /* DMA address for buffer */
|
||||
union {
|
||||
struct usb_hub_status hub;
|
||||
@@ -183,13 +209,28 @@ struct usb_hub {
|
||||
|
||||
int error; /* last reported error */
|
||||
int nerrors; /* track consecutive errors */
|
||||
int RestCounter;
|
||||
struct list_head hub_list; /* all hubs */
|
||||
|
||||
struct list_head event_list; /* hubs w/data or errs ready */
|
||||
unsigned long event_bits[1]; /* status change bitmask */
|
||||
unsigned long change_bits[1]; /* ports with logical connect
|
||||
status change */
|
||||
unsigned long busy_bits[1]; /* ports being reset */
|
||||
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
|
||||
#error event_bits[] is too short!
|
||||
#endif
|
||||
|
||||
struct usb_hub_descriptor *descriptor; /* class descriptor */
|
||||
struct semaphore khubd_sem;
|
||||
struct usb_tt tt; /* Transaction Translator */
|
||||
|
||||
u8 power_budget; /* in 2mA units; or zero */
|
||||
|
||||
unsigned quiescing:1;
|
||||
unsigned activating:1;
|
||||
unsigned resume_root_hub:1;
|
||||
|
||||
unsigned has_indicators:1;
|
||||
enum hub_led_mode indicator[USB_MAXCHILDREN];
|
||||
struct work_struct leds;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_HUB_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,14 @@
|
||||
#include "../miniport/usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
|
||||
#define to_urb(d) container_of(d, struct urb, kref)
|
||||
|
||||
static void urb_destroy(struct kref *kref)
|
||||
{
|
||||
struct urb *urb = to_urb(kref);
|
||||
kfree(urb);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_init_urb - initializes a urb so that it can be used by a USB driver
|
||||
* @urb: pointer to the urb to initialize
|
||||
@@ -19,7 +27,7 @@ void STDCALL usb_init_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
memset(urb, 0, sizeof(*urb));
|
||||
urb->count = (atomic_t)ATOMIC_INIT(1);
|
||||
kref_init(&urb->kref);
|
||||
spin_lock_init(&urb->lock);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +48,7 @@ void STDCALL usb_init_urb(struct urb *urb)
|
||||
*
|
||||
* The driver must call usb_free_urb() when it is finished with the urb.
|
||||
*/
|
||||
struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
struct urb* STDCALL usb_alloc_urb(int iso_packets, unsigned mem_flags)
|
||||
{
|
||||
struct urb *urb;
|
||||
|
||||
@@ -57,7 +65,7 @@ struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
|
||||
/**
|
||||
* usb_free_urb - frees the memory used by a urb when all users of it are finished
|
||||
* @urb: pointer to the urb to free
|
||||
* @urb: pointer to the urb to free, may be NULL
|
||||
*
|
||||
* Must be called when a user of a urb is finished with it. When the last user
|
||||
* of the urb calls this function, the memory of the urb is freed.
|
||||
@@ -68,15 +76,12 @@ struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
void STDCALL usb_free_urb(struct urb *urb)
|
||||
{
|
||||
if (urb)
|
||||
if (atomic_dec_and_test(&urb->count))
|
||||
{
|
||||
kfree(urb);
|
||||
}
|
||||
kref_put(&urb->kref, urb_destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_get_urb - increments the reference count of the urb
|
||||
* @urb: pointer to the urb to modify
|
||||
* @urb: pointer to the urb to modify, may be NULL
|
||||
*
|
||||
* This must be called whenever a urb is transferred from a device driver to a
|
||||
* host controller driver. This allows proper reference counting to happen
|
||||
@@ -84,16 +89,14 @@ void STDCALL usb_free_urb(struct urb *urb)
|
||||
*
|
||||
* A pointer to the urb with the incremented reference counter is returned.
|
||||
*/
|
||||
struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
struct urb* STDCALL usb_get_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
atomic_inc(&urb->count);
|
||||
return urb;
|
||||
} else
|
||||
return NULL;
|
||||
if (urb)
|
||||
kref_get(&urb->kref);
|
||||
return urb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
@@ -106,7 +109,8 @@ struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
* describing that request to the USB subsystem. Request completion will
|
||||
* be indicated later, asynchronously, by calling the completion handler.
|
||||
* The three types of completion are success, error, and unlink
|
||||
* (also called "request cancellation").
|
||||
* (a software-induced fault, also called "request cancellation").
|
||||
*
|
||||
* URBs may be submitted in interrupt context.
|
||||
*
|
||||
* The caller must have correctly initialized the URB before submitting
|
||||
@@ -117,12 +121,23 @@ struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
*
|
||||
* Successful submissions return 0; otherwise this routine returns a
|
||||
* negative error number. If the submission is successful, the complete()
|
||||
* callback from the urb will be called exactly once, when the USB core and
|
||||
* host controller driver are finished with the urb. When the completion
|
||||
* callback from the URB will be called exactly once, when the USB core and
|
||||
* Host Controller Driver (HCD) are finished with the URB. When the completion
|
||||
* function is called, control of the URB is returned to the device
|
||||
* driver which issued the request. The completion handler may then
|
||||
* immediately free or reuse that URB.
|
||||
*
|
||||
* With few exceptions, USB device drivers should never access URB fields
|
||||
* provided by usbcore or the HCD until its complete() is called.
|
||||
* The exceptions relate to periodic transfer scheduling. For both
|
||||
* interrupt and isochronous urbs, as part of successful URB submission
|
||||
* urb->interval is modified to reflect the actual transfer period used
|
||||
* (normally some power of two units). And for isochronous urbs,
|
||||
* urb->start_frame is modified to reflect when the URB's transfers were
|
||||
* scheduled to start. Not all isochronous transfer scheduling policies
|
||||
* will work, but most host controller drivers should easily handle ISO
|
||||
* queues going from now until 10-200 msec into the future.
|
||||
*
|
||||
* For control endpoints, the synchronous usb_control_msg() call is
|
||||
* often used (in non-interrupt context) instead of this call.
|
||||
* That is often used through convenience wrappers, for the requests
|
||||
@@ -133,15 +148,17 @@ struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
*
|
||||
* URBs may be submitted to endpoints before previous ones complete, to
|
||||
* minimize the impact of interrupt latencies and system overhead on data
|
||||
* throughput. This is required for continuous isochronous data streams,
|
||||
* throughput. With that queuing policy, an endpoint's queue would never
|
||||
* be empty. This is required for continuous isochronous data streams,
|
||||
* and may also be required for some kinds of interrupt transfers. Such
|
||||
* queueing also maximizes bandwidth utilization by letting USB controllers
|
||||
* queuing also maximizes bandwidth utilization by letting USB controllers
|
||||
* start work on later requests before driver software has finished the
|
||||
* completion processing for earlier requests.
|
||||
* completion processing for earlier (successful) requests.
|
||||
*
|
||||
* Bulk and Isochronous URBs may always be queued. At this writing, all
|
||||
* mainstream host controller drivers support queueing for control and
|
||||
* interrupt transfer requests.
|
||||
* As of Linux 2.6, all USB endpoint transfer queues support depths greater
|
||||
* than one. This was previously a HCD-specific behavior, except for ISO
|
||||
* transfers. Non-isochronous endpoint queues are inactive during cleanup
|
||||
* after faults (transfer errors or cancellation).
|
||||
*
|
||||
* Reserved Bandwidth Transfers:
|
||||
*
|
||||
@@ -195,7 +212,7 @@ struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
* GFP_NOIO, unless b) or c) apply
|
||||
*
|
||||
*/
|
||||
int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
int STDCALL usb_submit_urb(struct urb *urb, unsigned mem_flags)
|
||||
{
|
||||
int pipe, temp, max;
|
||||
struct usb_device *dev;
|
||||
@@ -209,6 +226,8 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
(dev->state < USB_STATE_DEFAULT) ||
|
||||
(!dev->bus) || (dev->devnum <= 0))
|
||||
return -ENODEV;
|
||||
if (dev->state == USB_STATE_SUSPENDED)
|
||||
return -EHOSTUNREACH;
|
||||
if (!(op = dev->bus->op) || !op->submit_urb)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -226,13 +245,6 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
|
||||
return -ENODEV;
|
||||
|
||||
/* (actually HCDs may need to duplicate this, endpoint might yet
|
||||
* stall due to queued bulk/intr transactions that complete after
|
||||
* we check)
|
||||
*/
|
||||
if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
|
||||
return -EPIPE;
|
||||
|
||||
/* FIXME there should be a sharable lock protecting us against
|
||||
* config/altsetting changes and disconnects, kicking in here.
|
||||
* (here == before maxpacket, and eventually endpoint type,
|
||||
@@ -241,11 +253,10 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
|
||||
max = usb_maxpacket (dev, pipe, is_out);
|
||||
if (max <= 0) {
|
||||
dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
|
||||
__FUNCTION__,
|
||||
usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
|
||||
dev->bus->bus_name, dev->devpath,
|
||||
max);
|
||||
dev_dbg(&dev->dev,
|
||||
"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
|
||||
usb_pipeendpoint (pipe), is_out ? "out" : "in",
|
||||
__FUNCTION__, max);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
@@ -259,7 +270,7 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
||||
if (dev->speed == USB_SPEED_HIGH) {
|
||||
int mult = 1 + ((max >> 11) & 0x03);
|
||||
max &= 0x03ff;
|
||||
max &= 0x07ff;
|
||||
max *= mult;
|
||||
}
|
||||
|
||||
@@ -287,9 +298,8 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
unsigned int allowed;
|
||||
|
||||
/* enforce simple/standard policy */
|
||||
allowed = URB_ASYNC_UNLINK; // affects later unlinks
|
||||
allowed |= URB_NO_DMA_MAP;
|
||||
allowed |= URB_NO_INTERRUPT;
|
||||
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
|
||||
URB_NO_INTERRUPT);
|
||||
switch (temp) {
|
||||
case PIPE_BULK:
|
||||
if (is_out)
|
||||
@@ -368,31 +378,109 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
|
||||
/**
|
||||
* usb_unlink_urb - abort/cancel a transfer request for an endpoint
|
||||
* @urb: pointer to urb describing a previously submitted request
|
||||
* @urb: pointer to urb describing a previously submitted request,
|
||||
* may be NULL
|
||||
*
|
||||
* This routine cancels an in-progress request. The requests's
|
||||
* completion handler will be called with a status code indicating
|
||||
* that the request has been canceled, and that control of the URB
|
||||
* has been returned to that device driver.
|
||||
* This routine cancels an in-progress request. URBs complete only
|
||||
* once per submission, and may be canceled only once per submission.
|
||||
* Successful cancellation means the requests's completion handler will
|
||||
* be called with a status code indicating that the request has been
|
||||
* canceled (rather than any other code) and will quickly be removed
|
||||
* from host controller data structures.
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
|
||||
* request is synchronous. Success is indicated by returning zero,
|
||||
* at which time the urb will have been unlinked,
|
||||
* and the completion function will see status -ENOENT. Failure is
|
||||
* indicated by any other return value. This mode may not be used
|
||||
* when unlinking an urb from an interrupt context, such as a bottom
|
||||
* half or a completion handler,
|
||||
* This request is always asynchronous.
|
||||
* Success is indicated by returning -EINPROGRESS,
|
||||
* at which time the URB will normally have been unlinked but not yet
|
||||
* given back to the device driver. When it is called, the completion
|
||||
* function will see urb->status == -ECONNRESET. Failure is indicated
|
||||
* by any other return value. Unlinking will fail when the URB is not
|
||||
* currently "linked" (i.e., it was never submitted, or it was unlinked
|
||||
* before, or the hardware is already finished with it), even if the
|
||||
* completion handler has not yet run.
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
|
||||
* request is asynchronous. Success is indicated by returning -EINPROGRESS,
|
||||
* at which time the urb will normally not have been unlinked,
|
||||
* and the completion function will see status -ECONNRESET. Failure is
|
||||
* indicated by any other return value.
|
||||
* Unlinking and Endpoint Queues:
|
||||
*
|
||||
* Host Controller Drivers (HCDs) place all the URBs for a particular
|
||||
* endpoint in a queue. Normally the queue advances as the controller
|
||||
* hardware processes each request. But when an URB terminates with an
|
||||
* error its queue stops, at least until that URB's completion routine
|
||||
* returns. It is guaranteed that the queue will not restart until all
|
||||
* its unlinked URBs have been fully retired, with their completion
|
||||
* routines run, even if that's not until some time after the original
|
||||
* completion handler returns. Normally the same behavior and guarantees
|
||||
* apply when an URB terminates because it was unlinked; however if an
|
||||
* URB is unlinked before the hardware has started to execute it, then
|
||||
* its queue is not guaranteed to stop until all the preceding URBs have
|
||||
* completed.
|
||||
*
|
||||
* This means that USB device drivers can safely build deep queues for
|
||||
* large or complex transfers, and clean them up reliably after any sort
|
||||
* of aborted transfer by unlinking all pending URBs at the first fault.
|
||||
*
|
||||
* Note that an URB terminating early because a short packet was received
|
||||
* will count as an error if and only if the URB_SHORT_NOT_OK flag is set.
|
||||
* Also, that all unlinks performed in any URB completion handler must
|
||||
* be asynchronous.
|
||||
*
|
||||
* Queues for isochronous endpoints are treated differently, because they
|
||||
* advance at fixed rates. Such queues do not stop when an URB is unlinked.
|
||||
* An unlinked URB may leave a gap in the stream of packets. It is undefined
|
||||
* whether such gaps can be filled in.
|
||||
*
|
||||
* When a control URB terminates with an error, it is likely that the
|
||||
* status stage of the transfer will not take place, even if it is merely
|
||||
* a soft error resulting from a short-packet with URB_SHORT_NOT_OK set.
|
||||
*/
|
||||
int STDCALL usb_unlink_urb(struct urb *urb)
|
||||
{
|
||||
if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
|
||||
return urb->dev->bus->op->unlink_urb(urb);
|
||||
else
|
||||
if (!urb)
|
||||
return -EINVAL;
|
||||
if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
|
||||
return -ENODEV;
|
||||
return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_kill_urb - cancel a transfer request and wait for it to finish
|
||||
* @urb: pointer to URB describing a previously submitted request,
|
||||
* may be NULL
|
||||
*
|
||||
* This routine cancels an in-progress request. It is guaranteed that
|
||||
* upon return all completion handlers will have finished and the URB
|
||||
* will be totally idle and available for reuse. These features make
|
||||
* this an ideal way to stop I/O in a disconnect() callback or close()
|
||||
* function. If the request has not already finished or been unlinked
|
||||
* the completion handler will see urb->status == -ENOENT.
|
||||
*
|
||||
* While the routine is running, attempts to resubmit the URB will fail
|
||||
* with error -EPERM. Thus even if the URB's completion handler always
|
||||
* tries to resubmit, it will not succeed and the URB will become idle.
|
||||
*
|
||||
* This routine may not be used in an interrupt context (such as a bottom
|
||||
* half or a completion handler), or when holding a spinlock, or in other
|
||||
* situations where the caller can't schedule().
|
||||
*/
|
||||
void STDCALL usb_kill_urb(struct urb *urb)
|
||||
{
|
||||
if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
|
||||
return;
|
||||
spin_lock_irq(&urb->lock);
|
||||
++urb->reject;
|
||||
spin_unlock_irq(&urb->lock);
|
||||
|
||||
urb->dev->bus->op->unlink_urb(urb, -ENOENT);
|
||||
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
|
||||
|
||||
spin_lock_irq(&urb->lock);
|
||||
--urb->reject;
|
||||
spin_unlock_irq(&urb->lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(usb_init_urb);
|
||||
EXPORT_SYMBOL(usb_alloc_urb);
|
||||
EXPORT_SYMBOL(usb_free_urb);
|
||||
EXPORT_SYMBOL(usb_get_urb);
|
||||
EXPORT_SYMBOL(usb_submit_urb);
|
||||
EXPORT_SYMBOL(usb_unlink_urb);
|
||||
EXPORT_SYMBOL(usb_kill_urb);
|
||||
|
||||
|
@@ -20,6 +20,11 @@
|
||||
#include "../miniport/usb_wrapper.h"
|
||||
#endif
|
||||
|
||||
void usb_show_device_descriptor(struct usb_device_descriptor *desc);
|
||||
void usb_show_config_descriptor(struct usb_config_descriptor *desc);
|
||||
void usb_show_interface_descriptor(struct usb_interface_descriptor *desc);
|
||||
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc);
|
||||
|
||||
static void usb_show_endpoint(struct usb_host_endpoint *endpoint)
|
||||
{
|
||||
usb_show_endpoint_descriptor(&endpoint->desc);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,60 @@
|
||||
/* Functions local to drivers/usb/core/ */
|
||||
|
||||
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
|
||||
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
|
||||
//extern void usb_create_sysfs_dev_files (struct usb_device *dev);
|
||||
//extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
|
||||
//extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
|
||||
//extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
|
||||
|
||||
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
|
||||
extern void usb_disable_interface (struct usb_device *dev,
|
||||
struct usb_interface *intf);
|
||||
extern void usb_release_interface_cache(struct kref *ref);
|
||||
extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
|
||||
|
||||
extern int usb_get_device_descriptor(struct usb_device *dev,
|
||||
unsigned int size);
|
||||
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
||||
|
||||
extern void usb_lock_all_devices(void);
|
||||
extern void usb_unlock_all_devices(void);
|
||||
|
||||
extern void usb_kick_khubd(struct usb_device *dev);
|
||||
extern void usb_resume_root_hub(struct usb_device *dev);
|
||||
|
||||
extern int usb_hub_init(void);
|
||||
extern void usb_hub_cleanup(void);
|
||||
extern int usb_major_init(void);
|
||||
extern void usb_major_cleanup(void);
|
||||
extern int usb_host_init(void);
|
||||
extern void usb_host_cleanup(void);
|
||||
|
||||
/* for labeling diagnostics */
|
||||
extern const char *usbcore_name;
|
||||
|
||||
/* usbfs stuff */
|
||||
/*extern struct usb_driver usbfs_driver;
|
||||
extern struct file_operations usbfs_devices_fops;
|
||||
extern struct file_operations usbfs_device_file_operations;*/
|
||||
extern void usbfs_conn_disc_event(void);
|
||||
|
||||
/*extern int usbdev_init(void);
|
||||
extern void usbdev_cleanup(void);
|
||||
extern void usbdev_add(struct usb_device *dev);
|
||||
extern void usbdev_remove(struct usb_device *dev);*/
|
||||
extern struct usb_device *usbdev_lookup_minor(int minor);
|
||||
|
||||
struct dev_state {
|
||||
struct list_head list; /* state list */
|
||||
struct usb_device *dev;
|
||||
struct file *file;
|
||||
spinlock_t lock; /* protects the async urb lists */
|
||||
struct list_head async_pending;
|
||||
struct list_head async_completed;
|
||||
wait_queue_head_t wait; /* wake up if a request completed */
|
||||
unsigned int discsignr;
|
||||
pid_t disc_pid;
|
||||
uid_t disc_uid, disc_euid;
|
||||
void __user *disccontext;
|
||||
unsigned long ifclaimed;
|
||||
};
|
||||
|
||||
|
@@ -69,10 +69,10 @@ DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
DriverObject->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH)DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usbcore\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0"
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB Port Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usbport\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbport.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
|
@@ -1,34 +1,31 @@
|
||||
;
|
||||
; Exports definition file for usbcore.sys
|
||||
;
|
||||
LIBRARY "usbport.sys"
|
||||
EXPORTS
|
||||
RegisterPortDriver@8
|
||||
usb_alloc_bus@4
|
||||
usb_alloc_dev@8
|
||||
usb_alloc_urb@8
|
||||
usb_bus_init@4
|
||||
usb_calc_bus_time@16
|
||||
usb_check_bandwidth@8
|
||||
usb_claim_bandwidth@16
|
||||
usb_connect@4
|
||||
usb_deregister_bus@4
|
||||
usb_disabled@0
|
||||
usb_exit@0
|
||||
usb_free_bus@4
|
||||
usb_free_urb@4
|
||||
usb_get_dev@4
|
||||
RegisterPortDriver
|
||||
usb_alloc_bus
|
||||
usb_alloc_dev
|
||||
usb_alloc_urb
|
||||
usb_bus_init
|
||||
usb_calc_bus_time
|
||||
usb_check_bandwidth
|
||||
usb_claim_bandwidth
|
||||
usb_deregister_bus
|
||||
usb_disabled
|
||||
usb_exit
|
||||
usb_free_urb
|
||||
usb_get_dev
|
||||
usb_get_string
|
||||
usb_get_urb@4
|
||||
usb_hcd_giveback_urb@12
|
||||
;usb_hcd_irq@12
|
||||
usb_hcd_pci_probe@8
|
||||
usb_hcd_pci_remove@4
|
||||
usb_hc_died@4
|
||||
usb_init@0
|
||||
usb_init_urb@4
|
||||
usb_put_dev@4
|
||||
usb_release_bandwidth@12
|
||||
usb_register_bus@4
|
||||
usb_register_root_hub@8
|
||||
usb_submit_urb@8
|
||||
usb_unlink_urb@4
|
||||
usb_get_urb
|
||||
usb_hcd_giveback_urb
|
||||
;usb_hcd_irq
|
||||
usb_hcd_pci_probe
|
||||
usb_hcd_pci_remove
|
||||
usb_hcd_poll_rh_status
|
||||
usb_hcd_resume_root_hub
|
||||
usb_hc_died
|
||||
usb_init
|
||||
usb_init_urb
|
||||
usb_put_dev
|
||||
usb_release_bandwidth
|
||||
usb_register_bus
|
||||
usb_submit_urb
|
||||
usb_unlink_urb
|
33
reactos/drivers/usb/usbport/usbport.mingw.def
Normal file
33
reactos/drivers/usb/usbport/usbport.mingw.def
Normal file
@@ -0,0 +1,33 @@
|
||||
;
|
||||
; Exports definition file for usbcore.sys
|
||||
;
|
||||
EXPORTS
|
||||
RegisterPortDriver@8
|
||||
usb_alloc_bus@4
|
||||
usb_alloc_dev@12
|
||||
usb_alloc_urb@8
|
||||
usb_bus_init@4
|
||||
usb_calc_bus_time@16
|
||||
usb_check_bandwidth@8
|
||||
usb_claim_bandwidth@16
|
||||
usb_deregister_bus@4
|
||||
usb_disabled@0
|
||||
usb_exit@0
|
||||
usb_free_urb@4
|
||||
usb_get_dev@4
|
||||
usb_get_string
|
||||
usb_get_urb@4
|
||||
usb_hcd_giveback_urb@12
|
||||
;usb_hcd_irq@12
|
||||
usb_hcd_pci_probe@8
|
||||
usb_hcd_pci_remove@4
|
||||
usb_hcd_poll_rh_status@4
|
||||
usb_hcd_resume_root_hub@4
|
||||
usb_hc_died@4
|
||||
usb_init@0
|
||||
usb_init_urb@4
|
||||
usb_put_dev@4
|
||||
usb_release_bandwidth@12
|
||||
usb_register_bus@4
|
||||
usb_submit_urb@8
|
||||
usb_unlink_urb@4
|
@@ -1,6 +1,8 @@
|
||||
<module name="usbport" type="kernelmodedriver" installbase="system32/drivers" installname="usbport.sys">
|
||||
<importlibrary definition="usbport.def" />
|
||||
<module name="usbport" type="kernelmodedriver" installbase="system32/drivers" installname="usbport.sys" allowwarnings="true">
|
||||
<importlibrary definition="usbport.mingw.def" />
|
||||
<!-- <linkerflag>-Wl,--enable-stdcall-fixup</linkerflag> -->
|
||||
<define name="__USE_W32API" />
|
||||
<define name="DEBUG_MODE" />
|
||||
<library>sys_base</library>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
@@ -12,7 +14,7 @@
|
||||
<file>config.c</file>
|
||||
<file>urb.c</file>
|
||||
<file>buffer_simple.c</file>
|
||||
<file>usb-debug.c</file>
|
||||
<!-- <file>usb-debug.c</file>-->
|
||||
<file>usbcore.c</file>
|
||||
<file>core_drivers/usbkey.c</file>
|
||||
<file>core_drivers/usbmouse.c</file>
|
||||
|
@@ -82,7 +82,12 @@ RtlAssert(
|
||||
#define CHECKPOINT do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0);
|
||||
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#ifdef _MSC_VER
|
||||
static __inline void DPRINT ( const char* fmt, ... )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(fmt);
|
||||
}
|
||||
#else
|
||||
#define DPRINT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
||||
#endif
|
||||
#define CHECKPOINT
|
||||
@@ -94,17 +99,18 @@ RtlAssert(
|
||||
#else
|
||||
|
||||
/* On non-debug builds, we never show these */
|
||||
#ifdef _MSC_VER
|
||||
static __inline void DPRINT1 ( const char* fmt, ... )
|
||||
{
|
||||
}
|
||||
static __inline void DPRINT ( const char* fmt, ... )
|
||||
{
|
||||
}
|
||||
#else
|
||||
#define DPRINT1(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
||||
#define DPRINT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
static __inline void DPRINT1 ( const char* fmt, ... )
|
||||
{
|
||||
}
|
||||
static __inline void DPRINT ( const char* fmt, ... )
|
||||
{
|
||||
}
|
||||
#else
|
||||
#define DPRINT1(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
||||
#define DPRINT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
||||
#endif
|
||||
|
||||
#define CHECKPOINT1
|
||||
#define CHECKPOINT
|
||||
#define UNIMPLEMENTED
|
||||
|
7
reactos/w32api/include/pshpck16.h
Normal file
7
reactos/w32api/include/pshpck16.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef RC_INVOKED
|
||||
# if ( __FreeBSD__ == 5 )
|
||||
# pragma pack(16)
|
||||
# else
|
||||
# pragma pack(push,16)
|
||||
# endif // __FreeBSD__
|
||||
#endif // RC_INVOKED
|
Reference in New Issue
Block a user