UsbDevice.FromIdAsync returning null in UWP app - windows

I'm currently working on an UWP app which includes USB communication with a custom USB device. I was able to set up a communication channel between a Raspberry Pi 3b and the device and sent some bytes back and forth. It does not work if I run this app on a local machine (Windows 10 build 1809) instead. In this case the call to UsbDevice.FromIdAsync always returns NULL.
I saw some related questions here, here and here with the similar or even the same problem. But none of the solutions mentioned are working for me.
I installed the Win USB driver using following inf-file:
;
; Installs WinUsb
;
[Version]
Signature = "$Windows NT$"
Class = USBDevice
ClassGUID = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider = %ManufacturerName%
CatalogFile = WinUSBInstallation.cat
DriverVer = 12/12/2016,13.54.20.543
[Generic.Section.NTamd64]
%USB\MS_COMP_WINUSB.DeviceDesc% = WINUSB,USB\MS_COMP_WINUSB
; ========== Manufacturer/Models sections ===========
[Manufacturer]
%ManufacturerName% = Standard,NTamd64
[Standard.NTamd64]
%DeviceName% = USB_Install, USB\VID_0483&PID_0001
; ========== Class definition ===========
[ClassInstall32]
AddReg = ClassInstall_AddReg
[ClassInstall_AddReg]
HKR,,,,%ClassName%
HKR,,NoInstallClass,,1
HKR,,SilentInstall,,1
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,,LowerLogoVersion,,5.2
; =================== Installation ===================
[USB_Install]
Include = winusb.inf
Needs = WINUSB.NT
[USB_Install.Services]
Include = winusb.inf
Needs = WINUSB.NT.Services
[USB_Install.HW]
AddReg = Dev_AddReg
[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
; =================== Strings ===================
[Strings]
ManufacturerName = "Manufacturer"
ClassName = "Universal Serial Bus devices"
DeviceName = "Device"
REG_MULTI_SZ = 0x00010000
The device shows up properly in the device manager without any errors.
I added the device capabilities to the Package.appxmanifest as follows:
<Capabilities>
<DeviceCapability Name="usb">
<Device Id="vidpid:0483 0001">
<Function Type="classId:ff 00 00"/>
<Function Type="name:vendorSpecific"/>
</Device>
</DeviceCapability>
</Capabilities>
And in my code I try to open the device as follows:
byte deviceClass = 0xff;
byte deviceSubclass = 0x00;
var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(
Windows.Devices.Usb.UsbDevice.GetDeviceClassSelector(
new Windows.Devices.Usb.UsbDeviceClass() {
ClassCode = deviceClass,
SubclassCode = deviceSubclass
}
)
);
UsbDevice device = null;
var numDevices = myDevices.Count;
foreach (var d in myDevices) {
device = await UsbDevice.FromIdAsync(d.Id);
if (device == null) {
// Device could not be found.
}
else {
// Found device.
}
}
The call to FindAllAsync does find a single device which has the correct id. But calling FromIdAsync always returns NULL. As mentioned before this all works on a Raspberry Pi 3b but not locally on my desktop machine or any other machine I tried out.
I searched for a few days now and I don't know what I'm still overlooking or missing. Any suggestions what else I can do?
Best regards

Related

How to use the DIO SPI on ESP32 with espidf?

I'm trying to use the DIO SPI mode on the ESP32 with the espidf (version 4.4).
But I encountered problems.
I have a ram device (ref 23LC1024) than can be accessed with several modes (single, dual, quad).
The single mode works perfectly (can write and read back)
The dual mode creates problems.
Here is how I configure the SPI bus (same setup for single or dual mode)
memset(&config, 0, sizeof(spi_bus_config_t));
config.mosi_io_num = MOSI_PIN;
config.miso_io_num = MISO_PIN;
config.sclk_io_num = SCLK_PIN;
config.quadwp_io_num = -1; // -1 not used
config.quadhd_io_num = -1; // -1 not used
config.flags = SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_MASTER;
spi_bus_initialize(VSPI_HOST, &config, SPI_DMA_DISABLED); // 0 DMA not used
Now the setup for the device (same setup for single mode or dual):
spi_device_interface_config_t devcfg = {
.clock_speed_hz = freq,
.command_bits = 8,
.address_bits = 24,
.dummy_bits = 8,
.mode = 0, // SPI MODE 0
.flags = 0,
.spics_io_num = _cs,
.queue_size = 1,
.pre_cb = NULL,
.post_cb = NULL};
ESP_ERROR_CHECK(spi_bus_add_device(VSPI_HOST, &devcfg, &data_Ram));
Now the setup for the transaction:
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.cmd = WRITE;
t.tx_buffer = data;
t.rx_buffer = NULL;
t.addr = address;
t.length = size * 8;
if (USE_DIO) // configure these flags in case of DIO
t.flags = SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MULTILINE_CMD;
ESP_ERROR_CHECK(spi_device_transmit(data_Ram, &t)); // Transmit!
It works nicely in the single mode but with the dual mode I got the error:
E (1618) spi_master: check_trans_valid(699): Incompatible when setting to both multi-line mode and half duplex mode
Does it mean I cannot use DIO in half duplex mode with the SPI master library?
Is there something I should change in my setup ?
I tried to specify the SPI_DEVICE_HALFDUPLEX flag in the spi_device_interface_config_t. Does not help.
Unfortunately I did not find any example on internet.
Thanks for your heads up!
E (1618) spi_master: check_trans_valid(699): Incompatible when setting to both multi-line mode and half duplex mode means that you cannot use MISO and MOSI for transfering (multiline) AND use them at the same time (full duplex).
Set your device to half duplex to fix the problem:
spi_device_interface_config_t devcfg = {
.flags = SPI_DEVICE_HALFDUPLEX,
...
};
In my experience, SPI_TRANS_MULTILINE_ADDR doesn't work, at least with spi_device_transmit.
If your ram device allows it, try without the "multilined" address and command.

DnsServiceRegister API issue

I'm trying to use the Windows 10+ API DnsServiceRegister to register a web server to be discoverable.
DNS_SERVICE_REGISTER_REQUEST rd = {};
DNS_SERVICE_INSTANCE di = {};
rd.pServiceInstance = &di;
rd.unicastEnabled = 0;
di.pszInstanceName = L"Remote Control._http._tcp.local";
di.pszHostName = L"192.168.10.6";
IP4_ADDRESS i4 = {};
InetPton(AF_INET, L"192.168.10.6", (void*)&i4);
di.ip4Address = &i4;
di.wPort = (WORD)12345;
rd.Version = DNS_QUERY_REQUEST_VERSION1;
rd.pRegisterCompletionCallback = [](DWORD Status,
PVOID pQueryContext,
PDNS_SERVICE_INSTANCE pInstance)
{
nop();
};
DnsServiceRegister(&rd, 0);
The call succeeds (return value DNS_REQUEST_PENDING as per documentation) and after a while, my callback is called with status = 0 (Success?). However, no UPnP tools detect my service.
When I set unicast to 1, status is 9002 (error).
What am I missing in using this API?
Edit: When the callback is called, the pInstance parameter there points to a DNS_SERVICE_INSTANCE with ip4Address and ip6Address null pointers. Why?
Edit: It's discoverable by using DnsServiceBrowse(). But UPnP scan tools don't discover it.

Windows Network Device Driver: Set link UP/DOWN from within the driver

I am writing a network driver for Windows. I want to do something like the pseudocode below:
Init_interface_link_status = disconnected (Equivalent to DOWN in Linux)
Repeat using delayed workitem:
if (condition is true)
interface_link_status = connected (UP)
break
else
interface_link_status = disconnected (DOWN)
All this happens inside the driver code.
I am using Windows Driver Samples as reference. I have found something that looks promising: https://github.com/microsoft/Windows-driver-samples/blob/master/network/ndis/netvmini/6x/adapter.c#L353
AdapterGeneral.MediaConnectState = HWGetMediaConnectStatus(Adapter);
I can set this MediaConnectSate to MediaConnectStateDisconnected here and the driver initialises in Disconnected state which is what I want.
But I can't find a way to change this state elsewhere after the driver is initialised.
Found inspiration from a proprietary network driver code.
This function turns interface on/off:
VOID NSUChangeAdapterLinkState(
_In_ PMP_ADAPTER Adapter,
_In_ BOOLEAN TurnInterfaceUP)
/*++
Routine Description:
Change Adapter Link's state. This is equivalent to doing ifup/ifdown on Linux.
Arguments:
Adapter - Pointer to our adapter
TurnInterfaceUP - Pass TRUE to turn interface UP, FALSE to turn DOWN
Return Value:
None
--*/
{
NDIS_LINK_STATE LinkState;
NDIS_STATUS_INDICATION StatusIndication;
RtlZeroMemory(&LinkState, sizeof(LinkState));
LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
LinkState.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
if (TurnInterfaceUP)
{
LinkState.MediaConnectState = MediaConnectStateConnected;
MP_CLEAR_FLAG(Adapter, fMP_DISCONNECTED);
} else
{
LinkState.MediaConnectState = MediaConnectStateDisconnected;
MP_SET_FLAG(Adapter, fMP_DISCONNECTED);
}
LinkState.RcvLinkSpeed = Adapter->ulLinkRecvSpeed;
LinkState.XmitLinkSpeed = Adapter->ulLinkSendSpeed;
LinkState.MediaDuplexState = MediaDuplexStateFull;
RtlZeroMemory(&StatusIndication, sizeof(StatusIndication));
StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
StatusIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
StatusIndication.SourceHandle = Adapter->AdapterHandle;
StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
StatusIndication.StatusBuffer = &LinkState;
StatusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE);
NdisMIndicateStatusEx(Adapter->AdapterHandle, &StatusIndication);
}

wvdial, pppd and default route metric

I have this in wvdial.conf:
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0
Modem Type = USB Modem
Phone = *99#
New PPD = yes
ISDN = 0
Username = foo
Init1 = ATZ
Password = foo
Modem = /dev/ttyUSB1
Baud = 9600
Stupid Mode = 0
#Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CFUN=1
Init4 = AT+CGDCONT=1,"ip","internet"
Auto Reconnect = on
(PIN disabled)
This is working for 4G USB Dongle Huawei E3131 # T-mobile.pl.
And now I have 2 questions:
1 How to translate this config to /etc/conf.d/net for connect as net.ppp1 (Gentoo) (I would connecting without wvdial)
2 After connecting I get default route with metric 0, How to change metric to say 100? (I'm interested in setting metric for both wvdial & pppd way)

Symbol Device Kill Process

I'm trying to see how many instances of an application are running on a MC65 device, a Windows Mobile 6.5 device. Then if there is more than one instance of the application running kill all instances and run the application. I've tried that code here. But it doesn't work on the MC65 device. I believe this is because it is a symbol device and I've read somewhere that they act differently than non-symbol devices.
Does anyone know how to find out what processes are running on a symbol device programatically?
Update: Upon further testing the device is having problems creating a snapshot of the running processes. Still haven't found a solution.
Taking a snapshot should work fine BUT you have to use a flag to avoid memory limitations throwing an exception:
[Flags]
private enum SnapshotFlags : uint
{
HeapList = 0x00000001,
Process = 0x00000002,
Thread = 0x00000004,
Module = 0x00000008,
Module32 = 0x00000010,
Inherit = 0x80000000,
All = 0x0000001F,
NoHeaps = 0x40000000
}
Then in a normal call to CreateToolhelp32Snapshot you can get a list of processes:
public static Dictionary<UInt32, process> getProcessNameList()
{
int iCnt = 0;
//List<processnames> name_list = new List<processnames>();
Dictionary<UInt32, process> _pList = new Dictionary<uint, process>();
uint procID = 0;
IntPtr pHandle = CreateToolhelp32Snapshot(SnapshotFlags.Process | SnapshotFlags.NoHeaps, procID);
if ((Int32)pHandle == INVALID_HANDLE_VALUE)
throw new Exception("CreateToolhelp32Snapshot error: " + Marshal.GetLastWin32Error().ToString());
if ((int)pHandle != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pEntry = new PROCESSENTRY32();
pEntry.dwSize = (uint)Marshal.SizeOf(pEntry);
if (Process32First(pHandle, ref pEntry) == 1)
{
do
{
//name_list.Add(new processnames(pEntry.th32ProcessID, pEntry.szExeFile));
_pList[pEntry.th32ProcessID] = new process(pEntry.th32ProcessID, pEntry.szExeFile, new List<thread>());
iCnt++;
} while (Process32Next(pHandle, ref pEntry) == 1);
}
else
System.Diagnostics.Debug.WriteLine("Process32First error: " + Marshal.GetLastWin32Error().ToString());
CloseToolhelp32Snapshot(pHandle);
}
return _pList;
}
The above code is part of my remote ProcessorUsage test application.
Nevertheless normal windows mobile application will terminate them self if a previous instance is already running. That is also the default when you create and run a SmartDevice project in CSharp or CPP targetting "Windows Mobile ...".
If you target a Standard Windows CE based SDK, there is no automatic code generated to prevent multiple instances in the start code of the app.
Let us know, if you still need assistance.

Resources