Sync with trunk head.
[reactos.git] / drivers / usb / usbhub / pdo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: USB hub driver
4 * FILE: drivers/usb/cromwell/hub/pdo.c
5 * PURPOSE: IRP_MJ_PNP operations for PDOs
6 *
7 * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #define NDEBUG
11 #include <stdio.h>
12 #include "usbhub.h"
13
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
15
16 NTSTATUS
17 UsbhubInternalDeviceControlPdo(
18 IN PDEVICE_OBJECT DeviceObject,
19 IN PIRP Irp)
20 {
21 PIO_STACK_LOCATION Stack;
22 ULONG_PTR Information = 0;
23 NTSTATUS Status;
24
25 DPRINT("Usbhub: UsbhubInternalDeviceControlPdo() called\n");
26
27 Stack = IoGetCurrentIrpStackLocation(Irp);
28 Status = Irp->IoStatus.Status;
29
30 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
31 {
32 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
33 {
34 PHUB_DEVICE_EXTENSION DeviceExtension;
35
36 DPRINT("Usbhub: IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
37 if (Irp->AssociatedIrp.SystemBuffer == NULL
38 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
39 {
40 Status = STATUS_INVALID_PARAMETER;
41 }
42 else
43 {
44 PVOID* pHubPointer;
45 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
46
47 pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
48 *pHubPointer = DeviceExtension->dev;
49 Information = sizeof(PVOID);
50 Status = STATUS_SUCCESS;
51 }
52 break;
53 }
54 default:
55 {
56 DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
57 Information = Irp->IoStatus.Information;
58 Status = Irp->IoStatus.Status;
59 }
60 }
61
62 Irp->IoStatus.Information = Information;
63 Irp->IoStatus.Status = Status;
64 IoCompleteRequest(Irp, IO_NO_INCREMENT);
65 return Status;
66 }
67
68 static NTSTATUS
69 UsbhubPdoStartDevice(
70 IN PDEVICE_OBJECT DeviceObject,
71 IN PIRP Irp)
72 {
73 PHUB_DEVICE_EXTENSION DeviceExtension;
74 NTSTATUS Status;
75
76 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
77
78 /* Register and activate device interface */
79 Status = IoRegisterDeviceInterface(
80 DeviceObject,
81 DeviceExtension->dev->descriptor.bDeviceClass == USB_CLASS_HUB ?
82 &GUID_DEVINTERFACE_USB_HUB :
83 &GUID_DEVINTERFACE_USB_DEVICE,
84 NULL, /* Reference string */
85 &DeviceExtension->SymbolicLinkName);
86 if (!NT_SUCCESS(Status))
87 {
88 DPRINT("Usbhub: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
89 return Status;
90 }
91
92 Status = IoSetDeviceInterfaceState(&DeviceExtension->SymbolicLinkName, TRUE);
93 if (!NT_SUCCESS(Status))
94 {
95 DPRINT("Usbhub: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status);
96 return Status;
97 }
98
99 return STATUS_SUCCESS;
100 }
101
102 static NTSTATUS
103 UsbhubPdoQueryId(
104 IN PDEVICE_OBJECT DeviceObject,
105 IN PIRP Irp,
106 OUT ULONG_PTR* Information)
107 {
108 PHUB_DEVICE_EXTENSION DeviceExtension;
109 ULONG IdType;
110 PUNICODE_STRING SourceString;
111 UNICODE_STRING String;
112 NTSTATUS Status;
113
114 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
115 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
116 RtlInitUnicodeString(&String, NULL);
117
118 switch (IdType)
119 {
120 case BusQueryDeviceID:
121 {
122 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
123 SourceString = &DeviceExtension->DeviceId;
124 break;
125 }
126 case BusQueryHardwareIDs:
127 {
128 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
129 SourceString = &DeviceExtension->HardwareIds;
130 break;
131 }
132 case BusQueryCompatibleIDs:
133 {
134 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
135 SourceString = &DeviceExtension->CompatibleIds;
136 break;
137 }
138 case BusQueryInstanceID:
139 {
140 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
141 SourceString = &DeviceExtension->InstanceId;
142 break;
143 }
144 default:
145 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
146 return STATUS_NOT_SUPPORTED;
147 }
148
149 Status = UsbhubDuplicateUnicodeString(
150 &String,
151 SourceString,
152 PagedPool);
153 *Information = (ULONG_PTR)String.Buffer;
154 return Status;
155 }
156
157 static NTSTATUS
158 UsbhubPdoQueryDeviceText(
159 IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp,
161 OUT ULONG_PTR* Information)
162 {
163 PHUB_DEVICE_EXTENSION DeviceExtension;
164 DEVICE_TEXT_TYPE DeviceTextType;
165 LCID LocaleId;
166
167 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
168 LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
169 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
170
171 switch (DeviceTextType)
172 {
173 case DeviceTextDescription:
174 case DeviceTextLocationInformation:
175 {
176 unsigned short size;
177 int ret;
178 PWCHAR buf;
179 PWCHAR bufret;
180
181 if (DeviceTextType == DeviceTextDescription)
182 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
183 else
184 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
185
186 if (!DeviceExtension->dev->descriptor.iProduct)
187 return STATUS_NOT_SUPPORTED;
188
189 ret = usb_get_string(DeviceExtension->dev, LocaleId, DeviceExtension->dev->descriptor.iProduct, &size, sizeof(size));
190 if (ret < 2)
191 {
192 DPRINT("Usbhub: usb_get_string() failed with error %d\n", ret);
193 return STATUS_IO_DEVICE_ERROR;
194 }
195 size &= 0xff;
196 buf = ExAllocatePool(PagedPool, size);
197 if (buf == NULL)
198 {
199 DPRINT("Usbhub: ExAllocatePool() failed\n");
200 return STATUS_INSUFFICIENT_RESOURCES;
201 }
202 ret = usb_get_string(DeviceExtension->dev, LocaleId, DeviceExtension->dev->descriptor.iProduct, buf, size);
203 if (ret < 0)
204 {
205 DPRINT("Usbhub: usb_get_string() failed with error %d\n", ret);
206 ExFreePool(buf);
207 return STATUS_IO_DEVICE_ERROR;
208 }
209 bufret = ExAllocatePool(PagedPool, size - 2 /* size of length identifier */ + 2 /* final NULL */);
210 if (bufret == NULL)
211 {
212 DPRINT("Usbhub: ExAllocatePool() failed\n");
213 ExFreePool(buf);
214 return STATUS_INSUFFICIENT_RESOURCES;
215 }
216
217 RtlCopyMemory(bufret, &buf[1], size - 2);
218 bufret[(size - 1) / sizeof(WCHAR)] = 0;
219 *Information = (ULONG_PTR)bufret;
220 ExFreePool(buf);
221 return STATUS_SUCCESS;
222 }
223 default:
224 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
225 return STATUS_NOT_SUPPORTED;
226 }
227 }
228
229 NTSTATUS NTAPI
230 UsbhubPnpPdo(
231 IN PDEVICE_OBJECT DeviceObject,
232 IN PIRP Irp)
233 {
234 ULONG MinorFunction;
235 PIO_STACK_LOCATION Stack;
236 ULONG_PTR Information = 0;
237 NTSTATUS Status;
238
239 Stack = IoGetCurrentIrpStackLocation(Irp);
240 MinorFunction = Stack->MinorFunction;
241
242 switch (MinorFunction)
243 {
244 case IRP_MN_START_DEVICE: /* 0x0 */
245 {
246 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
247 Status = UsbhubPdoStartDevice(DeviceObject, Irp);
248 break;
249 }
250 case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
251 {
252 PDEVICE_CAPABILITIES DeviceCapabilities;
253 ULONG i;
254 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
255
256 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
257 /* FIXME: capabilities can change with connected device */
258 DeviceCapabilities->LockSupported = TRUE;
259 DeviceCapabilities->EjectSupported = FALSE;
260 DeviceCapabilities->Removable = FALSE;
261 DeviceCapabilities->DockDevice = FALSE;
262 DeviceCapabilities->UniqueID = FALSE;
263 DeviceCapabilities->SilentInstall = TRUE;
264 DeviceCapabilities->RawDeviceOK = FALSE;
265 DeviceCapabilities->SurpriseRemovalOK = FALSE;
266 DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
267 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
268 DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
269 for (i = 0; i < PowerSystemMaximum; i++)
270 DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
271 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
272 DeviceCapabilities->D1Latency = 0; /* FIXME */
273 DeviceCapabilities->D2Latency = 0; /* FIXME */
274 DeviceCapabilities->D3Latency = 0; /* FIXME */
275 Status = STATUS_SUCCESS;
276 break;
277 }
278 case IRP_MN_QUERY_RESOURCES: /* 0x0a */
279 {
280 PCM_RESOURCE_LIST ResourceList;
281
282 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
283 ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
284 if (!ResourceList)
285 {
286 DPRINT("Usbhub: ExAllocatePool() failed\n");
287 Status = STATUS_INSUFFICIENT_RESOURCES;
288 }
289 else
290 {
291 ResourceList->Count = 0;
292 Information = (ULONG_PTR)ResourceList;
293 Status = STATUS_SUCCESS;
294 }
295 break;
296 }
297 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
298 {
299 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
300
301 DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
302 ResourceList = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
303 if (!ResourceList)
304 {
305 DPRINT("Usbhub: ExAllocatePool() failed\n");
306 Status = STATUS_INSUFFICIENT_RESOURCES;
307 }
308 else
309 {
310 RtlZeroMemory(ResourceList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
311 ResourceList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
312 ResourceList->AlternativeLists = 1;
313 ResourceList->List->Version = 1;
314 ResourceList->List->Revision = 1;
315 ResourceList->List->Count = 0;
316 Information = (ULONG_PTR)ResourceList;
317 Status = STATUS_SUCCESS;
318 }
319 break;
320 }
321 case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
322 {
323 Status = UsbhubPdoQueryDeviceText(DeviceObject, Irp, &Information);
324 break;
325 }
326 case IRP_MN_QUERY_ID: /* 0x13 */
327 {
328 Status = UsbhubPdoQueryId(DeviceObject, Irp, &Information);
329 break;
330 }
331 default:
332 {
333 /* We can't forward request to the lower driver, because
334 * we are a Pdo, so we don't have lower driver...
335 */
336 DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
337 Information = Irp->IoStatus.Information;
338 Status = Irp->IoStatus.Status;
339 }
340 }
341
342 Irp->IoStatus.Information = Information;
343 Irp->IoStatus.Status = Status;
344 IoCompleteRequest(Irp, IO_NO_INCREMENT);
345 return Status;
346 }
347