38b1873ad87c73b33b5cfc0ffd4a4b9b5d6c8019
[reactos.git] / reactos / drivers / usb / miniport / common / main.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/main.c
5 * PURPOSE: Driver entry
6 *
7 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.com)
8 * Hervé Poussineau (hpoussin@reactos.org),
9 *
10 * Some parts of code are inspired (or even just copied) from
11 * ReactOS Videoport driver (drivers/video/videoprt)
12 */
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #define INITGUID
18 #include "usbcommon.h"
19
20 // data for embedded drivers
21 CONNECT_DATA KbdClassInformation;
22 CONNECT_DATA MouseClassInformation;
23 PDEVICE_OBJECT KeyboardFdo = NULL;
24 PDEVICE_OBJECT MouseFdo = NULL;
25
26 static NTSTATUS
27 CreateRootHubPdo(
28 IN PDRIVER_OBJECT DriverObject,
29 IN PDEVICE_OBJECT Fdo,
30 OUT PDEVICE_OBJECT* pPdo)
31 {
32 PDEVICE_OBJECT Pdo;
33 PUSBMP_DEVICE_EXTENSION DeviceExtension;
34 NTSTATUS Status;
35
36 DPRINT("USBMP: CreateRootHubPdo()\n");
37
38 Status = IoCreateDevice(
39 DriverObject,
40 sizeof(USBMP_DEVICE_EXTENSION),
41 NULL, /* DeviceName */
42 FILE_DEVICE_BUS_EXTENDER,
43 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
44 FALSE,
45 &Pdo);
46 if (!NT_SUCCESS(Status))
47 {
48 DPRINT("USBMP: IoCreateDevice() call failed with status 0x%08x\n", Status);
49 return Status;
50 }
51
52 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
53 Pdo->Flags |= DO_POWER_PAGABLE;
54
55 // zerofill device extension
56 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)Pdo->DeviceExtension;
57 RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION));
58
59 DeviceExtension->IsFDO = FALSE;
60 DeviceExtension->FunctionalDeviceObject = Fdo;
61
62 Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
63
64 *pPdo = Pdo;
65 return STATUS_SUCCESS;
66 }
67 #if 0
68 static NTSTATUS
69 AddDevice_Keyboard(
70 IN PDRIVER_OBJECT DriverObject,
71 IN PDEVICE_OBJECT Pdo)
72 {
73 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
74 PDEVICE_OBJECT Fdo;
75 NTSTATUS Status;
76
77 Status = IoCreateDevice(DriverObject,
78 8, // debug
79 &DeviceName,
80 FILE_DEVICE_KEYBOARD,
81 FILE_DEVICE_SECURE_OPEN,
82 TRUE,
83 &Fdo);
84
85 if (!NT_SUCCESS(Status))
86 {
87 DPRINT1("USBMP: IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status);
88 return Status;
89 }
90 KeyboardFdo = Fdo;
91 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
92 DPRINT("USBMP: Created keyboard Fdo: %p\n", Fdo);
93
94 return STATUS_SUCCESS;
95 }
96
97 static NTSTATUS
98 AddDevice_Mouse(
99 IN PDRIVER_OBJECT DriverObject,
100 IN PDEVICE_OBJECT Pdo)
101 {
102 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
103 PDEVICE_OBJECT Fdo;
104 NTSTATUS Status;
105
106 Status = IoCreateDevice(DriverObject,
107 8, // debug
108 &DeviceName,
109 FILE_DEVICE_MOUSE,
110 FILE_DEVICE_SECURE_OPEN,
111 TRUE,
112 &Fdo);
113
114 if (!NT_SUCCESS(Status))
115 {
116 DPRINT1("USBMP: IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status);
117 return Status;
118 }
119 MouseFdo = Fdo;
120 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
121 DPRINT("USBMP: Created mouse Fdo: %p\n", Fdo);
122
123 return STATUS_SUCCESS;
124 }
125 #endif
126
127 NTSTATUS STDCALL
128 AddDevice(
129 IN PDRIVER_OBJECT DriverObject,
130 IN PDEVICE_OBJECT pdo)
131 {
132 PDEVICE_OBJECT fdo;
133 NTSTATUS Status;
134 WCHAR DeviceBuffer[20];
135 WCHAR LinkDeviceBuffer[20];
136 UNICODE_STRING DeviceName;
137 UNICODE_STRING LinkDeviceName;
138 PUSBMP_DRIVER_EXTENSION DriverExtension;
139 PUSBMP_DEVICE_EXTENSION DeviceExtension;
140 ULONG DeviceNumber;
141
142 /* FIXME: actually, we prevent multiple USB controllers on a computer */
143 static BOOLEAN xbox_workaround = FALSE;
144
145 DPRINT("USBMP: AddDevice called\n");
146
147 if (xbox_workaround)
148 // Fail for any other host controller than the first
149 return STATUS_INSUFFICIENT_RESOURCES;
150 xbox_workaround = TRUE;
151
152 // Allocate driver extension now
153 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
154 if (DriverExtension == NULL)
155 {
156 Status = IoAllocateDriverObjectExtension(
157 DriverObject,
158 DriverObject,
159 sizeof(USBMP_DRIVER_EXTENSION),
160 (PVOID *)&DriverExtension);
161
162 if (!NT_SUCCESS(Status))
163 {
164 DPRINT("USBMP: Allocating DriverObjectExtension failed.\n");
165 return Status;
166 }
167 }
168
169 // Create a unicode device name
170 DeviceNumber = 0; //TODO: Allocate new device number every time
171 swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
172 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
173
174 Status = IoCreateDevice(DriverObject,
175 sizeof(USBMP_DEVICE_EXTENSION),
176 &DeviceName,
177 FILE_DEVICE_BUS_EXTENDER,
178 0,
179 FALSE,
180 &fdo);
181
182 if (!NT_SUCCESS(Status))
183 {
184 DPRINT("USBMP: IoCreateDevice call failed with status 0x%08lx\n", Status);
185 return Status;
186 }
187
188 // zerofill device extension
189 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)fdo->DeviceExtension;
190 RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION));
191
192 /* Create root hub Pdo */
193 Status = CreateRootHubPdo(DriverObject, fdo, &DeviceExtension->RootHubPdo);
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT("USBMP: CreateRootHubPdo() failed with status 0x%08lx\n", Status);
197 IoDeleteDevice(fdo);
198 return Status;
199 }
200
201 /* Register device interface for controller */
202 Status = IoRegisterDeviceInterface(
203 pdo,
204 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
205 NULL,
206 &DeviceExtension->HcdInterfaceName);
207 if (!NT_SUCCESS(Status))
208 {
209 DPRINT("USBMP: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
210 IoDeleteDevice(DeviceExtension->RootHubPdo);
211 IoDeleteDevice(fdo);
212 return Status;
213 }
214
215 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
216
217 // Initialize device extension
218 DeviceExtension->IsFDO = TRUE;
219 DeviceExtension->DeviceNumber = DeviceNumber;
220 DeviceExtension->PhysicalDeviceObject = pdo;
221 DeviceExtension->FunctionalDeviceObject = fdo;
222 DeviceExtension->DriverExtension = DriverExtension;
223
224 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
225
226 /* FIXME: do a loop to find an available number */
227 swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", 0);
228
229 RtlInitUnicodeString(&LinkDeviceName, LinkDeviceBuffer);
230
231 Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName);
232
233 /*
234 if (NT_SUCCESS(Status))
235 Status = AddDevice_Keyboard(DriverObject, pdo);
236 if (NT_SUCCESS(Status))
237 Status = AddDevice_Mouse(DriverObject, pdo);
238 */
239
240 if (!NT_SUCCESS(Status))
241 {
242 DPRINT("USBMP: IoCreateSymbolicLink() call failed with status 0x%08x\n", Status);
243 IoDeleteDevice(DeviceExtension->RootHubPdo);
244 IoDeleteDevice(fdo);
245 return Status;
246 }
247
248
249 return STATUS_SUCCESS;
250 }
251
252 NTSTATUS STDCALL
253 IrpStub(
254 IN PDEVICE_OBJECT DeviceObject,
255 IN PIRP Irp)
256 {
257 NTSTATUS Status = STATUS_NOT_SUPPORTED;
258
259 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
260 {
261 DPRINT1("USBMP: FDO stub for major function 0x%lx\n",
262 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
263 #ifndef NDEBUG
264 DbgBreakPoint();
265 #endif
266 return ForwardIrpAndForget(DeviceObject, Irp);
267 }
268 else
269 {
270 /* We can't forward request to the lower driver, because
271 * we are a Pdo, so we don't have lower driver...
272 */
273 DPRINT1("USBMP: PDO stub for major function 0x%lx\n",
274 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
275 #ifndef NDEBUG
276 DbgBreakPoint();
277 #endif
278 }
279
280 Status = Irp->IoStatus.Status;
281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
282 return Status;
283 }
284
285 static NTSTATUS STDCALL
286 DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
287 {
288 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
289 return UsbMpCreate(DeviceObject, Irp);
290 else
291 return IrpStub(DeviceObject, Irp);
292 }
293
294 static NTSTATUS STDCALL
295 DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
296 {
297 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
298 return UsbMpClose(DeviceObject, Irp);
299 else
300 return IrpStub(DeviceObject, Irp);
301 }
302
303 static NTSTATUS STDCALL
304 DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
305 {
306 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
307 return UsbMpCleanup(DeviceObject, Irp);
308 else
309 return IrpStub(DeviceObject, Irp);
310 }
311
312 static NTSTATUS STDCALL
313 DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
314 {
315 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
316 return UsbMpDeviceControlFdo(DeviceObject, Irp);
317 else
318 return UsbMpDeviceControlPdo(DeviceObject, Irp);
319 }
320
321 static NTSTATUS STDCALL
322 DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
323 {
324 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
325 return UsbMpInternalDeviceControlFdo(DeviceObject, Irp);
326 else
327 return IrpStub(DeviceObject, Irp);
328 }
329
330 static NTSTATUS STDCALL
331 DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
332 {
333 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
334 return UsbMpPnpFdo(DeviceObject, Irp);
335 else
336 return UsbMpPnpPdo(DeviceObject, Irp);
337 }
338
339 static NTSTATUS STDCALL
340 DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
341 {
342 DPRINT1("USBMP: IRP_MJ_POWER unimplemented\n");
343 Irp->IoStatus.Information = 0;
344 Irp->IoStatus.Status = STATUS_SUCCESS;
345 IoCompleteRequest(Irp, IO_NO_INCREMENT);
346 return STATUS_SUCCESS;
347 }
348
349 /*
350 * Standard DriverEntry method.
351 */
352 NTSTATUS STDCALL
353 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
354 {
355 USBPORT_INTERFACE UsbPortInterface;
356 ULONG i;
357
358 DriverObject->DriverUnload = DriverUnload;
359 DriverObject->DriverExtension->AddDevice = AddDevice;
360
361 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
362 DriverObject->MajorFunction[i] = IrpStub;
363
364 DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
365 DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
366 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
367 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
368 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl;
369 DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
370 DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
371
372 // Register in usbcore.sys
373 UsbPortInterface.KbdConnectData = &KbdClassInformation;
374 UsbPortInterface.MouseConnectData = &MouseClassInformation;
375
376 KbdClassInformation.ClassService = NULL;
377 KbdClassInformation.ClassDeviceObject = NULL;
378 MouseClassInformation.ClassService = NULL;
379 MouseClassInformation.ClassDeviceObject = NULL;
380
381 RegisterPortDriver(DriverObject, &UsbPortInterface);
382
383 return STATUS_SUCCESS;
384 }