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