xref: /reactos/base/services/audiosrv/pnp.c (revision 4d3df0da)
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 #include <winreg.h>
12 #include <winuser.h>
13 #include <mmsystem.h>
14 #include <setupapi.h>
15 #include <ks.h>
16 #include <ksmedia.h>
17 
18 static HDEVNOTIFY device_notification_handle = NULL;
19 
20 /*
21     Finds all devices within the KSCATEGORY_AUDIO category and puts them
22     in the shared device list.
23 */
24 
25 BOOL
26 ProcessExistingDevices(VOID)
27 {
28     SP_DEVICE_INTERFACE_DATA interface_data;
29     SP_DEVINFO_DATA device_data;
30     PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail_data;
31     HDEVINFO dev_info;
32     DWORD length;
33     int index = 0;
34 
35     const GUID category_guid = {STATIC_KSCATEGORY_AUDIO};
36 
37     dev_info = SetupDiGetClassDevsExW(&category_guid,
38                                       NULL,
39                                       NULL,
40                                       DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
41                                       NULL,
42                                       NULL,
43                                       NULL);
44 
45 /*    printf("%s:\n", ClassString); */
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         logmsg("ProcessExistingDevices() 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
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
127 RegisterForDeviceNotifications(VOID)
128 {
129     DEV_BROADCAST_DEVICEINTERFACE notification_filter;
130 
131     const GUID wdmaud_guid = {STATIC_KSCATEGORY_AUDIO};
132 
133     ZeroMemory(&notification_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                                     &notification_filter,
141                                     DEVICE_NOTIFY_SERVICE_HANDLE
142 /* |
143                                    DEVICE_NOTIFY_ALL_INTERFACE_CLASSES*/);
144     if (!device_notification_handle)
145     {
146         logmsg("RegisterDeviceNotification() 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
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
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