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
< USB_MAXCHILDREN
; 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
+ 1);
107 Status
= UsbhubInitMultiSzString(
108 &PdoExtension
->InstanceId
,
110 if (!NT_SUCCESS(Status
))
114 sprintf(Buffer
[0], "USB\\Vid_%04x&Pid_%04x&Rev_%04x",
115 PdoExtension
->dev
->descriptor
.idVendor
,
116 PdoExtension
->dev
->descriptor
.idProduct
,
117 PdoExtension
->dev
->descriptor
.bcdDevice
);
118 sprintf(Buffer
[1], "USB\\Vid_%04x&Pid_%04x",
119 PdoExtension
->dev
->descriptor
.idVendor
,
120 PdoExtension
->dev
->descriptor
.idProduct
);
121 Status
= UsbhubInitMultiSzString(
122 &PdoExtension
->HardwareIds
,
123 Buffer
[0], Buffer
[1], NULL
);
124 if (!NT_SUCCESS(Status
))
127 Status
= UsbhubInitMultiSzString(
128 &PdoExtension
->DeviceId
,
130 if (!NT_SUCCESS(Status
))
133 if (PdoExtension
->dev
->actconfig
->desc
.bNumInterfaces
== 1)
135 /* Single-interface USB device */
136 sprintf(Buffer
[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
137 PdoExtension
->dev
->descriptor
.bDeviceClass
,
138 PdoExtension
->dev
->descriptor
.bDeviceSubClass
,
139 PdoExtension
->dev
->descriptor
.bDeviceProtocol
);
140 sprintf(Buffer
[1], "USB\\Class_%02x&SubClass_%02x",
141 PdoExtension
->dev
->descriptor
.bDeviceClass
,
142 PdoExtension
->dev
->descriptor
.bDeviceSubClass
);
143 sprintf(Buffer
[2], "USB\\Class_%02x",
144 PdoExtension
->dev
->descriptor
.bDeviceClass
);
145 Status
= UsbhubInitMultiSzString(
146 &PdoExtension
->CompatibleIds
,
147 Buffer
[0], Buffer
[1], Buffer
[2], NULL
);
151 /* Multiple-interface USB device */
152 sprintf(Buffer
[0], "USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
153 PdoExtension
->dev
->descriptor
.bDeviceClass
,
154 PdoExtension
->dev
->descriptor
.bDeviceSubClass
,
155 PdoExtension
->dev
->descriptor
.bDeviceProtocol
);
156 sprintf(Buffer
[1], "USB\\DevClass_%02x&SubClass_%02x",
157 PdoExtension
->dev
->descriptor
.bDeviceClass
,
158 PdoExtension
->dev
->descriptor
.bDeviceSubClass
);
159 sprintf(Buffer
[2], "USB\\DevClass_%02x",
160 PdoExtension
->dev
->descriptor
.bDeviceClass
);
161 Status
= UsbhubInitMultiSzString(
162 &PdoExtension
->CompatibleIds
,
163 Buffer
[0], Buffer
[1], Buffer
[2], "USB\\COMPOSITE", NULL
);
166 if (!NT_SUCCESS(Status
))
169 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
172 /* Fill returned structure */
173 NeededSize
= sizeof(DEVICE_RELATIONS
);
175 NeededSize
+= (Children
- 1) * sizeof(PDEVICE_OBJECT
);
176 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
179 if (!DeviceRelations
)
180 return STATUS_INSUFFICIENT_RESOURCES
;
181 DeviceRelations
->Count
= Children
;
183 for (i
= 0; i
< USB_MAXCHILDREN
; i
++)
185 if (DeviceExtension
->Children
[i
])
187 ObReferenceObject(DeviceExtension
->Children
[i
]);
188 DeviceRelations
->Objects
[Children
++] = DeviceExtension
->Children
[i
];
191 ASSERT(Children
== DeviceRelations
->Count
);
193 *pDeviceRelations
= DeviceRelations
;
194 return STATUS_SUCCESS
;
197 RtlFreeUnicodeString(&PdoExtension
->DeviceId
);
198 RtlFreeUnicodeString(&PdoExtension
->InstanceId
);
199 RtlFreeUnicodeString(&PdoExtension
->HardwareIds
);
200 RtlFreeUnicodeString(&PdoExtension
->CompatibleIds
);
207 IN PDEVICE_OBJECT DeviceObject
,
210 PIO_STACK_LOCATION IrpSp
;
213 ULONG_PTR Information
= 0;
215 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
216 MinorFunction
= IrpSp
->MinorFunction
;
218 switch (MinorFunction
)
220 case IRP_MN_START_DEVICE
: /* 0x0 */
222 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
223 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
227 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x7 */
229 switch (IrpSp
->Parameters
.QueryDeviceRelations
.Type
)
233 PDEVICE_RELATIONS DeviceRelations
;
234 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
235 Status
= UsbhubFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
236 Information
= (ULONG_PTR
)DeviceRelations
;
239 case RemovalRelations
:
241 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
242 return ForwardIrpAndForget(DeviceObject
, Irp
);
245 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
246 IrpSp
->Parameters
.QueryDeviceRelations
.Type
);
247 return ForwardIrpAndForget(DeviceObject
, Irp
);
254 DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
255 return ForwardIrpAndForget(DeviceObject
, Irp
);
258 Irp
->IoStatus
.Information
= Information
;
259 Irp
->IoStatus
.Status
= Status
;
260 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
265 UsbhubDeviceControlFdo(
266 IN PDEVICE_OBJECT DeviceObject
,
269 PIO_STACK_LOCATION Stack
;
271 PHUB_DEVICE_EXTENSION DeviceExtension
;
272 ULONG LengthIn
, LengthOut
;
273 ULONG_PTR Information
= 0;
274 PVOID BufferIn
, BufferOut
;
277 Stack
= IoGetCurrentIrpStackLocation(Irp
);
278 LengthIn
= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
279 LengthOut
= Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
280 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
281 IoControlCode
= Stack
->Parameters
.DeviceIoControl
.IoControlCode
;
282 UsbhubGetUserBuffers(Irp
, IoControlCode
, &BufferIn
, &BufferOut
);
284 switch (IoControlCode
)
286 case IOCTL_USB_GET_NODE_INFORMATION
:
288 PUSB_NODE_INFORMATION NodeInformation
;
289 struct usb_device
* dev
;
290 DPRINT("Usbhub: IOCTL_USB_GET_NODE_INFORMATION\n");
291 if (LengthOut
< sizeof(USB_NODE_INFORMATION
))
292 Status
= STATUS_BUFFER_TOO_SMALL
;
293 else if (BufferOut
== NULL
)
294 Status
= STATUS_INVALID_PARAMETER
;
297 NodeInformation
= (PUSB_NODE_INFORMATION
)BufferOut
;
298 dev
= ((PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->dev
;
299 NodeInformation
->NodeType
= UsbHub
;
301 &NodeInformation
->u
.HubInformation
.HubDescriptor
,
302 ((struct usb_hub
*)usb_get_intfdata(to_usb_interface(&dev
->actconfig
->interface
[0].dev
)))->descriptor
,
303 sizeof(USB_HUB_DESCRIPTOR
));
304 NodeInformation
->u
.HubInformation
.HubIsBusPowered
= dev
->actconfig
->desc
.bmAttributes
& 0x80;
305 Information
= sizeof(USB_NODE_INFORMATION
);
306 Status
= STATUS_SUCCESS
;
310 case IOCTL_USB_GET_NODE_CONNECTION_NAME
:
312 PHUB_DEVICE_EXTENSION DeviceExtension
;
313 PUSB_NODE_CONNECTION_NAME ConnectionName
;
314 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
315 ConnectionName
= (PUSB_NODE_CONNECTION_NAME
)BufferOut
;
317 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
318 if (LengthOut
< sizeof(USB_NODE_CONNECTION_NAME
))
319 Status
= STATUS_BUFFER_TOO_SMALL
;
320 else if (BufferOut
== NULL
)
321 Status
= STATUS_INVALID_PARAMETER
;
322 else if (ConnectionName
->ConnectionIndex
< 1
323 || ConnectionName
->ConnectionIndex
> USB_MAXCHILDREN
)
324 Status
= STATUS_INVALID_PARAMETER
;
325 else if (DeviceExtension
->Children
[ConnectionName
->ConnectionIndex
- 1] == NULL
)
326 Status
= STATUS_INVALID_PARAMETER
;
329 ULONG NeededStructureSize
;
330 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceExtension
->Children
[ConnectionName
->ConnectionIndex
- 1]->DeviceExtension
;
331 NeededStructureSize
= DeviceExtension
->SymbolicLinkName
.Length
+ sizeof(UNICODE_NULL
) + FIELD_OFFSET(USB_NODE_CONNECTION_NAME
, NodeName
);
332 if (ConnectionName
->ActualLength
< NeededStructureSize
/ sizeof(WCHAR
)
333 || LengthOut
< NeededStructureSize
)
335 /* Buffer too small */
336 ConnectionName
->ActualLength
= NeededStructureSize
/ sizeof(WCHAR
);
337 Information
= sizeof(USB_NODE_CONNECTION_NAME
);
338 Status
= STATUS_BUFFER_TOO_SMALL
;
343 ConnectionName
->NodeName
,
344 DeviceExtension
->SymbolicLinkName
.Buffer
,
345 DeviceExtension
->SymbolicLinkName
.Length
);
346 ConnectionName
->NodeName
[DeviceExtension
->SymbolicLinkName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
347 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME returns '%S'\n", ConnectionName
->NodeName
);
348 ConnectionName
->ActualLength
= NeededStructureSize
/ sizeof(WCHAR
);
349 Information
= NeededStructureSize
;
350 Status
= STATUS_SUCCESS
;
352 Information
= LengthOut
;
356 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
:
358 PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation
;
360 struct usb_device
* dev
;
361 ULONG NumberOfOpenPipes
= 0;
362 ULONG SizeOfOpenPipesArray
;
363 ConnectionInformation
= (PUSB_NODE_CONNECTION_INFORMATION
)BufferOut
;
365 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
366 if (LengthOut
< sizeof(USB_NODE_CONNECTION_INFORMATION
))
367 Status
= STATUS_BUFFER_TOO_SMALL
;
368 else if (BufferOut
== NULL
)
369 Status
= STATUS_INVALID_PARAMETER
;
370 else if (ConnectionInformation
->ConnectionIndex
< 1
371 || ConnectionInformation
->ConnectionIndex
> USB_MAXCHILDREN
)
372 Status
= STATUS_INVALID_PARAMETER
;
375 dev
= ((PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->dev
;
376 dev
= dev
->children
[ConnectionInformation
->ConnectionIndex
- 1];
379 /* No device connected to this port */
381 &ConnectionInformation
->DeviceDescriptor
,
382 sizeof(USB_NODE_CONNECTION_INFORMATION
) - FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION
, DeviceDescriptor
));
383 ConnectionInformation
->ConnectionStatus
= NoDeviceConnected
;
384 Information
= sizeof(USB_NODE_CONNECTION_INFORMATION
);
385 Status
= STATUS_SUCCESS
;
388 SizeOfOpenPipesArray
= (LengthOut
- FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION
, PipeList
)) / sizeof(USB_PIPE_INFO
);
390 &ConnectionInformation
->DeviceDescriptor
,
392 sizeof(USB_DEVICE_DESCRIPTOR
));
393 ConnectionInformation
->CurrentConfigurationValue
= dev
->actconfig
->desc
.bConfigurationValue
;
394 ConnectionInformation
->LowSpeed
= dev
->speed
== USB_SPEED_LOW
|| dev
->speed
== USB_SPEED_FULL
;
395 ConnectionInformation
->DeviceIsHub
= dev
->descriptor
.bDeviceClass
== USB_CLASS_HUB
;
396 ConnectionInformation
->DeviceAddress
= dev
->devnum
;
397 ConnectionInformation
->ConnectionStatus
= DeviceConnected
;
399 for (i
= 0; i
< dev
->actconfig
->desc
.bNumInterfaces
; i
++)
400 for (j
= 0; j
< dev
->actconfig
->interface
[i
].num_altsetting
; j
++)
401 for (k
= 0; k
< dev
->actconfig
->interface
[i
].altsetting
[j
].desc
.bNumEndpoints
; k
++)
403 if (NumberOfOpenPipes
< SizeOfOpenPipesArray
)
405 PUSB_PIPE_INFO Pipe
= &ConnectionInformation
->PipeList
[NumberOfOpenPipes
];
406 struct usb_host_endpoint
* endpoint
= &dev
->actconfig
->interface
[i
].altsetting
[j
].endpoint
[k
];
408 &Pipe
->EndpointDescriptor
,
410 endpoint
->desc
.bLength
);
411 Pipe
->ScheduleOffset
= 0; /* FIXME */
415 ConnectionInformation
->NumberOfOpenPipes
= NumberOfOpenPipes
;
417 Information
= sizeof(USB_NODE_CONNECTION_INFORMATION
);
418 if (NumberOfOpenPipes
<= SizeOfOpenPipesArray
)
419 Status
= STATUS_SUCCESS
;
421 Status
= STATUS_BUFFER_OVERFLOW
;
425 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
:
427 //PUSB_DESCRIPTOR_REQUEST Descriptor;
428 DPRINT("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
429 DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION unimplemented\n");
431 Status
= STATUS_NOT_IMPLEMENTED
;
434 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
:
436 PHUB_DEVICE_EXTENSION DeviceExtension
;
437 PUSB_NODE_CONNECTION_DRIVERKEY_NAME StringDescriptor
;
438 DPRINT("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
439 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
440 StringDescriptor
= (PUSB_NODE_CONNECTION_DRIVERKEY_NAME
)BufferOut
;
441 if (LengthOut
< sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME
))
442 Status
= STATUS_BUFFER_TOO_SMALL
;
443 else if (StringDescriptor
== NULL
)
444 Status
= STATUS_INVALID_PARAMETER
;
445 else if (StringDescriptor
->ConnectionIndex
< 1
446 || StringDescriptor
->ConnectionIndex
> USB_MAXCHILDREN
)
447 Status
= STATUS_INVALID_PARAMETER
;
448 else if (DeviceExtension
->Children
[StringDescriptor
->ConnectionIndex
- 1] == NULL
)
449 Status
= STATUS_INVALID_PARAMETER
;
453 Status
= IoGetDeviceProperty(
454 DeviceExtension
->Children
[StringDescriptor
->ConnectionIndex
- 1],
455 DevicePropertyDriverKeyName
,
456 LengthOut
- FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME
, DriverKeyName
),
457 StringDescriptor
->DriverKeyName
,
459 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
461 StringDescriptor
->ActualLength
= StringSize
+ FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME
, DriverKeyName
);
462 Information
= LengthOut
;
463 Status
= STATUS_SUCCESS
;
470 /* Pass Irp to lower driver */
471 DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
472 return ForwardIrpAndForget(DeviceObject
, Irp
);
476 Irp
->IoStatus
.Information
= Information
;
477 Irp
->IoStatus
.Status
= Status
;
478 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);