How to get filtered target device information from windows upper class filter - driver

I'm writing a upper class filter for WPD device. I specified the callback functions for the Read/Write/Ioctl, from the callback declaration I could get the WDFQueue, WDFRequest.
VOID WdfFltrDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode)
But from the parameter Queue or Request, I could only get the information of device which is created by my driver. Is there any way to retrieve the informations of the attached devices which my driver is currently filtering?(e.g. From the kernel log I can see the ioctl request to my android device, but I don't know how to get the android device object to get the device name)

You are really should be able to get information about your WPD device request using parameters of this method. If you are not, probably your code or .inf filter setup is wrong.
You can use this code snippet to check what device you are filtering now:
WDFDEVICE device = WdfIoQueueGetDevice(Queue);
WCHAR id[255];
ULONG resultLength;
NTSTATUS status = WdfDeviceQueryProperty(device, DevicePropertyHardwareID, sizeof(id), id, &resultLength);
if(NT_SUCCESS(status))
{
//check the device id here
}
Or, if you prefer some another parameter, you could find the list here

Related

What devices does CBCentralManager.retrieveConnectedPeripherals() return?

I want to check which Bluetooth Devices my iPhone is connected to. In order to do that, I use CBCentralManager.retrieveConnectedPeripherals() like this:
let connectedPerphs = centralManager.retrieveConnectedPeripherals(withServices: []);
My problem is that even if my iPhone is connected to a BluetoothDongle (it explicitly says "connected" in the settings), the list that is returned by retriveConnectedPeripherals() is always empty. Am I using the method in a wrong way or can it not be used to detect a bluetooth connection such as the connection to to my dongle? If the latter is the case, how can I detect that connection?
Let me clear, centralManager.retrieveConnectedPeripherals always return empty or nil value, If you are not passing any value into serviceUUIDs
retrieveConnectedPeripherals(withServices:)
Returns a list of the peripherals (containing any of the specified
services) currently connected to the system.
serviceUUIDs:
A list of service UUIDs (represented by CBUUID objects).
Update:
Unfortunately this the long way to do it. You can create Array of CBUUID statically then you can pass it to the method. Please refer below code.
let aryUUID = ["1800","18811"]
var aryCBUUIDS = [CBUUID]()
for uuid in aryUUID{
let uuid = CBUUID(string: "1800")
aryCBUUIDS.append(uuid)
}
let connectedPerphs = centralManager.retrieveConnectedPeripherals(withServices: aryCBUUIDS)
List of available services
First, this works only with BLE devices, thus if your dongle is using a common BT you will not get it from here, but probably using EAAccessoryManager var connectedAccessories: [EAAccessory] method, but as far as I know your app must comply to MFI.
That is why is asking which service your devices are exposing as a filter.

GetDescriptor() null value / 128-bit UUID descriptor?

I'm writing my code using Xamarin. I'm developing my IOS app which allows me to read the BLE devices, Services, characteristic value and activation of the notification.
My BLE beacon have one custom Services that contain two custom characteristics and both have the notification implemented using CCCD.
My ble devices work correctly I test it with BLE scanner app and it working well without any problem.
I can read value and I can active the notification for both characteristic. See picture here.
The app that I wrote using xamarin work correctly (reading services, characteristic value....) the only problem that didn't work is the activation of the notification. Here's a portion of the code :
public UUID Charac_UUID0 = UUID.FromString("0000beef-1212-efde-1523-785fef13d123");
public UUID Charac_UUID = UUID.FromString("0000b1e0-1212-efde-1523-785fef13d123") ;
public UUID Descr_UUID = UUID.FromString("00002902-1212-efde-1523-785fef13d123");
protected BluetoothGattCharacteristic _charac;
....
....
this._charac = App.Current.State.SelectedService.GetCharacteristic(Charac_UUID0);
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].SetCharacteristicNotification(_charac, true);
BluetoothGattDescriptor descriptor = _charac.GetDescriptor(Descr_UUID0);
descriptor.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].WriteDescriptor(descriptor);
The code always give me an error at descriptor.SetValue and it indicate me that the descriptor is NULL meaning that _charac.GetDescriptor didn't return any value.
I suspect the Descriptor UUID value (Descr_UUID) is not correct. I don't know excatly how can I determine the Descr_UUID but I saw many example in the internet of people replacing the custom UUID of the caracteristic by 2902 which give me in my case a 128 descriptor UUID equal to 00002902-1212-efde-1523-785fef13d123.
But there is a problem here. The descriptor UUID for both characteristic will be the same because the base UUID is the same for both characteristic?
Any solution?
3 years later im sure you figured it out but, 2902 is the 16 bit value for a Client Characteristic Configuration Descriptor, and I believe it should also be inflated using the "BASE UUID" not just whatever your characteristic descriptor uses. See this: answer
This will convert your 16 (or 32) bit uuids to full 128 bit uuids using the BASE UUID:
public static UUID ConvertUuid(uint uuid)
{
const long msbMask = 0x0000000000001000;
const ulong lsb = 0x800000805f9b34fb;
var msb = msbMask | ((ulong)(uuid & uint.MaxValue) << 32);
return new UUID((long)msb, unchecked((long)lsb));
}

Xamarin: Detect network/host reachability

I'm experimenting with "Reachability" in Xmarin, using the Reachability class (sample here), but I cannot get the "IsHostReachable" feature to work.
I do realize that the Reachability class utilizes the NetworkReachability class but no matter which class I use the TryGetFlags() method always passes back the NetworkReachabilityFlags argument with a zero (0) value.
I started out using the Reachability class' method but while debugging I saw that the problem seems to originate in NetworkReachability. I tried the following code just to make sure:
using (var r = new NetworkReachability(host))
{
NetworkReachabilityFlags flags;
if (r.TryGetFlags(out flags)) // <-- flags is always 0 (zero)
return (flags & NetworkReachabilityFlags.Reachable) == NetworkReachabilityFlags.Reachable;
return false;
}
Like I said the flags variable is passed back with a zero (0) value, regardless of the device's current connection status. The host I'm testing against is a intranet web app that is only available when I'm on my company's WIFI. I have tested debuging the iPhone while connected and double checked by simply trying to browse to the host in Safari, which works.
The API is poorly documented but I'm suspecting I might need to initialize the NetworkReachability class somehow.
Any ideas?

How to trigger a DMA operation on PCI sound card

I'm a newbie to driver development in Linux. I want to trigger a DMA read operation at specified target address, but I have no basic concept about how to do it. Should I write a new driver for my sound card? Or just invoke some APIs(if any) provided by current sound card driver?
I can imagine that what I want looks like this (from LDD3 Ch15),
int dad_transfer(struct dad_dev *dev, int write, void *buffer,
size_t count)
{
dma_addr_t bus_addr;
/* Map the buffer for DMA */
dev->dma_dir = (write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
dev->dma_size = count;
bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count,
dev->dma_dir);
dev->dma_addr = bus_addr;
/* Set up the device */
writeb(dev->registers.command, DAD_CMD_DISABLEDMA);
writeb(dev->registers.command, write ? DAD_CMD_WR : DAD_CMD_RD);
writel(dev->registers.addr, cpu_to_le32(bus_addr));
writel(dev->registers.len, cpu_to_le32(count));
/* Start the operation */
writeb(dev->registers.command, DAD_CMD_ENABLEDMA);
return 0;
}
But what should this be, a user-space program or a module? And where can I grub more device-specific details in order to know which and how the registers should be write?
You have several questions buried in here, so I will take them one at a time:
Should I write a new driver or invoke some API function calls?
If the existing driver has such a function accessible from userspace, yes you should use them - they will the easiest option. If they do not already exist, you will have to write a driver because you cannot directly access the kernel's DMA engine from userspace. You need a driver to help you along.
Should this be a userspace program or module?
It would have to be a module so that it can access low-level kernel features. Using your included code as an example, you cannot call "dma_map_single" from userspace or access a PCI device's device structure. You need to be in kernel space to do that, which requires either a driver module or static kernel driver.
Where can I get more device-specific details?
(I assume you meant Grep.) You will have to get a hold of a programmer's guide for the device you want to access. Regular user's manuals won't have the level of detail you need (register addresses, bit patterns, etc) so you may have to contact the manufacturer to get a driver writer's guide. You also may be able to find some examples in the kernel source code. Check http://lxr.free-electrons.com/ for a searchable, up-to-date listing of the entire kernel source. If you look in /drivers/, you may be able to find some examples to get you started.

How do you retain uniqueness of virtual MIDI source from MIDISourceCreate()?

I'm working on a little hack sending MIDI messages from an app using RtMidi as a wrapper for CoreMIDI on OS X. I use RtMidiOut::openVirtualPort("MyAwesomePort") so I can select my app as an input source in a DAW.
However, if my program closes and I open it again, my DAW does not recognize the input device as the same port, despite being given the same name.
I was originally using pyrtmidi, so went and verified the behavior writing in C++ directly with RtMidi. "My DAW" in this case is Reaper 4, but I've duplicated the behavior in Pro Tools, Logic, and MuLab.
I know it's possible to retain some uniqueness of a virtual midi port, since MidiKeys behaves just as I'd like my application to behave: my DAWs remember it even if MidiKeys closes and re-opens while my DAW is still running.
So I dug into the RtMidi source, and the CoreMIDI wrapper seemed straightforward enough. All that the MIDISourceCreate asks for is a string. The client parameter is (what I presume after browsing the docs) an identifier for my application, it being a client of the CoreMIDI services.
void RtMidiOut :: openVirtualPort( std::string portName )
{
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
if ( data->endpoint ) {
errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";
error( RtError::WARNING );
return;
}
// Create a virtual MIDI output source.
MIDIEndpointRef endpoint;
OSStatus result = MIDISourceCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
&endpoint );
if ( result != noErr ) {
errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";
error( RtError::DRIVER_ERROR );
}
// Save our api-specific connection information.
data->endpoint = endpoint;
}
So I looked at the MIDISourceCreate documentation, and read this:
After creating a virtual source, it's a good idea to assign it the same unique ID it had the last time your application created it. (Although you should be prepared for this to fail in the unlikely event of a collision.) This will permit other clients to retain persistent references to your virtual source more easily.
This seems like exactly what I'm looking for. Except I have no idea how to assign the source a unique ID. The out parameter for MIDISourceCreate is a MIDIEndpointRef, which according to the docs is just typedef'd to a UInt32 down the line. So I hypothesized that maybe I should keep track of this UInt32, but that seems like a bad idea.
After digging through all of this I feel like I'm hitting a bit of a brick wall. How do I retain the uniqueness of my MIDI port in between runs of my application?
According to the docs,
kMIDIPropertyUniqueID
The system assigns unique ID's to all objects. Creators of virtual endpoints may set this property on their endpoints, though doing so may fail if the chosen ID is not unique.
So maybe something like this:
// Try to set the ID if it's saved.
if (savedUniqueId) {
OSStatus result = MIDIObjectSetIntegerProperty(endpoint, kMIDIPropertyUniqueID, myUniqueId);
if (result == kMIDIIDNotUnique) {
savedUniqueId = 0;
}
}
// If not saved, record the system-assigned ID
if (!savedUniqueId) {
OSStatus result = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &savedUniqueId);
// Handle the error?
}
The unique ID is typedefed to a SInt32. I've made the assumption that 0 is an invalid unique ID, which is at least true for connections (the docs for kMIDIPropertyConnectionUniqueID say it's "non-existant or 0 if there is no connection").
I'm not sure how you maintain long-term uniqueness with only 32 bits, but it'll hopefully be sufficient for relaunches of your app.

Resources