From the documentation of windows, I know that there are three ways to get the audio device:
IMMDeviceCollection::Item
IMMDeviceEnumerator::GetDefaultAudioEndpoint
IMMDeviceEnumerator::GetDevice
then I hook the three ways, And I see all of them has been called,
And I find a device been created but not by the above ways.
So how did it created with? (it is a default device)
Related
I'm trying to write a custom USB MIDI driver for macOS. I found a few projects online that are based on some old Apple Sample code, one example linked below.
https://github.com/ysalathe/GenericUSBMIDI
The project seems sensible and works to an extent, but I'm having a problem with it. I hoped someone with experience of the macOS CFPlugin based MIDI driver system might be able to help me...
Steps to recreate issue:
Copy the project's product (GenericUSBDriver.plugin) to ~/Library/Audio/MIDI Drivers
Connect my MIDI device via USB
Open Audio MIDI setup and select show MIDI studio
MIDI studio now shows an icon with the name from my MIDI device's USB descriptor. However, my log shows that my driver failed in USBDevice::OpenAndConfigure when USBDeviceOpen() returns kIOReturnExclusiveAccess (USBDevice.cpp line: 189).
require_noerr((*mPluginIntf)->USBDeviceOpen(mPluginIntf), errexit);
Then after clicking 'Rescan MIDI' my driver loads successfully and a 2nd icon appears in MIDI studio with the driver specified name, but the original icon from step 4 persists. So, I now have 2 icons representing the attached device in MIDI Studio.
Googling things like: 'USBDeviceOpen() kIOReturnExclusiveAccess MIDI' gets various 'Apple Mailing Lists' hits around a decade old, but with no solutions.
It seems to me the standard Apple USB MIDI driver is grabbing my device and causing my driver to fail with kIOReturnExclusiveAccess on USBDeviceOpen(). Then after clicking 'Rescan MIDI' the Apple driver has let go, which allows my driver to load.
My device has an asynchronous USB audio interface, and a MIDI interface with 2 bidirectional ports.
My main question is...
How can I get the Apple MIDI system to select my driver after matching on USB VID/PID instead of the standard Apple driver?
but also...
Does anyone know of any docs or books that can help me? Is there a newer/ better way perhaps?
My driver renames the MIDI ports to something more intuitive for our users, macOS seems to ignore the names in the jack descriptors unlike Windows. Is there another way to do this?
I've been reading the book "OS X and iOS Kernel Programming", but while being very interesting hasn't shed any light on this problem. I can get their USB driver example to match on my USB device's MIDI interface and load, but there seems no obvious way for that to then influence the CFPlugin choice.
I am writing a USB driver and have a popup that contains specific information about the currently selected USB device.
However, I seem unable to find any way to determine the current power being used by the device. I can obtain the current power available on the port, but not the device itself.
There are API's to request extra power and to release it, but I can find nothing that tells me what the current power draw of the device is.
I know it is possible as other utilities can show this information, however, IOKit seems to lack the usual level of Apple documentation!
Is the "Requested Power" property on the IOUSBDevice node corresponding to the device of use to you? This is the value of the "bMaxPower" property in the configuration descriptor, i.e. the device's advertised maximum power consumption in 2mA units. Things get a little more complicated with USB3, the extra 400mA that can be made available to a superspeed device are recorded separately, and I think it's different again for the extra power supplied to iPods, iPhones, etc. which don't follow the USB3 spec. You'll need to check the IOUSBDevice source code for that, and maybe do some digging around with IORegistryExplorer.
I wish to simultaneously play sounds through up to 12 mono speakers.
I could connect these to my MacBook using 6 USB soundcards, and use the left and right channel of each.
But how can I get the MacBook to play sound out of speaker #5, for example?
PS If anyone can see a smarter way to wire up 12 speakers to a MacBook, please do say!
You can setup an Aggregate Device (Audio Midi Setup > Create Aggregate Device), which allows the ability to combine multiple devices of the same model, or to combine multiple inputs and outputs for apps that don't support separate input and output devices. This Apple guide shows how it works and is surprisingly quite easy to setup.
Another way to route audio to multiple channels and outputs (up to 64) is with the free app/plug-in Soundflower. You can download a compiled version, or compile the source code if you want/need to specifically do something that the current compiled version might not.
I wonder if anyone can help at all, a bit of a specialist problem this.
I have an application that needs to read and analyse a number of USB devices (not simultaneously, they are each run in seperate tests and could in theory be run on different machines).
Each of the USB devices is based on the USB HID class, and are manufactured by different companies, none of these USB devices are designed to be run on PC, but are meant for a different platform, however for the purposes of testing the devices the client has requested that the test application is run from a PC.
Some of the devices will start up, be recognised by windows which will initialise and start them correctly using the generic HID class driver built into windows, the devices will then start sending correct data packets of the data to be tested.
Some of the devices will start up, be recognised by windows which will try to start them but fail to fully to initialise them leaving them in a half initialised state. This is fine, as I can use my beagle protocol analyser to capture the initialisation packets from the genuine platform and then use the LibUSBDotNet library to replicate the remaining packets in the initialisation sequence and get them to start sending the packets correctly.
The problem I have is with one particular device (though there are some more I haven't tested yet so it's quite possible one of those may also exhibit the same problem). The issue is the the Windows HID class driver recognises the device and trys to initialise and start it, this works after a fashion and the device starts sending data.
The problem is that the data being sent is different to that which is sent to the genuine platform (containing only a subset of the full data). It's as though windows has initialised the device into a different mode.
When I capture the initialisation packets from both the PC and the genuine platform using my USB protocol analyser I see that Windows is sending some slightly different initialisation packets. Using LibUSBDotNet to resend the correct packets once Windows has already started the device seems to have no effect.
My problem is that I need to stop windows from trying to initialise the device using the standard HID class driver, I've tried removing the driver in Device Manager but it still initialises it (and the driver is magically reassigned in device manager). I've done some investigation and there are possible alternatives:
Create a specific driver which windows will assign to the particular VID/PID of the device but that does nothing, then I can use LibUSBDotNet to send the correct initialisation sequence to the device from within my own code.
Use something like WinUSB to create a proper driver for the device (or possibly to create a "dead" driver like 1.
Will a driver with a specific VID/PID defined be used by windows in preference to it's inbuilt USB HID class driver? If not then I would be wasting my time going down this route?
Note, my mac initialises the problem device correctly, and I've asked the question of the client whether the application can be developed for Mac and their answer was frustrating Windows only.
I've no experience in writing proper Windows drivers, though I have experience in talking to USB at a relatively low level (so that part doesn't worry too much). Can anyone suggest a good course of action (before I potentially waste weeks investigating how to write drivers for the PC only to find my selected course of action can't deliver what I required).
Any help or suggest much appreciated.
Thanks,
Rich
Added after trying suggestions below:
I tried using the LibUsbDotNet inf wizard to create the necessary files and install them and this appeared to work - certainly the device was now appearing in Device Manager as a libusb-win32 device - not HID device and the associated driver was libusb driver. Even after doing this the device still seems to become initialised and start sending the wrong type of data packets although now those packets are no longer handled by the class driver and are just lost.
I also came across Zadig which has a similar inf creation wizard for WinUSB and this had exactly the same result.
A colleague has suggested that it might not be windows itself that is switching the device into this mode, rather the device identifying that it is connected to a windows machine and switching itself into this mode. I suspect this is the case, in which case I am stuck - time to have another conversation with the client.
Many thanks for the help.
You're using libusb-win32 as a filter driver; that is, the HidUsb device driver is assigned and loaded for your device, but then the libusb-win32 driver is loaded on top and gives you unobstructed access to the hardware.
If you don't want a HidUsb (or any other class driver) to perform any communication "on your behalf", simply associate libusb-win32 as a device driver with your hardware. For this, you'd have to create an .INF file associating it with the VID/PID/Revision of each USB device. If I recall correctly, libusb-win32 even comes with a utility to generate such .INF files.
If you install this .INF file e.g. with PnpUtil.exe (available on Vista or higher), you might still run into issues where, although you're a better match than the generic HID driver, the HID driver is still selected.
The generic HID driver matches devices by their Compatible IDs (i.e. by a USB interface class) while you'd be matching by Hardware IDs (which have higher priority). However, Windows might give priority to other aspects, such as your driver being unsigned. Read: How Windows Selects Drivers
Luckily, even in that scenario, signing drivers with a self-generated certificate (use CertUtil.exe, MakeCat.exe and SignTool.exe) is not too difficult.
A friend of mine and I got into a conversation and realized Windows 7 is missing a key component to its per-application audio settings. You can set volume but you can't stipulate which device each application should use.
Some applications such as ventrilo or skype allow you to select which device to use however, MOST applications simply rely on the current 'Default Audio Device.'
Is there a way to access this? What language would be best used to expose these kinds of functions? Thanks!
Ventrilo and Skype are able to choose which audio device to use because they are coded to directly specify audio output devices instead of just getting the default from the OS. For applications which are coded to use the default Windows device, you can of course change which device is the default device using the sound settings, but this will change the default for the whole system.
Setting different audio devices for separate applications which all use the default audio device isn't something that is necessarily supported by Windows, and many applications use the DirectSound API which complicates the situation further. However, some applications check which device is the default when they initialize and then output exclusively to that device. In this case, you could change the default sound device to one audio device, start a program, then change the default to another audio device, and the first program would continue to use the device which was default when it started up.
However, this is a pretty weak workaround and will only work for specific applications which have been coded in the way described above.