2 * PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/hid/hidclass/fdo.c
5 * PURPOSE: HID Class Driver
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
13 HidClassPDO_HandleQueryDeviceId(
14 IN PDEVICE_OBJECT DeviceObject
,
19 LPWSTR NewBuffer
, Ptr
;
23 // copy current stack location
25 IoCopyCurrentIrpStackLocationToNext(Irp
);
30 Status
= HidClassFDO_DispatchRequestSynchronous(DeviceObject
, Irp
);
31 if (!NT_SUCCESS(Status
))
42 Buffer
= (LPWSTR
)Irp
->IoStatus
.Information
;
43 Length
= wcslen(Buffer
);
46 // allocate new buffer
48 NewBuffer
= (LPWSTR
)ExAllocatePool(NonPagedPool
, (Length
+ 1) * sizeof(WCHAR
));
52 // failed to allocate buffer
54 return STATUS_INSUFFICIENT_RESOURCES
;
60 wcscpy(NewBuffer
, L
"HID\\");
63 // get offset to first '\\'
65 Ptr
= wcschr(Buffer
, L
'\\');
71 wcscat(NewBuffer
, Ptr
+ 1);
82 Irp
->IoStatus
.Information
= (ULONG_PTR
)NewBuffer
;
83 return STATUS_SUCCESS
;
87 HidClassPDO_HandleQueryHardwareId(
88 IN PDEVICE_OBJECT DeviceObject
,
92 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
98 // get device extension
100 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
101 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
104 // copy current stack location
106 IoCopyCurrentIrpStackLocationToNext(Irp
);
111 Status
= HidClassFDO_DispatchRequestSynchronous(DeviceObject
, Irp
);
112 if (!NT_SUCCESS(Status
))
121 // store hardware ids
123 Offset
= swprintf(&Buffer
[Offset
], L
"HID\\Vid_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension
->Attributes
.VendorID
, PDODeviceExtension
->Attributes
.ProductID
, PDODeviceExtension
->Attributes
.VersionNumber
) + 1;
124 Offset
+= swprintf(&Buffer
[Offset
], L
"HID\\Vid_%04x&Pid_%04x", PDODeviceExtension
->Attributes
.VendorID
, PDODeviceExtension
->Attributes
.ProductID
) + 1;
126 if (PDODeviceExtension
->DeviceDescription
.CollectionDesc
[PDODeviceExtension
->CollectionIndex
].UsagePage
== HID_USAGE_PAGE_GENERIC
)
128 switch(PDODeviceExtension
->DeviceDescription
.CollectionDesc
[PDODeviceExtension
->CollectionIndex
].Usage
)
130 case HID_USAGE_GENERIC_POINTER
:
131 case HID_USAGE_GENERIC_MOUSE
:
135 Offset
+= swprintf(&Buffer
[Offset
], L
"HID_DEVICE_SYSTEM_MOUSE") + 1;
137 case HID_USAGE_GENERIC_GAMEPAD
:
138 case HID_USAGE_GENERIC_JOYSTICK
:
140 // Joystick / Gamepad
142 Offset
+= swprintf(&Buffer
[Offset
], L
"HID_DEVICE_SYSTEM_GAME") + 1;
144 case HID_USAGE_GENERIC_KEYBOARD
:
145 case HID_USAGE_GENERIC_KEYPAD
:
149 Offset
+= swprintf(&Buffer
[Offset
], L
"HID_DEVICE_SYSTEM_KEYBOARD") + 1;
151 case HID_USAGE_GENERIC_SYSTEM_CTL
:
155 Offset
+= swprintf(&Buffer
[Offset
], L
"HID_DEVICE_SYSTEM_CONTROL") + 1;
159 else if (PDODeviceExtension
->DeviceDescription
.CollectionDesc
[PDODeviceExtension
->CollectionIndex
].UsagePage
== HID_USAGE_PAGE_CONSUMER
&& PDODeviceExtension
->DeviceDescription
.CollectionDesc
[PDODeviceExtension
->CollectionIndex
].Usage
== HID_USAGE_CONSUMERCTRL
)
162 // Consumer Audio Control
164 Offset
+= swprintf(&Buffer
[Offset
], L
"HID_DEVICE_SYSTEM_CONSUMER") + 1;
168 // FIXME: add 'HID_DEVICE_UP:0001_U:0002'
174 Offset
+=swprintf(&Buffer
[Offset
], L
"HID_DEVICE") + 1;
179 ExFreePool((PVOID
)Irp
->IoStatus
.Information
);
184 Ptr
= (LPWSTR
)ExAllocatePool(NonPagedPool
, (Offset
+1)* sizeof(WCHAR
));
190 Irp
->IoStatus
.Information
= 0;
191 return STATUS_INSUFFICIENT_RESOURCES
;
197 RtlCopyMemory(Ptr
, Buffer
, Offset
* sizeof(WCHAR
));
198 Ptr
[Offset
] = UNICODE_NULL
;
203 Irp
->IoStatus
.Information
= (ULONG_PTR
)Ptr
;
204 return STATUS_SUCCESS
;
208 HidClassPDO_HandleQueryInstanceId(
209 IN PDEVICE_OBJECT DeviceObject
,
215 // copy current stack location
217 IoCopyCurrentIrpStackLocationToNext(Irp
);
222 Status
= HidClassFDO_DispatchRequestSynchronous(DeviceObject
, Irp
);
223 if (!NT_SUCCESS(Status
))
230 DPRINT1("HidClassPDO_HandleQueryInstanceId Buffer %S\n", Irp
->IoStatus
.Information
);
232 //TODO implement instance id
234 // HID\VID_045E&PID_0047\8&1A0700BC&0&0000
235 return STATUS_NOT_IMPLEMENTED
;
239 HidClassPDO_HandleQueryCompatibleId(
240 IN PDEVICE_OBJECT DeviceObject
,
246 // copy current stack location
248 IoCopyCurrentIrpStackLocationToNext(Irp
);
253 Status
= HidClassFDO_DispatchRequestSynchronous(DeviceObject
, Irp
);
254 if (!NT_SUCCESS(Status
))
263 // FIXME: implement me
265 return STATUS_NOT_IMPLEMENTED
;
271 IN PDEVICE_OBJECT DeviceObject
,
274 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
275 PIO_STACK_LOCATION IoStack
;
277 PPNP_BUS_INFORMATION BusInformation
;
278 PDEVICE_RELATIONS DeviceRelation
;
281 // get device extension
283 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
284 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
287 // get current irp stack location
289 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
294 switch(IoStack
->MinorFunction
)
296 case IRP_MN_QUERY_ID
:
298 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
301 // handle query device id
303 Status
= HidClassPDO_HandleQueryDeviceId(DeviceObject
, Irp
);
306 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
309 // handle instance id
311 Status
= HidClassPDO_HandleQueryHardwareId(DeviceObject
, Irp
);
314 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
317 // handle instance id
319 Status
= HidClassPDO_HandleQueryInstanceId(DeviceObject
, Irp
);
322 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryCompatibleIDs
)
325 // handle instance id
327 Status
= HidClassPDO_HandleQueryCompatibleId(DeviceObject
, Irp
);
331 DPRINT1("[HIDCLASS]: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack
->Parameters
.QueryId
.IdType
);
332 Status
= STATUS_NOT_SUPPORTED
;
333 Irp
->IoStatus
.Information
= 0;
336 case IRP_MN_QUERY_CAPABILITIES
:
338 if (IoStack
->Parameters
.DeviceCapabilities
.Capabilities
== NULL
)
343 Status
= STATUS_DEVICE_CONFIGURATION_ERROR
;
349 RtlCopyMemory(IoStack
->Parameters
.DeviceCapabilities
.Capabilities
, &PDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
350 Status
= STATUS_SUCCESS
;
353 case IRP_MN_QUERY_BUS_INFORMATION
:
358 BusInformation
= (PPNP_BUS_INFORMATION
)ExAllocatePool(NonPagedPool
, sizeof(PNP_BUS_INFORMATION
));
363 RtlCopyMemory(&BusInformation
->BusTypeGuid
, &GUID_BUS_TYPE_HID
, sizeof(GUID
));
364 BusInformation
->LegacyBusType
= PNPBus
;
365 BusInformation
->BusNumber
= 0; //FIXME
370 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
371 Status
= STATUS_SUCCESS
;
374 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
377 // FIXME set flags when driver fails / disabled
379 Status
= STATUS_SUCCESS
;
382 case IRP_MN_QUERY_DEVICE_RELATIONS
:
385 // only target relations are supported
387 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
392 Status
= Irp
->IoStatus
.Status
;
397 // allocate device relations
399 DeviceRelation
= (PDEVICE_RELATIONS
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_RELATIONS
));
405 Status
= STATUS_INSUFFICIENT_RESOURCES
;
410 // init device relation
412 DeviceRelation
->Count
= 1;
413 DeviceRelation
->Objects
[0] = DeviceObject
;
414 ObReferenceObject(DeviceRelation
->Objects
[0]);
419 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
420 Status
= STATUS_SUCCESS
;
423 case IRP_MN_START_DEVICE
:
425 DPRINT1("[HIDCLASS] PDO PnP not implemented %x\n", IoStack
->MinorFunction
);
431 Status
= Irp
->IoStatus
.Status
;
434 case IRP_MN_REMOVE_DEVICE
:
436 DPRINT1("[HIDCLASS] PDO IRP_MN_REMOVE_DEVICE not implemented\n");
442 Status
= Irp
->IoStatus
.Status
;
445 case IRP_MN_QUERY_INTERFACE
:
447 DPRINT1("[HIDCLASS] PDO IRP_MN_QUERY_INTERFACE not implemented\n");
453 Status
= Irp
->IoStatus
.Status
;
461 Status
= Irp
->IoStatus
.Status
;
469 if (Status
!= STATUS_PENDING
)
474 Irp
->IoStatus
.Status
= Status
;
479 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
489 HidClassPDO_CreatePDO(
490 IN PDEVICE_OBJECT DeviceObject
)
492 PHIDCLASS_FDO_EXTENSION FDODeviceExtension
;
494 PDEVICE_OBJECT PDODeviceObject
;
495 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
498 // get device extension
500 FDODeviceExtension
= (PHIDCLASS_FDO_EXTENSION
)DeviceObject
->DeviceExtension
;
501 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
504 // lets create the device object
506 Status
= IoCreateDevice(FDODeviceExtension
->Common
.DriverExtension
->DriverObject
, sizeof(HIDCLASS_PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_UNKNOWN
, FILE_AUTOGENERATED_DEVICE_NAME
, FALSE
, &PDODeviceObject
);
507 if (!NT_SUCCESS(Status
))
510 // failed to create device
512 DPRINT1("[HIDCLASS] Failed to create device %x\n", Status
);
519 PDODeviceObject
->StackSize
= DeviceObject
->StackSize
+ 1;
522 // get device extension
524 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
527 // init device extension
529 PDODeviceExtension
->Common
.HidDeviceExtension
.MiniDeviceExtension
= FDODeviceExtension
->Common
.HidDeviceExtension
.MiniDeviceExtension
;
530 PDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
= FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
;
531 PDODeviceExtension
->Common
.HidDeviceExtension
.PhysicalDeviceObject
= NULL
;
532 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
533 PDODeviceExtension
->Common
.DriverExtension
= FDODeviceExtension
->Common
.DriverExtension
;
534 RtlCopyMemory(&PDODeviceExtension
->Attributes
, &FDODeviceExtension
->Attributes
, sizeof(HID_DEVICE_ATTRIBUTES
));
535 RtlCopyMemory(&PDODeviceExtension
->DeviceDescription
, &FDODeviceExtension
->DeviceDescription
, sizeof(HIDP_DEVICE_DESC
));
536 RtlCopyMemory(&PDODeviceExtension
->Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
539 // FIXME: support composite devices
541 PDODeviceExtension
->CollectionIndex
= 0;
542 ASSERT(PDODeviceExtension
->DeviceDescription
.CollectionDescLength
== 1);
545 // store in device relations struct
547 FDODeviceExtension
->DeviceRelations
.Count
= 1;
548 FDODeviceExtension
->DeviceRelations
.Objects
[0] = PDODeviceObject
;
553 PDODeviceObject
->Flags
|= DO_MAP_IO_BUFFER
;
556 // device is initialized
558 PDODeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
560 ObReferenceObject(PDODeviceObject
);
565 return STATUS_SUCCESS
;