2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: USB hub driver
4 * FILE: drivers/usb/cromwell/hub/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
19 IN ULONG IoControlCode
,
27 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode
))
30 *BufferIn
= *BufferOut
= Irp
->AssociatedIrp
.SystemBuffer
;
32 case METHOD_IN_DIRECT
:
33 case METHOD_OUT_DIRECT
:
34 *BufferIn
= Irp
->AssociatedIrp
.SystemBuffer
;
35 *BufferOut
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
38 *BufferIn
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.Type3InputBuffer
;
39 *BufferOut
= Irp
->UserBuffer
;
42 /* Should never happen */
50 UsbhubFdoQueryBusRelations(
51 IN PDEVICE_OBJECT DeviceObject
,
52 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
54 PHUB_DEVICE_EXTENSION DeviceExtension
;
55 PDEVICE_RELATIONS DeviceRelations
;
57 PHUB_DEVICE_EXTENSION PdoExtension
;
58 struct usb_device
* dev
;
65 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
66 dev
= DeviceExtension
->dev
;
68 /* Create PDOs that are missing */
69 for (i
= 0; i
< dev
->maxchild
; i
++)
71 if (dev
->children
[i
] == NULL
)
73 /* No child device at this place */
77 if (DeviceExtension
->Children
[i
] != NULL
)
79 /* PDO already exists */
82 /* Need to create the PDO */
83 Status
= IoCreateDevice(
84 DeviceObject
->DriverObject
,
85 sizeof(HUB_DEVICE_EXTENSION
),
86 NULL
, /* Device name */
87 FILE_DEVICE_CONTROLLER
,
88 FILE_AUTOGENERATED_DEVICE_NAME
,
90 &DeviceExtension
->Children
[i
]);
91 if (!NT_SUCCESS(Status
))
93 DPRINT("Usbhub: IoCreateDevice() failed with status 0x%08lx\n", Status
);
97 Pdo
= DeviceExtension
->Children
[i
];
98 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
100 PdoExtension
= Pdo
->DeviceExtension
;
101 RtlZeroMemory(PdoExtension
, sizeof(HUB_DEVICE_EXTENSION
));
103 PdoExtension
->IsFDO
= FALSE
;
104 PdoExtension
->dev
= dev
->children
[i
];
106 sprintf(Buffer
[0], "%lu", i
);
107 Status
= UsbhubInitMultiSzString(
108 &PdoExtension
->InstanceId
,
110 if (!NT_SUCCESS(Status
))
113 DPRINT1("child #%lu: USB\\Vid_%04x&Pid_%04x&Rev_%04x\n",
115 PdoExtension
->dev
->descriptor
.idVendor
,
116 PdoExtension
->dev
->descriptor
.idProduct
,
117 PdoExtension
->dev
->descriptor
.bcdDevice
);
118 sprintf(Buffer
[0], "USB\\Vid_%04x&Pid_%04x&Rev_%04x",
119 PdoExtension
->dev
->descriptor
.idVendor
,
120 PdoExtension
->dev
->descriptor
.idProduct
,
121 PdoExtension
->dev
->descriptor
.bcdDevice
);
122 sprintf(Buffer
[1], "USB\\Vid_%04x&Pid_%04x",
123 PdoExtension
->dev
->descriptor
.idVendor
,
124 PdoExtension
->dev
->descriptor
.idProduct
);
125 Status
= UsbhubInitMultiSzString(
126 &PdoExtension
->HardwareIds
,
127 Buffer
[0], Buffer
[1], NULL
);
128 if (!NT_SUCCESS(Status
))
131 Status
= UsbhubInitMultiSzString(
132 &PdoExtension
->DeviceId
,
134 if (!NT_SUCCESS(Status
))
137 if (PdoExtension
->dev
->actconfig
->desc
.bNumInterfaces
== 1)
139 /* Single-interface USB device */
140 if (PdoExtension
->dev
->descriptor
.bDeviceClass
!= 0)
142 /* Use these values for device class/sub class/protocol */
143 sprintf(Buffer
[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
144 PdoExtension
->dev
->descriptor
.bDeviceClass
,
145 PdoExtension
->dev
->descriptor
.bDeviceSubClass
,
146 PdoExtension
->dev
->descriptor
.bDeviceProtocol
);
147 sprintf(Buffer
[1], "USB\\Class_%02x&SubClass_%02x",
148 PdoExtension
->dev
->descriptor
.bDeviceClass
,
149 PdoExtension
->dev
->descriptor
.bDeviceSubClass
);
150 sprintf(Buffer
[2], "USB\\Class_%02x",
151 PdoExtension
->dev
->descriptor
.bDeviceClass
);
155 /* Use values specified in the interface descriptor */
156 struct usb_host_interface
*itf
= PdoExtension
->dev
->actconfig
->interface
->altsetting
;
157 sprintf(Buffer
[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
158 itf
->desc
.bInterfaceClass
,
159 itf
->desc
.bInterfaceSubClass
,
160 itf
->desc
.bInterfaceProtocol
);
161 sprintf(Buffer
[1], "USB\\Class_%02x&SubClass_%02x",
162 itf
->desc
.bInterfaceClass
,
163 itf
->desc
.bInterfaceSubClass
);
164 sprintf(Buffer
[2], "USB\\Class_%02x",
165 itf
->desc
.bInterfaceClass
);
167 Status
= UsbhubInitMultiSzString(
168 &PdoExtension
->CompatibleIds
,
169 Buffer
[0], Buffer
[1], Buffer
[2], NULL
);
173 /* Multiple-interface USB device */
174 sprintf(Buffer
[0], "USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
175 PdoExtension
->dev
->descriptor
.bDeviceClass
,
176 PdoExtension
->dev
->descriptor
.bDeviceSubClass
,
177 PdoExtension
->dev
->descriptor
.bDeviceProtocol
);
178 sprintf(Buffer
[1], "USB\\DevClass_%02x&SubClass_%02x",
179 PdoExtension
->dev
->descriptor
.bDeviceClass
,
180 PdoExtension
->dev
->descriptor
.bDeviceSubClass
);
181 sprintf(Buffer
[2], "USB\\DevClass_%02x",
182 PdoExtension
->dev
->descriptor
.bDeviceClass
);
183 Status
= UsbhubInitMultiSzString(
184 &PdoExtension
->CompatibleIds
,
185 Buffer
[0], Buffer
[1], Buffer
[2], "USB\\COMPOSITE", NULL
);
188 if (!NT_SUCCESS(Status
))
191 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
194 /* Fill returned structure */
195 NeededSize
= sizeof(DEVICE_RELATIONS
);
197 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
198 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
201 if (!DeviceRelations
)
202 return STATUS_INSUFFICIENT_RESOURCES
;
203 DeviceRelations
->Count
= Children
;
205 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
207 if (DeviceExtension
->Children
[i
])
209 ObReferenceObject(DeviceExtension
->Children
[i
]);
210 DeviceRelations
->Objects
[Children
++] = DeviceExtension
->Children
[i
];
213 ASSERT(Children
== DeviceRelations
->Count
);
215 *pDeviceRelations
= DeviceRelations
;
216 return STATUS_SUCCESS
;
219 RtlFreeUnicodeString(&PdoExtension
->DeviceId
);
220 RtlFreeUnicodeString(&PdoExtension
->InstanceId
);
221 RtlFreeUnicodeString(&PdoExtension
->HardwareIds
);
222 RtlFreeUnicodeString(&PdoExtension
->CompatibleIds
);
229 IN PDEVICE_OBJECT DeviceObject
,
232 PIO_STACK_LOCATION IrpSp
;
235 ULONG_PTR Information
= 0;
237 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
238 MinorFunction
= IrpSp
->MinorFunction
;
240 switch (MinorFunction
)
242 case IRP_MN_START_DEVICE
: /* 0x0 */
244 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
245 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
249 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x7 */
251 switch (IrpSp
->Parameters
.QueryDeviceRelations
.Type
)
255 PDEVICE_RELATIONS DeviceRelations
= NULL
;
256 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
257 Status
= UsbhubFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
258 Information
= (ULONG_PTR
)DeviceRelations
;
261 case RemovalRelations
:
263 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
264 return ForwardIrpAndForget(DeviceObject
, Irp
);
267 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
268 IrpSp
->Parameters
.QueryDeviceRelations
.Type
);
269 return ForwardIrpAndForget(DeviceObject
, Irp
);
276 DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
277 return ForwardIrpAndForget(DeviceObject
, Irp
);
280 Irp
->IoStatus
.Information
= Information
;
281 Irp
->IoStatus
.Status
= Status
;
282 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
287 UsbhubDeviceControlFdo(
288 IN PDEVICE_OBJECT DeviceObject
,
291 PIO_STACK_LOCATION Stack
;
293 PHUB_DEVICE_EXTENSION DeviceExtension
;
294 ULONG LengthIn
, LengthOut
;
295 ULONG_PTR Information
= 0;
296 PVOID BufferIn
, BufferOut
;
299 Stack
= IoGetCurrentIrpStackLocation(Irp
);
300 LengthIn
= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
301 LengthOut
= Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
302 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
303 IoControlCode
= Stack
->Parameters
.DeviceIoControl
.IoControlCode
;
304 UsbhubGetUserBuffers(Irp
, IoControlCode
, &BufferIn
, &BufferOut
);
306 switch (IoControlCode
)
308 case IOCTL_USB_GET_NODE_INFORMATION
:
310 PUSB_NODE_INFORMATION NodeInformation
;
311 struct usb_device
* dev
;
312 DPRINT("Usbhub: IOCTL_USB_GET_NODE_INFORMATION\n");
313 if (LengthOut
< sizeof(USB_NODE_INFORMATION
))
314 Status
= STATUS_BUFFER_TOO_SMALL
;
315 else if (BufferOut
== NULL
)
316 Status
= STATUS_INVALID_PARAMETER
;
319 NodeInformation
= (PUSB_NODE_INFORMATION
)BufferOut
;
320 dev
= ((PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->dev
;
321 NodeInformation
->NodeType
= UsbHub
;
323 &NodeInformation
->u
.HubInformation
.HubDescriptor
,
324 ((struct usb_hub
*)usb_get_intfdata(to_usb_interface(&dev
->actconfig
->interface
[0].dev
)))->descriptor
,
325 sizeof(USB_HUB_DESCRIPTOR
));
326 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= dev
->actconfig
->desc
.bmAttributes
& 0x80;
327 Information
= sizeof(USB_NODE_INFORMATION
);
328 Status
= STATUS_SUCCESS
;
332 case IOCTL_USB_GET_NODE_CONNECTION_NAME
:
334 PHUB_DEVICE_EXTENSION DeviceExtension
;
335 PUSB_NODE_CONNECTION_NAME ConnectionName
;
336 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
337 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)BufferOut
;
339 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
340 if (LengthOut
< sizeof(USB_NODE_CONNECTION_NAME
))
341 Status
= STATUS_BUFFER_TOO_SMALL
;
342 else if (BufferOut
== NULL
)
343 Status
= STATUS_INVALID_PARAMETER
;
344 else if (ConnectionName
->ConnectionIndex
< 1
345 || ConnectionName
->ConnectionIndex
> USB_MAXCHILDREN
)
346 Status
= STATUS_INVALID_PARAMETER
;
347 else if (DeviceExtension
->Children
[ConnectionName
->ConnectionIndex
- 1] == NULL
)
348 Status
= STATUS_INVALID_PARAMETER
;
351 ULONG NeededStructureSize
;
352 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceExtension
->Children
[ConnectionName
->ConnectionIndex
- 1]->DeviceExtension
;
353 NeededStructureSize
= DeviceExtension
->SymbolicLinkName
.Length
+ sizeof(UNICODE_NULL
) + FIELD_OFFSET(USB_NODE_CONNECTION_NAME
, NodeName
);
354 if (ConnectionName
->ActualLength
< NeededStructureSize
/ sizeof(WCHAR
)
355 || LengthOut
< NeededStructureSize
)
357 /* Buffer too small */
358 ConnectionName
->ActualLength
= NeededStructureSize
/ sizeof(WCHAR
);
359 Information
= sizeof(USB_NODE_CONNECTION_NAME
);
360 Status
= STATUS_BUFFER_TOO_SMALL
;
365 ConnectionName
->NodeName
,
366 DeviceExtension
->SymbolicLinkName
.Buffer
,
367 DeviceExtension
->SymbolicLinkName
.Length
);
368 ConnectionName
->NodeName
[DeviceExtension
->SymbolicLinkName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
369 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME returns '%S'\n", ConnectionName
->NodeName
);
370 ConnectionName
->ActualLength
= NeededStructureSize
/ sizeof(WCHAR
);
371 Information
= NeededStructureSize
;
372 Status
= STATUS_SUCCESS
;
374 Information
= LengthOut
;
378 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
:
380 PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation
;
382 struct usb_device
* dev
;
383 ULONG NumberOfOpenPipes
= 0;
384 ULONG SizeOfOpenPipesArray
;
385 ConnectionInformation
= (PUSB_NODE_CONNECTION_INFORMATION
)BufferOut
;
387 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
388 if (LengthOut
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
389 Status
= STATUS_BUFFER_TOO_SMALL
;
390 else if (BufferOut
== NULL
)
391 Status
= STATUS_INVALID_PARAMETER
;
392 else if (ConnectionInformation
->ConnectionIndex
< 1
393 || ConnectionInformation
->ConnectionIndex
> USB_MAXCHILDREN
)
394 Status
= STATUS_INVALID_PARAMETER
;
397 dev
= ((PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->dev
;
398 dev
= dev
->children
[ConnectionInformation
->ConnectionIndex
- 1];
401 /* No device connected to this port */
403 &ConnectionInformation
->DeviceDescriptor
,
404 sizeof(USB_NODE_CONNECTION_INFORMATION
) - FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION
, DeviceDescriptor
));
405 ConnectionInformation
->ConnectionStatus
= NoDeviceConnected
;
406 Information
= sizeof(USB_NODE_CONNECTION_INFORMATION
);
407 Status
= STATUS_SUCCESS
;
410 SizeOfOpenPipesArray
= (LengthOut
- FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION
, PipeList
)) / sizeof(USB_PIPE_INFO
);
412 &ConnectionInformation
->DeviceDescriptor
,
414 sizeof(USB_DEVICE_DESCRIPTOR
));
415 ConnectionInformation
->CurrentConfigurationValue
= dev
->actconfig
->desc
.bConfigurationValue
;
416 ConnectionInformation
->LowSpeed
= dev
->speed
== USB_SPEED_LOW
|| dev
->speed
== USB_SPEED_FULL
;
417 ConnectionInformation
->DeviceIsHub
= dev
->descriptor
.bDeviceClass
== USB_CLASS_HUB
;
418 ConnectionInformation
->DeviceAddress
= dev
->devnum
;
419 ConnectionInformation
->ConnectionStatus
= DeviceConnected
;
421 for (i
= 0; i
< dev
->actconfig
->desc
.bNumInterfaces
; i
++)
422 for (j
= 0; j
< dev
->actconfig
->interface
[i
].num_altsetting
; j
++)
423 for (k
= 0; k
< dev
->actconfig
->interface
[i
].altsetting
[j
].desc
.bNumEndpoints
; k
++)
425 if (NumberOfOpenPipes
< SizeOfOpenPipesArray
)
427 PUSB_PIPE_INFO Pipe
= &ConnectionInformation
->PipeList
[NumberOfOpenPipes
];
428 struct usb_host_endpoint
* endpoint
= &dev
->actconfig
->interface
[i
].altsetting
[j
].endpoint
[k
];
430 &Pipe
->EndpointDescriptor
,
432 endpoint
->desc
.bLength
);
433 Pipe
->ScheduleOffset
= 0; /* FIXME */
437 ConnectionInformation
->NumberOfOpenPipes
= NumberOfOpenPipes
;
439 Information
= sizeof(USB_NODE_CONNECTION_INFORMATION
);
440 if (NumberOfOpenPipes
<= SizeOfOpenPipesArray
)
441 Status
= STATUS_SUCCESS
;
443 Status
= STATUS_BUFFER_OVERFLOW
;
447 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
:
449 //PUSB_DESCRIPTOR_REQUEST Descriptor;
450 DPRINT("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
451 DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION unimplemented\n");
453 Status
= STATUS_NOT_IMPLEMENTED
;
456 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
:
458 PHUB_DEVICE_EXTENSION DeviceExtension
;
459 PUSB_NODE_CONNECTION_DRIVERKEY_NAME StringDescriptor
;
460 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
461 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
462 StringDescriptor
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)BufferOut
;
463 if (LengthOut
< sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
))
464 Status
= STATUS_BUFFER_TOO_SMALL
;
465 else if (StringDescriptor
== NULL
)
466 Status
= STATUS_INVALID_PARAMETER
;
467 else if (StringDescriptor
->ConnectionIndex
< 1
468 || StringDescriptor
->ConnectionIndex
> USB_MAXCHILDREN
)
469 Status
= STATUS_INVALID_PARAMETER
;
470 else if (DeviceExtension
->Children
[StringDescriptor
->ConnectionIndex
- 1] == NULL
)
471 Status
= STATUS_INVALID_PARAMETER
;
475 Status
= IoGetDeviceProperty(
476 DeviceExtension
->Children
[StringDescriptor
->ConnectionIndex
- 1],
477 DevicePropertyDriverKeyName
,
478 LengthOut
- FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME
, DriverKeyName
),
479 StringDescriptor
->DriverKeyName
,
481 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
483 StringDescriptor
->ActualLength
= StringSize
+ FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME
, DriverKeyName
);
484 Information
= LengthOut
;
485 Status
= STATUS_SUCCESS
;
492 /* Pass Irp to lower driver */
493 DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
494 return ForwardIrpAndForget(DeviceObject
, Irp
);
498 Irp
->IoStatus
.Information
= Information
;
499 Irp
->IoStatus
.Status
= Status
;
500 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);