libudev udev_device_get_sysattr_value() return NULL for idVendor/idProduct when device is removed - linux

I'm trying to implement USB monitor service/daemon to detect specfic PID/VID device only. I can easily detect device 'add' action attrib by filtering PID/VID but when I remove ANY USB device from port then as part of 'remove' action attrib, I try to filter PID/VID same like in 'add' action ... by using
const char* vendor = udev_device_get_sysattr_value(dev, "idVendor");
const char* product = udev_device_get_sysattr_value(dev, "idProduct");
but in above two char ptr I always get NULL.
Due to this my remove action will execute for all USB device which will remove from port
Is their any other way in libudev API to detect specific device remove only ?

Once the USB device is at the "remove" action, udev_device_get_sysattr_value(dev) will return NULL in my experience. Even the prior "unbind" action is too late.
One way to detect the removal of a specific device is to store its dev node when it is inserted.
First, find the udev_device* you want to monitor by enumerating the devices (struct udev_enumerate*)(device already plugged in) and monitoring the "add" or "bind" action.
In those states, the udev_device_get_sysattr_value will return the correct strings as you have already seen. If the values match the ones for the device you want to monitor, retrieve its current dev node by calling udev_device_get_devnode(dev). Store that dev node value (strdup to make a copy of it).
In the "unbind" or "remove" action, udev_device_get_devnode(dev) will still return the proper value as opposed to udev_device_get_sysattr_value(dev, prop_name). Match the dev_node with the previously stored dev node to identify that the action applies to the device you are monitoring.
Note that the dev node will likely change every time the device is inserted.

Related

Web Bluetooth - Show extra info on scanning dialog

I'm trying to support web-bluetooth to connect to my devices and perform a simple task (such as playing LED).
However, the device information showed on the scanning dialog when calling navigator.bluetooth.requestDevice is not so clear. It only shows the device name and a random (?) hex string.
The problem here is all my devices have the same name (AWESOME_LED), thus it's not easy for the user to select the correct LED if all scanning items show the same device name info. As far as I know, we can not custom to add more info showing on the scanning dialog.
I come up with a new solution that is changing the device name to unique for each LED with the format AWESOME_LED + [uniqueid] e.g AWESOME_LED1, AWESOME_LED2, AWESOME_LED3 so that the user can distinguish one from the others.
My question are:
Is there any alternative solution without making the device name unique?
If not, is there any problem / rejection / limitation from Apple or Google for my current app on App Store / Google Play by not using the same device name for all devices? I have been investigating it at Apple forums / Accessory Design Guidelines and looks like there are no problems, just to make sure if anyone has faced trouble from Apple / Google.
Thanks for your help.
Scanning dialog
My question are:
Is there any alternative solution without making the device name unique?
The browser prompt is not customisable yet. One solution you highlighted already is to make your LED device name unique. If you're able to control the device, why not having one AWESOME_DEVICE name and a GATT characteristic you can write to that controls individual LED colors. Maybe something like:
const device = await navigator.bluetooth.requestDevice({
filters: [{ name: "AWESOME_DEVICE" }],
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(0x1234); // Your service UUID
const characteristic = await service.getCharacteristic(0x5678); // Your characteristic UUID
// Set LED #1 to red color.
await characteristic.writeValue(
new Uint8Array(/*ledIndex=*/ 1, /*r=*/ 255, /*g=*/ 0, /*b=*/ 0)
);
If not, is there any problem / rejection / limitation from Apple or Google for my current app on App Store / Google Play by not using the
same device name for all devices? I have been investigating it at
[Apple forums][1] / [Accessory Design Guidelines][2] and looks like
there are no problems, just to make sure if anyone has faced trouble
from Apple / Google.
None that I'm aware of.

How the function works cdev_add()?

Do I understand correctly that when the structure is initialized
struct dev_t dev;
dev = MKDEV(major,minor_first);
I create only the device file, it's right to say - to the node. Next, should I indicate how I will work with this device? To do this, you need the function
cdev_add(&my_ch_dev, dev, minor_count);
after
cdev_init(&my_ch_dev ,&dev_fops);
So, I mean that my driver will work with the created node as a character device? Thanks in advance!
Here is the details how it works
dev = MKDEV(major,minor_first);
Still kernel doesn't know whether we selected major/minor number or not, so for this you need to register he device by calling register_chrdev_region()
register_chrdev_region(dev,minor_count,"AYRAT_DEVICE"); so till now number(major/minor) has reserved the name(dev) so that other driver will not get the same name. Next you need to register your driver with kernel.
register with cdev by calling cdev_init(&my_ch_dev ,&dev_fops); Next you need to inform to kernel that we filled all member of struct cdev, so for this use cdev_add().
cdev_add(&my_ch_dev, dev, minor_count);

CallKit no sound when answer second call and put first call on hold

I am facing issue with multiple calls when start using CallKit in my VOIP application.
When there is one to one VOIP call, sound is working fine. But once one party gets another VOIP call, and choose to Hold and Accept option; First call is put on hold successfully and second call is answered; But sound gets closed now. Even swapping between calls also does not work. and Dropping one call also does not work.
I am using RTP for voice.
I tried to put breakpoints and check if the AVAudioSession's category and mode are correct.
In the console I can check at my end that the device which has more than one calls, stop sending sound packets.
I am enabling VOIP just before reportNewIncomingCallWithUUID and CXStartCallAction of Provider.
Same case with GSM call. If there is one to one VOIP call with sound is ok and GSM call is received at one side and user choose to Hold and Accept option, sound in GSM call is working fine. But if user makes VOIP call as active and put GSM call on hold by swapping calls, there is no sound in VOIP call. Swapping calls and making GSM call active, sound again works fine. But no sound for VOIP call.
In this case, we are getting AVAudioSessionInterruptionTypeBegan but AVAudioSessionInterruptionTypeEnded is never called. Even after the GSM call is ended.
Has anyone run into similar issues?
Had the same issue. If I have 1 active call, then new calls is incoming, I tap hold&accept. New call works, but after using Swap in CallKit audio stopped working.
After long debug found the spot where actually audio is deactivating/activating for Swap calls via CallKit native interface - that is provider:performSetHeldCallAction: method from CXProviderDelegate protocol.
In my case I used the [audioController deactivateAudioSession] method for the call was putting in OnHold.
But I found that the same method provider:performSetHeldCallAction: was fired for other call that is being put active (from OnHold state), when tap Swap button via CallKit.
So in my case I first toggle hold for call (it put call either on hold or put it active out of hold).
Then I check what is call condition (whether hold or not) and then deactivate or activate audio respectively.
In common way it looks this way:
- (void)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAction *)action {
SomeCallClass *call = [self.callManager callWithUUID:action.callUUID];
if (!call) {
[action fail];
return;
}
NSError *holdError;
[call toggleHold:&holdError];
if (holdError) {
[action fail];
} else {
if (call.onHold)
[self.audioController deactivateAudioSession];
else
[self.audioController activateAudioSession];
[action fulfill];
}
}
This code should be in the class that works as a CallKit provider delegate.

App Inventor 2: Not finding a specific block

In the App Inventor 2, where is the block mentioned in last item (figure) of the url: http://beta.appinventor.mit.edu/learn/reference/blocks/definition.html
I am trying to use bluetooth to connect my custom device with Android App.
The internet says:
This block provides a "dummy socket" for fitting a block that has a
plug on its left into a place where there is no socket, such as one of
the sequence of blocks in the do part of a procedure or an if block.
The block you fit in will be run, but its returned result will be
ignored. This can be useful if you define a procedure that returns a
result, but want to call it in a context that does not accept a
result.
You are looking for the evaluate but ignore result block
However in your bluetooth connecting example let me recommend you to use an if statement instead
if BluetoothClient1.connect ...
then do something
else display a message, e.g. "connection was not successful"
see also this bluetooth example
and see the documentation of the Bluetooth components
boolean Connect(text address)
Connect to the Bluetooth device with the specified address and the Serial Port Profile (SPP).
Returns true if the connection was successful.

How can I select an audio output device in directshow

I was wondering how I can select the output device for audio in directshow. I am able to get available audio output devices in directshow. But how can I make one of these to be audio output device. Its always going for the default audio device. I want to be able to output audio on my choice of device. I have been struggling through google but couldn't find anything useful. All I could get was this link but it doesn't really solve my problem.
Any help will be really helpful for me.
First off, if you're not using DirectShow .NET (DirectShowLib), get that here: It serves as a (very complete) interface between unmanaged DirectShow and C#
What follows is a pretty simple example of how to play an audio file, to the desired audio device
using DirectShowLib;
private IGraphBuilder m_objFilterGraph = null;
private IBasicAudio m_objBasicAudio = null;
private IMediaControl m_objMediaControl = null;
private void playAudioToDevice(string fName, int devIndex)
{
object source = null;
DsDevice[] devices;
devices = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory);
DsDevice device = (DsDevice)devices[devIndex];
Guid iid = typeof(IBaseFilter).GUID;
device.Mon.BindToObject(null, null, ref iid, out source);
m_objFilterGraph = (IGraphBuilder)new FilterGraph();
m_objFilterGraph.AddFilter((IBaseFilter)source, "Audio Render");
m_objFilterGraph.RenderFile(fName, "");
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
m_objMediaControl = m_objFilterGraph as IMediaControl;
m_objMediaControl.Run();
}
It is up to user to manage audio devices and choose a primary device (such as via Control Panel applet). You can find ways to switch devices programmatically in Windows XP, however in Vista+ it is impossible without interactive user action by design.
See also Larry's answer here: How to change default sound playback device programmatically?
UPDATE: The mentioned above refers to modifying system configuration trying to alter default audio output device. An application is however not limited to default device only. Instead, it can enumerate available devices (see Using the System Device Enumerator + CLSID_AudioRendererCategory) and then create an instance of renderer for specific device with BindToObject call. From there on, it is a regular filter, just bound internally to device of interest.

Resources