Compare commits

...

6 Commits

Author SHA1 Message Date
Aleksey Bragin
23b5638e57 Dump of changes I made to the usb2.6 branch a while ago, most probably it's my last commit to this branch. If noone else picks it up, it's going into "unmaintained" directory soon.
WARNING: These changes include debug/tracing like changes (including calls to DbgBreakPoint(), allocation unneeded buffers, etc), so please check the diff thoroughly if you want to try it. And even more, these changes aren't guaranteed to compile at all...

svn path=/branches/usb2_6/; revision=25307
2007-01-05 13:48:46 +00:00
Aleksey Bragin
539644d05f Fix module struct initialization in usbmouse, and make some visual changes to the same place in usbkeyboard.
svn path=/branches/usb2_6/; revision=20750
2006-01-09 11:24:09 +00:00
Aleksey Bragin
8b8378a51e Fix an error in struct initialization, remove some debug things.
svn path=/branches/usb2_6/; revision=20711
2006-01-08 12:55:06 +00:00
Aleksey Bragin
ebaf2fcb94 Merge r20642
svn path=/branches/usb2_6/; revision=20705
2006-01-08 10:14:14 +00:00
Aleksey Bragin
1786c4ac08 USB stack adapted from Linux 2.6.14.3.
Currently compiles with mingw and msvc, produces *lots* of warnings and doesn't work properly.

svn path=/branches/usb2_6/; revision=20702
2006-01-08 09:24:55 +00:00
Aleksey Bragin
7a17598925 Merge r20668
svn path=/branches/usb2_6/; revision=20674
2006-01-07 21:53:47 +00:00
52 changed files with 10283 additions and 6221 deletions

View File

@@ -8,8 +8,6 @@
*/
#define NDEBUG
#include <debug.h>
#include "usbcommon.h"
NTSTATUS STDCALL

View File

@@ -8,8 +8,6 @@
*/
#define NDEBUG
#include <debug.h>
#include "usbcommon.h"
NTSTATUS STDCALL

View File

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

View File

@@ -8,8 +8,6 @@
*/
#define NDEBUG
#include <debug.h>
#include "usbcommon.h"
NTSTATUS STDCALL

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View 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

View File

@@ -0,0 +1,7 @@
#ifndef RC_INVOKED
# if ( __FreeBSD__ == 5 )
# pragma pack(16)
# else
# pragma pack(push,16)
# endif // __FreeBSD__
#endif // RC_INVOKED