sync trunk HEAD (r50626)
[reactos.git] / base / services / audiosrv / pnp.c
1 /*
2 * PROJECT: ReactOS
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/services/audiosrv/pnp.c
5 * PURPOSE: Audio Service Plug and Play
6 * COPYRIGHT: Copyright 2007 Andrew Greenwood
7 */
8
9 #include <windows.h>
10 #include <winuser.h>
11 #include <dbt.h>
12 #include <setupapi.h>
13
14 #include <ks.h>
15 #include <ksmedia.h>
16
17 #include <audiosrv/audiosrv.h>
18 #include "audiosrv.h"
19
20 static HDEVNOTIFY device_notification_handle = NULL;
21
22
23 /*
24 Finds all devices within the KSCATEGORY_AUDIO category and puts them
25 in the shared device list.
26 */
27
28 BOOL
29 ProcessExistingDevices()
30 {
31 SP_DEVICE_INTERFACE_DATA interface_data;
32 SP_DEVINFO_DATA device_data;
33 PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail_data;
34 HDEVINFO dev_info;
35 DWORD length;
36 int index = 0;
37
38 const GUID category_guid = {STATIC_KSCATEGORY_AUDIO};
39
40 dev_info = SetupDiGetClassDevsExW(&category_guid,
41 NULL,
42 NULL,
43 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
44 NULL,
45 NULL,
46 NULL);
47
48 /* printf("%s:\n", ClassString); */
49
50 interface_data.cbSize = sizeof(interface_data);
51 interface_data.Reserved = 0;
52
53 /* Enumerate the devices within the category */
54 index = 0;
55
56 length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)
57 + (MAX_PATH * sizeof(WCHAR));
58
59 detail_data =
60 (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
61 0,
62 length);
63
64 if ( ! detail_data )
65 {
66 logmsg("ProcessExistingDevices() failed to allocate detail_data\n");
67 return TRUE;
68 }
69
70 while (
71 SetupDiEnumDeviceInterfaces(dev_info,
72 NULL,
73 &category_guid,
74 index,
75 &interface_data) )
76 {
77 PnP_AudioDevice* list_node;
78
79 ZeroMemory(detail_data, length);
80
81 /* NOTE: We don't actually use device_data... */
82 detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
83 device_data.cbSize = sizeof(device_data);
84 device_data.Reserved = 0;
85 SetupDiGetDeviceInterfaceDetailW(dev_info,
86 &interface_data,
87 detail_data,
88 length,
89 NULL,
90 &device_data);
91
92 list_node = CreateDeviceDescriptor(detail_data->DevicePath, TRUE);
93 AppendAudioDeviceToList(list_node);
94 DestroyDeviceDescriptor(list_node);
95
96 /* TODO: Cleanup the device we enumerated? */
97
98 index ++;
99 };
100
101 HeapFree(GetProcessHeap(), 0, detail_data);
102
103 SetupDiDestroyDeviceInfoList(dev_info);
104
105 return TRUE;
106 }
107
108
109 /*
110 Add new devices to the list as they arrive.
111 */
112
113 DWORD
114 ProcessDeviceArrival(DEV_BROADCAST_DEVICEINTERFACE* device)
115 {
116 PnP_AudioDevice* list_node;
117 list_node = CreateDeviceDescriptor(device->dbcc_name, TRUE);
118 AppendAudioDeviceToList(list_node);
119 DestroyDeviceDescriptor(list_node);
120
121 return NO_ERROR;
122 }
123
124
125 /*
126 Request notification of device additions/removals.
127 */
128
129 BOOL
130 RegisterForDeviceNotifications()
131 {
132 DEV_BROADCAST_DEVICEINTERFACE notification_filter;
133
134 const GUID wdmaud_guid = {STATIC_KSCATEGORY_AUDIO};
135
136 ZeroMemory(&notification_filter, sizeof(notification_filter));
137 notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
138 notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
139 notification_filter.dbcc_classguid = wdmaud_guid;
140
141 device_notification_handle =
142 RegisterDeviceNotificationW((HANDLE) service_status_handle,
143 &notification_filter,
144 DEVICE_NOTIFY_SERVICE_HANDLE
145 /* |
146 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES*/);
147
148 if ( ! device_notification_handle )
149 {
150 logmsg("RegisterDeviceNotification() failed with error %d\n", GetLastError());
151 }
152
153 return ( device_notification_handle != NULL );
154 }
155
156
157 /*
158 When we're not interested in device notifications any more, this gets
159 called.
160 */
161
162 VOID UnregisterDeviceNotifications()
163 {
164 /* TODO -- NOT IMPLEMENTED! */
165
166 if ( device_notification_handle )
167 {
168 /* TODO */
169 device_notification_handle = NULL;
170 }
171 }
172
173
174 /*
175 Device events from the main service handler get passed to this.
176 */
177
178 DWORD
179 HandleDeviceEvent(
180 DWORD dwEventType,
181 LPVOID lpEventData)
182 {
183 switch ( dwEventType )
184 {
185 case DBT_DEVICEARRIVAL :
186 {
187 DEV_BROADCAST_DEVICEINTERFACE* incoming_device =
188 (DEV_BROADCAST_DEVICEINTERFACE*) lpEventData;
189
190 return ProcessDeviceArrival(incoming_device);
191 }
192
193 default :
194 {
195 break;
196 }
197 }
198
199 return NO_ERROR;
200 }