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(¬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 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