IOServiceMatching on AppleUSBCDCACMData IOClass: Anomaly? - macos

I am trying to extract a list of all AppleUSBCDCACMData IOClass devices in my mac using the following code snippet (just some small scale modifications in apple sample code). The device is a usb modem which creates some 7 /dev/cu.usbmodemx device nodes.
error = IOMasterPort(MACH_PORT_NULL, &masterPort);
if(error){
return ;
}
else{
matchingDict = IOServiceMatching("AppleUSBCDCACMData");
IOServiceGetMatchingServices(masterPort,matchingDict,&modem_iterator);
while(usbDevice = IOIteratorNext(modem_iterator))
{
}
My observation is, the iterator returned by IOServiceGetMatchingServices is empty (ie nothing to iterate on). But if i pass "AppleUSBCDCACMControl" as the parameter to IOServiceMatching, i get a iterator of a list of 7 elements - which is in conformance with the IORegistryExplorer view. See a screenshot of IORegistryExplorer here, http://tumblr.deepak.dk/post/1666218968/ioregistryexplorer
It appears that it is not possible to query IORegistry with arbitrary IOClass name strings? Since i faced the same issues with some non-standard proprietary IOClasses as well.
This can be reproduced using any USB modem (3g/HSDPA) which loads AppleUSBCDC driver.
What am i doing wrong?

IOService objects can only be matched once registerService() has been called for them. AppleUSBCDCACMControl does this, but AppleUSBCDCACMData does not.

Related

Using termios in Swift

Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)

What's the difference between event's Unique-ID and Channel-Call-UUID?

Freeswitch events contain two variables (Unique-ID and Channel-Call-UUID) that seem to always be set to the exact same value: the leg's unique identifier.
I don't see the purpose of this and while Unique-ID has a one-line documentation on FS's wiki ("uuid of this channel's call leg"), Channel-Call-UUID doesn't.
Even worse: I came accross two examples where their values were different:
[...]
Channel-Call-UUID: c9bbde8b-379b-45d4-b193-3f761a44f3e2
Unique-ID: 81273088-c31f-4469-85a6-c878e42210e5
[...]
[...]
Channel-Call-UUID: ada7f3de-2374-4144-9b1d-eade29df0779
Unique-ID: f3ebca6c-d9cd-4f89-ae12-748e6c479dda
[...]
I need to be able to clearly identify a leg in my code, so I'd like to know
which one is the most accurate and
what's the purpose of the other one
"Unique-ID" identifies the leg of the current channel (this value seems to always be identical to "Caller-Unique-ID", documented as "This channel's uuid").
"Channel-Call-UUID" is an ID that can be used to identify answered/bridged channels. It seems to be derived from the "Unique-ID" of the channel's creator.
The value of "Channel-Call-UUID" of the b-leg (the callee) differs from its "Unique-ID", but it is identical to the value of the "Other-Leg-Unique-ID" header.
The source code (src/switch_channel.c) supports my previous claims:
if ((v = switch_channel_get_variable(channel, "call_uuid"))) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", switch_core_session_get_uuid(channel->session));
}

How does one discover [non-Apple] Audio Units with Audio Component Services?

In OS X, I am trying to find an example of how to discover all the Audio Units installed on an end-users system and get back that information for display and use.
I know that Audio Component is involved with that task, but I am completely baffled how to go about doing it. All the examples I come across are based around finding a 'known' Apple AU with AudioComponentFindNext, and I cannot find an example for discovering anything else.
Can anyone point me to an example?
Thanks
You can set up a AudioComponentDescription struct using 0 as a wildcard for type, subtype, and manufacturer. Pass that to AudioComponentFindNext:
AudioComponentDescription acd = { 0 };
AudioComponent comp = nullptr;
while((comp = AudioComponentFindNext(comp, &acd)) {
// Found an AU
}
Here is some relevant documentation from the header:
#function AudioComponentFindNext
#abstract Finds an audio component.
#discussion This function is used to find an audio component that is the closest match
to the provided values.
#param inComponent
If NULL, then the search starts from the beginning until an audio
component is found that matches the description provided by inDesc.
If non-NULL, then the search starts (continues) from the previously
found audio component specified by inComponent, and will return the next
found audio component.
#param inDesc
The type, subtype and manufacturer fields are used to specify the audio
component to search for. A value of 0 (zero) for any of these fields is
a wildcard, so the first match found is returned.
#result An audio component that matches the search parameters, or NULL if none found.
Simply use the provided AVAudioUnitComponentManager components function to get audio units.
It will return an array of audio units that match the AudioComponentDescription you pass.
Command click AudioComponentDescription and kAudioUnitType_MusicDevice to see the various values you can use.
// Exemple to get instruments audio units
var match = AudioComponentDescription()
match.componentType = kAudioUnitType_MusicDevice
let audioUnitComponents = AVAudioUnitComponentManager.shared().components(matching: match)

Find DeviceInterface (SP_DEVICE_INTERFACE_DATA) for DeviceInfo (SP_DEVINFO_DATA)

I am trying to communicate with a USB printer using c-function CreateFile and therefore i need the device path. I know that i can get the device path by SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetail, but for SetupDiEnumDeviceInterfaces i need to give an InterfaceClassGuid as third parameter which I don't know.
My current approach is:
OpenPrinter with the "user friendly" name of the Printer
GetPrinterDataEx with "PnpData" and "DeviceInstanceId" as parameters 2 and 3 which gives me the DeviceInstanceId
ClosePrinter
SetupDiCreateDeviceInfoList (with NULL-parameters)
SetupDiOpenDeviceInfo with the DeviceInstanceId obtained in step 2. Now I have the DeviceInfo of the printer
CM_Get_Parent with the DevInst of the printer (obtained in step 5).
CM_Get_Device_ID of the parent (obtained in step 6)
SetupDiOpenDeviceInfo with the device id obtained in step 7. Now I have the DeviceInfo of the USB-Interface (but not the interface itself) and am almost at the end.
The only missing thing is to get the device interface (SP_DEVICE_INTERFACE_DATA) when I have the SP_DEVINFO_DATA. The other way would be easy: Having the SP_DEVICE_INTERFACE_DATA, I could call SetupDiGetDeviceInterfaceDetail, so basically I am looking for the opposite function of SetupDiGetDeviceInterfaceDetail.
If it would be possible to enumerate ALL interfaces without having to know the InterfaceClassGuid, I could iterate through the list of interfaces and look for the one that is pointing to my device, but unfortunately, this is not possible.
The following articles were very helpful on my way:
Figuring which printer name corresponds to which device ID AND
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/51449be7-a4fa-476b-8cd2-b8933bfa3294/enumerate-multifunction-printer-in-vc?forum=wdk
Am I missing something?
It's been awhile, so I imagine you already found the answer. I'll answer it anyway for someone who may find this question later. I believe the answer is to call SetupDiEnumDeviceInterfaces passing in your SP_DEVINFO_DATA as the second parameter. From the documentation:
A pointer to an SP_DEVINFO_DATA
structure that specifies a device information element in
DeviceInfoSet.
This parameter is optional and can be NULL. If this parameter is
specified, SetupDiEnumDeviceInterfaces constrains the enumeration to
the interfaces that are supported by the specified device. If this
parameter is NULL, repeated calls to SetupDiEnumDeviceInterfaces
return information about the interfaces that are associated with all
the device information elements in DeviceInfoSet. This pointer is
typically returned by SetupDiEnumDeviceInfo.

In OS X (lion) how can I find whether a key combination is in use as a keyboard shortcut?

I want to put a bunch of keyboard shortcuts in my app (OS X lion) so I can do most things from the keyboard. There are of course a bunch of lists of hot key combos in use already, including the one in the HIG.
Is there some utility that can be used to type a key combination and find out if it already means something (either globally, or mac standard -- I'm not too worried about reusing some special combo used by another app -- or should I be?)?
You can use Carbon to do this. Don't be afraid to use Carbon here, there is no Cocoa way to get this information and the Carbon methods are still supported.
The CopySymbolicHotKeys() function returns an array of dictionaries, containing information about the system-wide symbolic hot keys defined in the Keyboard preferences pane. Each dictionary contains information about a single hot key.
Specifically, each dictionary has three keys:
kHISymbolicHotKeyCode: The virtual key code of the hot key, represented as a CFNumber.
kHISymbolicHotKeyModifiers: The hot key’s keyboard modifiers, represented as a CFNumber.
kHISymbolicHotKeyEnabled: The enabled state of the hot key, represented as a CFBoolean.
Obviously these are raw key codes so you will need to do some work if you want to see what the key codes actually refer to.
Note that the array doesn't contain custom, application-specific hotkeys, but this is a minor problem.
Here's a simple example:
#import <Carbon/Carbon.h>
CFArrayRef registeredHotKeys;
if(CopySymbolicHotKeys(&registeredHotKeys) == noErr)
{
CFIndex count = CFArrayGetCount(registeredHotKeys);
for(CFIndex i = 0; i < count; i++)
{
CFDictionaryRef hotKeyInfo = CFArrayGetValueAtIndex(registeredHotKeys, i);
CFNumberRef hotKeyCode = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyCode);
CFNumberRef hotKeyModifiers = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyModifiers);
CFBooleanRef hotKeyEnabled = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyEnabled);
NSLog(#"key code: %# modifiers: %# enabled: %#", hotKeyCode, hotKeyModifiers, hotKeyEnabled);
}
//you MUST release the dictionary when finished with it
CFRelease(registeredHotKeys);
}
Remember that you'll need to add the Carbon framework to the Link Binary with Libraries build phase in your project settings.
For more information you should look at the Carbon Event Manager docs (11Mb PDF).
Thear used to be an API in Carbon to get the global keyboard shortcuts, however, I do not believe there is a Cocoa API for this. I don't think you should worry about other third party apps, but you could refer to http://support.apple.com/kb/HT1343 and just hard code to avoid those. He that helps.

Resources