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