Move shareable part of USB miniport drivers to a new directory. UHCI uses it.
[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 static ULONG DeviceNumber = 0; /* FIXME: what is that? */
21
22 static NTSTATUS
23 CreateRootHubPdo(
24 IN PDRIVER_OBJECT DriverObject,
25 IN PDEVICE_OBJECT Fdo,
26 OUT PDEVICE_OBJECT* pPdo)
27 {
28 PDEVICE_OBJECT Pdo;
29 PUSBMP_DEVICE_EXTENSION DeviceExtension;
30 NTSTATUS Status;
31
32 DPRINT("USBMP: CreateRootHubPdo()\n");
33
34 Status = IoCreateDevice(
35 DriverObject,
36 sizeof(USBMP_DEVICE_EXTENSION),
37 NULL, /* DeviceName */
38 FILE_DEVICE_BUS_EXTENDER,
39 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
40 FALSE,
41 &Pdo);
42 if (!NT_SUCCESS(Status))
43 {
44 DPRINT("USBMP: IoCreateDevice() call failed with status 0x%08x\n", Status);
45 return Status;
46 }
47
48 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
49 Pdo->Flags |= DO_POWER_PAGABLE;
50
51 // zerofill device extension
52 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)Pdo->DeviceExtension;
53 RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION));
54
55 DeviceExtension->IsFDO = FALSE;
56 DeviceExtension->FunctionalDeviceObject = Fdo;
57
58 Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
59
60 *pPdo = Pdo;
61 return STATUS_SUCCESS;
62 }
63
64 NTSTATUS STDCALL
65 AddDevice(
66 IN PDRIVER_OBJECT DriverObject,
67 IN PDEVICE_OBJECT pdo)
68 {
69 PDEVICE_OBJECT fdo;
70 NTSTATUS Status;
71 WCHAR DeviceBuffer[20];
72 WCHAR LinkDeviceBuffer[20];
73 UNICODE_STRING DeviceName;
74 UNICODE_STRING LinkDeviceName;
75 PUSBMP_DRIVER_EXTENSION DriverExtension;
76 PUSBMP_DEVICE_EXTENSION DeviceExtension;
77
78 DPRINT("USBMP: AddDevice called\n");
79
80 // Allocate driver extension now
81 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
82 if (DriverExtension == NULL)
83 {
84 Status = IoAllocateDriverObjectExtension(
85 DriverObject,
86 DriverObject,
87 sizeof(USBMP_DRIVER_EXTENSION),
88 (PVOID *)&DriverExtension);
89
90 if (!NT_SUCCESS(Status))
91 {
92 DPRINT("USBMP: Allocating DriverObjectExtension failed.\n");
93 return Status;
94 }
95 }
96
97 // Create a unicode device name
98 // DeviceNumber = 0; //TODO: Allocate new device number every time
99 swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
100 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
101
102 Status = IoCreateDevice(DriverObject,
103 sizeof(USBMP_DEVICE_EXTENSION),
104 &DeviceName,
105 FILE_DEVICE_BUS_EXTENDER,
106 0,
107 FALSE,
108 &fdo);
109
110 if (!NT_SUCCESS(Status))
111 {
112 DPRINT("USBMP: IoCreateDevice call failed with status 0x%08lx\n", Status);
113 return Status;
114 }
115
116 // zerofill device extension
117 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)fdo->DeviceExtension;
118 RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION));
119
120 /* Create root hub Pdo */
121 Status = CreateRootHubPdo(DriverObject, fdo, &DeviceExtension->RootHubPdo);
122 if (!NT_SUCCESS(Status))
123 {
124 DPRINT("USBMP: CreateRootHubPdo() failed with status 0x%08lx\n", Status);
125 IoDeleteDevice(fdo);
126 return Status;
127 }
128
129 /* Register device interface for controller */
130 Status = IoRegisterDeviceInterface(
131 pdo,
132 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
133 NULL,
134 &DeviceExtension->HcdInterfaceName);
135 if (!NT_SUCCESS(Status))
136 {
137 DPRINT("USBMP: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
138 IoDeleteDevice(DeviceExtension->RootHubPdo);
139 IoDeleteDevice(fdo);
140 return Status;
141 }
142
143 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
144
145 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
146
147 // Initialize device extension
148 DeviceExtension->IsFDO = TRUE;
149 DeviceExtension->DeviceNumber = DeviceNumber;
150 DeviceExtension->PhysicalDeviceObject = pdo;
151 DeviceExtension->FunctionalDeviceObject = fdo;
152 DeviceExtension->DriverExtension = DriverExtension;
153
154 /* FIXME: do a loop to find an available number */
155 swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", 0);
156
157 RtlInitUnicodeString(&LinkDeviceName, LinkDeviceBuffer);
158
159 Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName);
160
161 if (!NT_SUCCESS(Status))
162 {
163 DPRINT("USBMP: IoCreateSymbolicLink call failed with status 0x%08x\n", Status);
164 IoDeleteDevice(DeviceExtension->RootHubPdo);
165 IoDeleteDevice(fdo);
166 return Status;
167 }
168
169 return STATUS_SUCCESS;
170 }
171
172 NTSTATUS STDCALL
173 IrpStub(
174 IN PDEVICE_OBJECT DeviceObject,
175 IN PIRP Irp)
176 {
177 NTSTATUS Status = STATUS_NOT_SUPPORTED;
178
179 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
180 {
181 DPRINT1("USBMP: FDO stub for major function 0x%lx\n",
182 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
183 #ifndef NDEBUG
184 DbgBreakPoint();
185 #endif
186 return ForwardIrpAndForget(DeviceObject, Irp);
187 }
188 else
189 {
190 /* We can't forward request to the lower driver, because
191 * we are a Pdo, so we don't have lower driver...
192 */
193 DPRINT1("USBMP: PDO stub for major function 0x%lx\n",
194 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
195 #ifndef NDEBUG
196 DbgBreakPoint();
197 #endif
198 }
199
200 Status = Irp->IoStatus.Status;
201 IoCompleteRequest(Irp, IO_NO_INCREMENT);
202 return Status;
203 }
204
205 static NTSTATUS STDCALL
206 DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
207 {
208 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
209 return UsbMpCreate(DeviceObject, Irp);
210 else
211 return IrpStub(DeviceObject, Irp);
212 }
213
214 static NTSTATUS STDCALL
215 DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
216 {
217 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
218 return UsbMpClose(DeviceObject, Irp);
219 else
220 return IrpStub(DeviceObject, Irp);
221 }
222
223 static NTSTATUS STDCALL
224 DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
225 {
226 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
227 return UsbMpCleanup(DeviceObject, Irp);
228 else
229 return IrpStub(DeviceObject, Irp);
230 }
231
232 static NTSTATUS STDCALL
233 DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
234 {
235 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
236 return UsbMpDeviceControlFdo(DeviceObject, Irp);
237 else
238 return UsbMpDeviceControlPdo(DeviceObject, Irp);
239 }
240
241 static NTSTATUS STDCALL
242 DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
243 {
244 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
245 return UsbMpPnpFdo(DeviceObject, Irp);
246 else
247 return UsbMpPnpPdo(DeviceObject, Irp);
248 }
249
250 static NTSTATUS STDCALL
251 DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
252 {
253 DPRINT1("USBMP: IRP_MJ_POWER unimplemented\n");
254 Irp->IoStatus.Information = 0;
255 Irp->IoStatus.Status = STATUS_SUCCESS;
256 IoCompleteRequest(Irp, IO_NO_INCREMENT);
257 return STATUS_SUCCESS;
258 }
259
260 /*
261 * Standard DriverEntry method.
262 */
263 NTSTATUS STDCALL
264 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
265 {
266 ULONG i;
267
268 DriverObject->DriverUnload = DriverUnload;
269 DriverObject->DriverExtension->AddDevice = AddDevice;
270
271 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
272 DriverObject->MajorFunction[i] = IrpStub;
273
274 DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
275 DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
276 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
277 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
278 DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
279 DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
280
281 return STATUS_SUCCESS;
282 }