- Revert to pre-38722 to unbreak build
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / adapter.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/multimedia/portcls/adapter.c
5 * PURPOSE: Port Class driver / DriverEntry and IRP handlers
6 * PROGRAMMER: Andrew Greenwood
7 *
8 * HISTORY:
9 * 27 Jan 07 Created
10 */
11
12 #include "private.h"
13 #include <devguid.h>
14 #include <initguid.h>
15
16 const GUID IID_ISubdevice;
17
18 /*
19 This is called from DriverEntry so that PortCls can take care of some
20 IRPs and map some others to the main KS driver. In most cases this will
21 be the first function called by an audio driver.
22
23 First 2 parameters are from DriverEntry.
24
25 The AddDevice parameter is a driver-supplied pointer to a function which
26 typically then calls PcAddAdapterDevice (see below.)
27 */
28 NTSTATUS NTAPI
29 PcInitializeAdapterDriver(
30 IN PDRIVER_OBJECT DriverObject,
31 IN PUNICODE_STRING RegistryPathName,
32 IN PDRIVER_ADD_DEVICE AddDevice)
33 {
34 /*
35 (* = implement here, otherwise KS default)
36 IRP_MJ_CLOSE
37 * IRP_MJ_CREATE
38 IRP_MJ_DEVICE_CONTROL
39 IRP_MJ_FLUSH_BUFFERS
40 * IRP_MJ_PNP
41 * IRP_MJ_POWER
42 IRP_MJ_QUERY_SECURITY
43 IRP_MJ_READ
44 IRP_MJ_SET_SECURITY
45 * IRP_MJ_SYSTEM_CONTROL
46 IRP_MJ_WRITE
47 */
48
49 //NTSTATUS status;
50 //ULONG i;
51
52 DPRINT("PcInitializeAdapterDriver\n");
53
54 #if 0
55 /* Set default stub - is this a good idea? */
56 DPRINT1("Setting IRP stub\n");
57 for ( i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i ++ )
58 {
59 DriverObject->MajorFunction[i] = IrpStub;
60 }
61 #endif
62
63 /* Our IRP handlers */
64 DPRINT1("Setting IRP handlers\n");
65 DriverObject->MajorFunction[IRP_MJ_CREATE] = PcDispatchIrp;
66 DriverObject->MajorFunction[IRP_MJ_PNP] = PcDispatchIrp;
67 DriverObject->MajorFunction[IRP_MJ_POWER] = PcDispatchIrp;
68 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PcDispatchIrp;
69
70 /* The driver-supplied AddDevice */
71 DriverObject->DriverExtension->AddDevice = AddDevice;
72
73 /* KS handles these */
74 DPRINT1("Setting KS function handlers\n");
75 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
76 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
77 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_FLUSH_BUFFERS);
78 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_QUERY_SECURITY);
79 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_READ);
80 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_SET_SECURITY);
81 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
82
83 DPRINT1("PortCls has finished initializing the adapter driver\n");
84
85 return STATUS_SUCCESS;
86 }
87
88 /*
89 Typically called by a driver's AddDevice function, which is set when
90 calling PcInitializeAdapterDriver. This performs some common driver
91 operations, such as creating a device extension.
92
93 The StartDevice parameter is a driver-supplied function which gets
94 called in response to IRP_MJ_PNP / IRP_MN_START_DEVICE.
95 */
96 NTSTATUS NTAPI
97 PcAddAdapterDevice(
98 IN PDRIVER_OBJECT DriverObject,
99 IN PDEVICE_OBJECT PhysicalDeviceObject,
100 IN PCPFNSTARTDEVICE StartDevice,
101 IN ULONG MaxObjects,
102 IN ULONG DeviceExtensionSize)
103 {
104 /*
105 Note - after this has been called, we can
106 handle IRP_MN_START_DEVICE by calling StartDevice
107
108 TODO:
109 Validate DeviceExtensionSize!! (et al...)
110 */
111
112 NTSTATUS status = STATUS_UNSUCCESSFUL;
113 PDEVICE_OBJECT fdo = NULL;
114 PCExtension* portcls_ext;
115
116 DPRINT1("PcAddAdapterDevice called\n");
117
118 if ( ! DriverObject)
119 {
120 DPRINT("DriverObject is NULL!\n");
121 return STATUS_INVALID_PARAMETER;
122 }
123
124 if ( ! PhysicalDeviceObject )
125 {
126 DPRINT("PhysicalDeviceObject is NULL!\n");
127 return STATUS_INVALID_PARAMETER;
128 }
129
130 if ( ! StartDevice )
131 {
132 DPRINT("No StartDevice parameter!\n");
133 return STATUS_INVALID_PARAMETER;
134 }
135
136 /* TODO: Make sure this is right */
137 if ( DeviceExtensionSize < PORT_CLASS_DEVICE_EXTENSION_SIZE )
138 {
139 if ( DeviceExtensionSize != 0 )
140 {
141 /* TODO: Error */
142 DPRINT("DeviceExtensionSize is invalid\n");
143 return STATUS_INVALID_PARAMETER;
144 }
145 }
146
147 DPRINT("portcls is creating a device\n");
148 status = IoCreateDevice(DriverObject,
149 DeviceExtensionSize,
150 NULL,
151 FILE_DEVICE_KS,
152 PhysicalDeviceObject->Characteristics, /* TODO: Check */
153 FALSE,
154 &fdo);
155
156 if ( ! NT_SUCCESS(status) )
157 {
158 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", status);
159 return status;
160 }
161
162 /* Obtain the new device extension */
163 portcls_ext = (PCExtension*) fdo->DeviceExtension;
164
165 ASSERT(portcls_ext);
166
167 /* Initialize */
168 RtlZeroMemory(portcls_ext, sizeof(PCExtension));
169 portcls_ext->PhysicalDeviceObject = PhysicalDeviceObject;
170 portcls_ext->StartDevice = StartDevice;
171 InitializeListHead(&portcls_ext->SubDeviceList);
172
173 status = KsAllocateDeviceHeader(&portcls_ext->KsDeviceHeader, 0, NULL);
174 if (!NT_SUCCESS(status))
175 {
176 IoDeleteDevice(fdo);
177 return status;
178 }
179
180 DPRINT("PcAddAdapterDriver succeeded\n");
181
182 return status;
183 }
184
185 NTSTATUS
186 NTAPI
187 PciDriverDispatch(
188 IN PDEVICE_OBJECT DeviceObject,
189 IN PIRP Irp)
190 {
191 NTSTATUS Status;
192
193 ISubdevice * SubDevice;
194 PCExtension* DeviceExt;
195 SUBDEVICE_ENTRY * Entry;
196 KSDISPATCH_TABLE DispatchTable;
197
198 DPRINT1("PortClsSysControl called\n");
199
200 SubDevice = (ISubdevice*)Irp->Tail.Overlay.DriverContext[3];
201 DeviceExt = (PCExtension*)DeviceObject->DeviceExtension;
202
203 if (!SubDevice || !DeviceExt)
204 {
205 return STATUS_UNSUCCESSFUL;
206 }
207
208 Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
209 if (!Entry)
210 return STATUS_INSUFFICIENT_RESOURCES;
211
212 /* initialize DispatchTable */
213 RtlZeroMemory(&DispatchTable, sizeof(KSDISPATCH_TABLE));
214 /* FIXME
215 * initialize DispatchTable pointer
216 * which call in turn ISubDevice
217 */
218
219
220 Status = KsAllocateObjectHeader(&Entry->ObjectHeader, 1, NULL, Irp, &DispatchTable);
221 if (!NT_SUCCESS(Status))
222 {
223 ExFreePoolWithTag(Entry, TAG_PORTCLASS);
224 return Status;
225 }
226
227
228 InsertTailList(&DeviceExt->SubDeviceList, &Entry->Entry);
229
230 Irp->IoStatus.Status = STATUS_SUCCESS;
231 Irp->IoStatus.Information = 0;
232 IoCompleteRequest(Irp, IO_NO_INCREMENT);
233
234 return STATUS_SUCCESS;
235 }
236
237 NTSTATUS NTAPI
238 PcRegisterSubdevice(
239 IN PDEVICE_OBJECT DeviceObject,
240 IN PWCHAR Name,
241 IN PUNKNOWN Unknown)
242 {
243 PCExtension* DeviceExt;
244 NTSTATUS Status;
245 ISubdevice *SubDevice;
246 UNICODE_STRING ReferenceString;
247 UNICODE_STRING SymbolicLinkName;
248
249
250 if (!DeviceObject || !Name || !Unknown)
251 return STATUS_INVALID_PARAMETER;
252
253 DeviceExt = (PCExtension*)DeviceObject->DeviceExtension;
254 if (!DeviceExt)
255 return STATUS_UNSUCCESSFUL;
256
257 Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice);
258 if (!NT_SUCCESS(Status))
259 {
260 /* the provided port driver doesnt support ISubdevice */
261 return STATUS_INVALID_PARAMETER;
262 }
263
264 Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PciDriverDispatch, (PVOID)SubDevice, Name, NULL);
265 if (!NT_SUCCESS(Status))
266 {
267 /* failed to attach */
268 SubDevice->lpVtbl->Release(SubDevice);
269 return Status;
270 }
271
272 /* FIXME retrieve guid from subdescriptor */
273
274 RtlInitUnicodeString(&ReferenceString, Name);
275 /* register device interface */
276 Status = IoRegisterDeviceInterface(DeviceExt->PhysicalDeviceObject,
277 &GUID_DEVCLASS_SOUND, //FIXME
278 &ReferenceString,
279 &SymbolicLinkName);
280 if (NT_SUCCESS(Status))
281 {
282 Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
283 RtlFreeUnicodeString(&SymbolicLinkName);
284 }
285
286
287 return Status;
288 }