From: Aric Stewart <aric@codeweavers.com> --- dlls/winecoreaudio.drv/Makefile.in | 2 +- dlls/winecoreaudio.drv/coreaudio.c | 83 +++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/dlls/winecoreaudio.drv/Makefile.in b/dlls/winecoreaudio.drv/Makefile.in index e8ee5ed433a..d54640e7686 100644 --- a/dlls/winecoreaudio.drv/Makefile.in +++ b/dlls/winecoreaudio.drv/Makefile.in @@ -1,5 +1,5 @@ UNIXLIB = winecoreaudio.so -UNIX_LIBS = $(COREAUDIO_LIBS) +UNIX_LIBS = $(COREAUDIO_LIBS) $(IOKIT_LIBS) SOURCES = \ coreaudio.c \ diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index c7e0dc24048..4e6afd8157e 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -47,6 +47,10 @@ #include <AudioToolbox/AudioFormat.h> #include <AudioToolbox/AudioConverter.h> #include <AudioUnit/AudioUnit.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/audio/IOAudioDefines.h> +#include <IOKit/usb/USB.h> + #include <os/lock.h> #undef LoadResource @@ -64,6 +68,7 @@ #include "mmdeviceapi.h" #include "initguid.h" #include "audioclient.h" +#include "devpkey.h" #include "wine/debug.h" #include "wine/unixlib.h" @@ -125,6 +130,14 @@ static HRESULT osstatus_to_hresult(OSStatus sc) return E_FAIL; } +static DWORD CFNumberToDWORD(CFNumberRef num) +{ + int dwNum = 0; + if (num) + CFNumberGetValue(num, kCFNumberIntType, &dwNum); + return dwNum; +} + static struct coreaudio_stream *handle_get_stream(stream_handle h) { return (struct coreaudio_stream *)(UINT_PTR)h; @@ -1700,12 +1713,80 @@ static NTSTATUS unix_is_started(void *args) return STATUS_SUCCESS; } +static NTSTATUS get_device_vid_pid(const char *device, DWORD *vid, DWORD *pid) +{ + CFStringRef uid = NULL; + io_iterator_t it; + NTSTATUS rc = E_FAIL; + + uid = CFStringCreateWithCStringNoCopy(NULL, device, kCFStringEncodingUTF8, kCFAllocatorNull); + + /* Find the matching IOAudioEngine object */ + if (IOServiceGetMatchingServices(kIOMainPortDefault, + IOServiceMatching(kIOAudioEngineClassName), + &it) == KERN_SUCCESS){ + io_service_t service; + + while ((service = IOIteratorNext(it)) != 0){ + CFStringRef uniqueID = IORegistryEntryCreateCFProperty(service, + CFSTR(kIOAudioEngineGlobalUniqueIDKey), + kCFAllocatorDefault, + 0); + if (uniqueID){ + if (CFEqual(uniqueID, uid)){ + CFNumberRef cfVID, cfPID; + cfVID = IORegistryEntryCreateCFProperty(service, CFSTR(kUSBVendorID), kCFAllocatorDefault, 0); + *vid = CFNumberToDWORD(cfVID); + + cfPID = IORegistryEntryCreateCFProperty(service, CFSTR(kUSBProductID), kCFAllocatorDefault, 0); + *pid = CFNumberToDWORD(cfPID); + + if(cfVID) CFRelease(cfVID); + if(cfPID) CFRelease(cfPID); + if (*vid || *pid) rc = STATUS_SUCCESS; + } + CFRelease(uniqueID); + } + if (*vid || *pid) break; + } + IOObjectRelease(it); + } + CFRelease(uid); + return rc; +} + static NTSTATUS unix_get_prop_value(void *args) { struct get_prop_value_params *params = args; + const PROPERTYKEY *prop = params->prop; - params->result = E_NOTIMPL; + if(IsEqualPropertyKey(*prop, DEVPKEY_Device_InstanceId)){ + DWORD vid=0, pid=0; + + if (SUCCEEDED(get_device_vid_pid(params->device, &vid, &pid))) { + int len; + char buf[128]; + PROPVARIANT *out = params->value; + + len = sizeof(buf); + snprintf(buf, len, "{1}.USB\\VID_%04X&PID_%04X", vid, pid); + + len = strlen(buf) + 1; + if(*params->buffer_size < len * sizeof(WCHAR)){ + params->result = E_NOT_SUFFICIENT_BUFFER; + *params->buffer_size = len * sizeof(WCHAR); + return STATUS_SUCCESS; + } + + out->vt = VT_LPWSTR; + out->pwszVal = params->buffer; + ntdll_umbstowcs(buf, len, out->pwszVal, len); + params->result = S_OK; + return STATUS_SUCCESS; + } + } + params->result = E_NOTIMPL; return STATUS_SUCCESS; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11264