4d7259df3fef5a087a3f6d27c4bf9fe7f19b13ce
[reactos.git] / reactos / drivers / usb / miniport / common / pdo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS USB miniport driver (Cromwell type)
4 * FILE: drivers/usb/miniport/common/pdo.c
5 * PURPOSE: IRP_MJ_PNP/IRP_MJ_DEVICE_CONTROL operations for PDOs
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org),
8 * James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
9 */
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #include "usbcommon.h"
15
16 extern struct usb_driver hub_driver;
17
18 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
19
20 NTSTATUS
21 UsbMpDeviceControlPdo(
22 IN PDEVICE_OBJECT DeviceObject,
23 IN PIRP Irp)
24 {
25 PIO_STACK_LOCATION Stack;
26 ULONG_PTR Information = 0;
27 NTSTATUS Status;
28
29 DPRINT("USBMP: UsbMpDeviceControlPdo() called\n");
30
31 Stack = IoGetCurrentIrpStackLocation(Irp);
32 Status = Irp->IoStatus.Status;
33
34 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
35 {
36 case IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE:
37 {
38 PUSBMP_DEVICE_EXTENSION DeviceExtension;
39
40 DPRINT("USBMP: IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE\n");
41 if (Irp->AssociatedIrp.SystemBuffer == NULL
42 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
43 {
44 Status = STATUS_INVALID_PARAMETER;
45 }
46 else
47 {
48 PVOID* pRootHubPointer;
49 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
50 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceExtension->FunctionalDeviceObject->DeviceExtension;
51
52 pRootHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
53 *pRootHubPointer = (PVOID)DeviceExtension->pdev->bus; /* struct usb_device* */
54 Information = sizeof(PVOID);
55 Status = STATUS_SUCCESS;
56 }
57 break;
58 }
59 default:
60 {
61 DPRINT1("USBMP: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
62 Information = Irp->IoStatus.Information;
63 Status = Irp->IoStatus.Status;
64 }
65 }
66
67 Irp->IoStatus.Information = Information;
68 Irp->IoStatus.Status = Status;
69 IoCompleteRequest(Irp, IO_NO_INCREMENT);
70 return Status;
71 }
72
73 static NTSTATUS
74 UsbMpPdoQueryId(
75 IN PDEVICE_OBJECT DeviceObject,
76 IN PIRP Irp,
77 OUT ULONG_PTR* Information)
78 {
79 PUSBMP_DEVICE_EXTENSION DeviceExtension;
80 ULONG IdType;
81 UNICODE_STRING SourceString;
82 UNICODE_STRING String;
83 NTSTATUS Status;
84
85 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
86 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
87 RtlInitUnicodeString(&String, NULL);
88
89 switch (IdType)
90 {
91 case BusQueryDeviceID:
92 {
93 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
94 RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB");
95 break;
96 }
97 case BusQueryHardwareIDs:
98 {
99 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
100 /* FIXME: Should return
101 USB\ROOT_HUB&VID????&PID????&REV????
102 USB\ROOT_HUB&VID????&PID????
103 USB\ROOT_HUB
104 */
105 UsbMpInitMultiSzString(&SourceString, "USB\\ROOT_HUB", NULL);
106 break;
107 }
108 case BusQueryCompatibleIDs:
109 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
110 /* No compatible ID */
111 *Information = 0;
112 return STATUS_NOT_SUPPORTED;
113 case BusQueryInstanceID:
114 {
115 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
116 RtlInitUnicodeString(&SourceString, L"0000"); /* FIXME */
117 break;
118 }
119 default:
120 DPRINT1("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
121 return STATUS_NOT_SUPPORTED;
122 }
123
124 Status = UsbMpDuplicateUnicodeString(
125 &String,
126 &SourceString,
127 PagedPool);
128 *Information = (ULONG_PTR)String.Buffer;
129 return Status;
130 }
131
132 static NTSTATUS
133 UsbMpPnpStartDevice(
134 IN PDEVICE_OBJECT DeviceObject)
135 {
136 PUSBMP_DEVICE_EXTENSION DeviceExtension;
137 NTSTATUS Status;
138
139 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
140
141 /* Register device interface for root hub */
142 Status = IoRegisterDeviceInterface(
143 DeviceObject,
144 &GUID_DEVINTERFACE_USB_HUB,
145 NULL,
146 &DeviceExtension->HcdInterfaceName);
147 if (!NT_SUCCESS(Status))
148 {
149 DPRINT("USBMP: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
150 return Status;
151 }
152
153 return Status;
154 }
155
156 NTSTATUS STDCALL
157 UsbMpPnpPdo(
158 IN PDEVICE_OBJECT DeviceObject,
159 IN PIRP Irp)
160 {
161 ULONG MinorFunction;
162 PIO_STACK_LOCATION Stack;
163 ULONG_PTR Information = 0;
164 NTSTATUS Status;
165
166 Stack = IoGetCurrentIrpStackLocation(Irp);
167 MinorFunction = Stack->MinorFunction;
168
169 switch (MinorFunction)
170 {
171 case IRP_MN_START_DEVICE: /* 0x00 */
172 {
173 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
174 Status = UsbMpPnpStartDevice(DeviceObject);
175 break;
176 }
177 case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
178 {
179 PDEVICE_CAPABILITIES DeviceCapabilities;
180 ULONG i;
181 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
182
183 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
184 /* FIXME: capabilities can change with connected device */
185 DeviceCapabilities->LockSupported = FALSE;
186 DeviceCapabilities->EjectSupported = FALSE;
187 DeviceCapabilities->Removable = TRUE;
188 DeviceCapabilities->DockDevice = FALSE;
189 DeviceCapabilities->UniqueID = FALSE;
190 DeviceCapabilities->SilentInstall = FALSE;
191 DeviceCapabilities->RawDeviceOK = TRUE;
192 DeviceCapabilities->SurpriseRemovalOK = TRUE;
193 DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
194 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
195 DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
196 for (i = 0; i < PowerSystemMaximum; i++)
197 DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
198 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
199 DeviceCapabilities->D1Latency = 0; /* FIXME */
200 DeviceCapabilities->D2Latency = 0; /* FIXME */
201 DeviceCapabilities->D3Latency = 0; /* FIXME */
202 Status = STATUS_SUCCESS;
203 break;
204 }
205 case IRP_MN_QUERY_RESOURCES: /* 0x0a */
206 {
207 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
208 /* Root buses don't need resources, except the ones of
209 * the usb controller. This PDO is the root bus PDO, so
210 * report no resource by not changing Information and
211 * Status
212 */
213 Information = Irp->IoStatus.Information;
214 Status = Irp->IoStatus.Status;
215 break;
216 }
217 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
218 {
219 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
220 /* Root buses don't need resources, except the ones of
221 * the usb controller. This PDO is the root bus PDO, so
222 * report no resource by not changing Information and
223 * Status
224 */
225 Information = Irp->IoStatus.Information;
226 Status = Irp->IoStatus.Status;
227 break;
228 }
229 #if 0 /* FIXME */
230 case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
231 {
232 switch (Stack->Parameters.QueryDeviceText.DeviceTextType)
233 {
234 case DeviceTextDescription:
235 {
236 ULONG DescriptionSize;
237 PWSTR Description;
238 DPRINT("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
239
240 Status = IoGetDeviceProperty(
241 DeviceObject,
242 DevicePropertyDeviceDescription,
243 0, NULL,
244 &DescriptionSize);
245 if (Status == STATUS_BUFFER_TOO_SMALL)
246 {
247 Description = ExAllocatePool(PagedPool, DescriptionSize);
248 if (!Description)
249 Status = STATUS_INSUFFICIENT_RESOURCES;
250 else
251 {
252 Status = IoGetDeviceProperty(
253 DeviceObject,
254 DevicePropertyDeviceDescription,
255 DescriptionSize, Description,
256 &DescriptionSize);
257 Information = DescriptionSize;
258 }
259 }
260 break;
261 }
262 case DeviceTextLocationInformation:
263 {
264 /* We don't have any text location to report,
265 * and this query is optional, so ignore it.
266 */
267 Information = Irp->IoStatus.Information;
268 Status = Irp->IoStatus.Status;
269 break;
270 }
271 default:
272 {
273 DPRINT1("USBMP: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
274 Stack->Parameters.QueryDeviceText.DeviceTextType);
275 Status = STATUS_NOT_SUPPORTED;
276 }
277 }
278 break;
279 }
280 #endif
281 case IRP_MN_QUERY_ID: /* 0x13 */
282 {
283 Status = UsbMpPdoQueryId(DeviceObject, Irp, &Information);
284 break;
285 }
286 default:
287 {
288 /* We can't forward request to the lower driver, because
289 * we are a Pdo, so we don't have lower driver...
290 */
291 DPRINT1("USBMP: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
292 Information = Irp->IoStatus.Information;
293 Status = Irp->IoStatus.Status;
294 }
295 }
296
297 Irp->IoStatus.Information = Information;
298 Irp->IoStatus.Status = Status;
299 IoCompleteRequest(Irp, IO_NO_INCREMENT);
300 return Status;
301 }
302