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