[PATCH v3 0/2] MR11264: Hardware Device IDs from CoreAudio USB devices
-- v3: mmdevapi: Propagate the hardware Device_InstanceId coreaudio: Report USB device PKEY_Device_InstanceId https://gitlab.winehq.org/wine/wine/-/merge_requests/11264
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..2ddf1526baa 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 = STATUS_UNSUCCESSFUL; + + 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
Thanks for the review. I believe I have addressed all of these. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11264#note_144315
From: Aric Stewart <aric@codeweavers.com> --- dlls/mmdevapi/devenum.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 11d20f29957..8440b5d8630 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -503,6 +503,8 @@ static MMDevice *MMDevice_Create(const WCHAR *name, GUID *id, EDataFlow flow, DW pv.vt = VT_LPWSTR; pv.pwszVal = cur->drv_id; + set_driver_prop_value(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_InstanceId); + if (SUCCEEDED(set_driver_prop_value(id, flow, &devicepath_key))) { PROPVARIANT pv2; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11264
Brendan Shanks (@bshanks) commented about dlls/winecoreaudio.drv/coreaudio.c:
+ 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))) { extra space before `&vid`
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11264#note_144493
I tested this out on macOS 26.5.1 with a USB audio device connected, and it's not detecting the VID/PID. Which OS version are you testing with? Unfortunately I think there may have been macOS changes which have broken the general approach here. Using IORegistryExplorer (part of the Xcode Additional Tools downloadable from https://developer.apple.com/download/all/) or `ioreg -l`, I don't see any `IOAudioEngine` objects in the registry. I also don't see the CoreAudio UIDs stored anywhere in the registry. I unfortunately don't see an alternate way to do this. We might need to ask Apple (on the developer forums) and/or ask for a new API to be added. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11264#note_144494
Some investigation seems to show that it may be something that changed more from the shift from Intel to Apple Silicon. While this is working on my 15.7.8 Intel machine, it was not working on another developers 15 machine nor his 26. He is on apple silicon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11264#note_144546
participants (3)
-
Aric Stewart -
Aric Stewart (@aricstewart) -
Brendan Shanks (@bshanks)