e53a56e5880bc517184a1e145a3034fa8f68d6b1
[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 InitializeListHead(&portcls_ext->PhysicalConnectionList);
173
174 status = KsAllocateDeviceHeader(&portcls_ext->KsDeviceHeader, 0, NULL);
175 if (!NT_SUCCESS(status))
176 {
177 IoDeleteDevice(fdo);
178 return status;
179 }
180
181 DPRINT("PcAddAdapterDriver succeeded\n");
182
183 return status;
184 }
185
186 NTSTATUS
187 NTAPI
188 PciDriverDispatch(
189 IN PDEVICE_OBJECT DeviceObject,
190 IN PIRP Irp)
191 {
192 NTSTATUS Status;
193
194 ISubdevice * SubDevice;
195 PCExtension* DeviceExt;
196 SUBDEVICE_ENTRY * Entry;
197 KSDISPATCH_TABLE DispatchTable;
198
199 DPRINT1("PortClsSysControl called\n");
200
201 SubDevice = (ISubdevice*)Irp->Tail.Overlay.DriverContext[3];
202 DeviceExt = (PCExtension*)DeviceObject->DeviceExtension;
203
204 if (!SubDevice || !DeviceExt)
205 {
206 return STATUS_UNSUCCESSFUL;
207 }
208
209 Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
210 if (!Entry)
211 return STATUS_INSUFFICIENT_RESOURCES;
212
213 /* initialize DispatchTable */
214 RtlZeroMemory(&DispatchTable, sizeof(KSDISPATCH_TABLE));
215 /* FIXME
216 * initialize DispatchTable pointer
217 * which call in turn ISubDevice
218 */
219
220
221 Status = KsAllocateObjectHeader(&Entry->ObjectHeader, 1, NULL, Irp, &DispatchTable);
222 if (!NT_SUCCESS(Status))
223 {
224 ExFreePoolWithTag(Entry, TAG_PORTCLASS);
225 return Status;
226 }
227
228
229 InsertTailList(&DeviceExt->SubDeviceList, &Entry->Entry);
230
231 Irp->IoStatus.Status = STATUS_SUCCESS;
232 Irp->IoStatus.Information = 0;
233 IoCompleteRequest(Irp, IO_NO_INCREMENT);
234
235 return STATUS_SUCCESS;
236 }
237
238 NTSTATUS NTAPI
239 PcRegisterSubdevice(
240 IN PDEVICE_OBJECT DeviceObject,
241 IN PWCHAR Name,
242 IN PUNKNOWN Unknown)
243 {
244 PCExtension* DeviceExt;
245 NTSTATUS Status;
246 ISubdevice *SubDevice;
247 UNICODE_STRING ReferenceString;
248 UNICODE_STRING SymbolicLinkName;
249
250
251 if (!DeviceObject || !Name || !Unknown)
252 return STATUS_INVALID_PARAMETER;
253
254 DeviceExt = (PCExtension*)DeviceObject->DeviceExtension;
255 if (!DeviceExt)
256 return STATUS_UNSUCCESSFUL;
257
258 Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice);
259 if (!NT_SUCCESS(Status))
260 {
261 /* the provided port driver doesnt support ISubdevice */
262 return STATUS_INVALID_PARAMETER;
263 }
264
265 Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PciDriverDispatch, (PVOID)SubDevice, Name, NULL);
266 if (!NT_SUCCESS(Status))
267 {
268 /* failed to attach */
269 SubDevice->lpVtbl->Release(SubDevice);
270 return Status;
271 }
272
273 /* FIXME retrieve guid from subdescriptor */
274
275 RtlInitUnicodeString(&ReferenceString, Name);
276 /* register device interface */
277 Status = IoRegisterDeviceInterface(DeviceExt->PhysicalDeviceObject,
278 &GUID_DEVCLASS_SOUND, //FIXME
279 &ReferenceString,
280 &SymbolicLinkName);
281 if (NT_SUCCESS(Status))
282 {
283 Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
284 RtlFreeUnicodeString(&SymbolicLinkName);
285 }
286
287
288 return Status;
289 }