USBHIDManager HID, getReport() and setReport() On Mac Environment - cocoa

We are trying to communicate with a USB HIDDevice. This device is working fine in windows, where we can send a report and get a report back using WriteFile() and ReadFile().
On the Mac, we are trying to interface with the device using setReoprt() and getReport(). But getReport() is not returning any data, but an error.
What is the wrong in the application?

In order to make use of asynchronous behavior, the event source obtained using getAsyncEventSource must be added to a run loop.
The above note is part of the comment of setReport. U might need to learn the runloop mechanism of Runloop in Mac OS first.
Since it's impossible to explain the mechanism here. The following functions and orders might help u coding when u get familiar with RunLoop.(Try to search "CFRunLoop" in google)
CFRunLoopGetCurrent();
CFRunLoopRun();
CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef mode);
CFRunLoopStop(CFRunLoopRef rl);(i usually call this function in the callback method)

Related

How does GetCommState populate the DCB struct in Windows 10 when using usbser.sys CDC ACM driver

I am building a embedded device that will communicate to the outside world by virtual COM. I have the descriptor and all the callbacks for the USB set up correctly and COM is working - well kind of. The problem is that when I issue the GetCommState command for the COM I get a semi valid struct back and when one fixes only couple of parameters (like setting the speed and 8N1) and try to reconfigure the port by calling SetCommState the actions fails with: 'A device attached to the system is not functioning.'
If one continues to use the port it just work - all writes and reads - without a problem. But the issue is that most libraries try to reconfigure the port by first issuing the GetCommState and then SetCommState - pyserial and C# both do it in this way.
My question is where do the "default" configuration for COM comes form?
In the USB ACM CDC standard there are (optional) class requests for SET and GET COMM feature but I can see (from USB sniffer) that they are never called (I tried with capabilities for USB ACM CDC set to 0x06 (that is without SET/GET COMM) and 0x07 (with SET/GET COMM) but in no case I get a class request from the driver). So the driver must take the config from somewhere else, does anybody knows from where or how?
I am using an NXP LPC and Windows 10 with usbser.sys driver on other end.
What I already checked is:
compared the USB descriptor to the working one - they are the same
checked the USB traffic - the enumeration and communication looks the same
without doing GetCommState and SetCommState the COM is working without problem
I attached the content of the DCB struct for working sample (left) and my (right). I do not understand where do the marked values come from? Who sets them?
The settings should come from the port driver - you can view and set default values in the Windows Device Manager. In your case, it would seem that flow control with RTS/CTS is enabled (left picture), which might be something that your USB adapter uses internally. If it works, then leave those settings as they were.
I'd advise to do like this:
Always check the result of each API function you call!
Call CreateFile to get the port handle.
Optionally call GetCommTimeouts and store the result in a zero-initialized struct like COMMTIMEOUTS com_timeouts = {0};. Change members of the struct as needed, then call SetCommTimeouts.
Create an (almost) zero-initialized struct DCB dcb = { .DCBlength = sizeof(DCB) }.
Call GetCommState on this struct.
Set baudrate, parity, stop bits etc as required. Leave other members as they were.
Call SetCommState.

Interact with virtual serial device in polling mode in linux C

I'm trying to enable polling support for a serial over USB driver on an android kernel, so that I can debug it using kgdboc. I based myself on the code from these githubs:
https://github.com/dankex/kgdb-android
https://github.com/jacktang310/KernelDebugOnNexus6P
However, I can't find a way to enable and use char by char polling mode via a C program on userland. Which makes debugging very difficult, since the only thing I can do is to set kgdboc to /dev/ttyGS0 and then send "g" to sysrq-trigger, and pray it works.
In other terms, I need a userland program that triggers the code path which reaches the following operations on the tty_operations structure:
.poll_init = gs_poll_init,
.poll_get_char = gs_poll_get_char,
.poll_put_char = gs_poll_put_char,
Instead, whenever I write to /dev/ttyGS0 I trigger the "write" operation.
Any help will be greatly appreciated.
Thanks!
I ended up creating a driver that exports a sysfs node as Chris Stratton suggested.
I based myself on this tutorial

Why is WebViewControlProcess.CreateWebViewControlAsync() never completing?

I’m trying to write some Rust code that uses Windows.Web.UI.Interop.WebViewControl (which is a Universal Windows Platform out-of-process wrapper expressly designed so Win32 apps can use EdgeHTML), and it’s all compiling, but not working properly at runtime.
The relevant code boils down to this, using the winit, winapi and winrt crates:
use winit::os::windows::WindowExt;
use winit::{EventsLoop, WindowBuilder};
use winapi::winrt::roapi::{RoInitialize, RO_INIT_SINGLETHREADED};
use winapi::shared::winerror::S_OK;
use winrt::{RtDefaultConstructible, RtAsyncOperation};
use winrt::windows::foundation::Rect;
use winrt::windows::web::ui::interop::WebViewControlProcess;
fn main() {
assert!(unsafe { RoInitialize(RO_INIT_SINGLETHREADED) } == S_OK);
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new()
.build(&events_loop)
.unwrap();
WebViewControlProcess::new()
.create_web_view_control_async(
window.get_hwnd() as usize as i64,
Rect {
X: 0.0,
Y: 0.0,
Width: 800.0,
Height: 600.0,
},
)
.expect("Creation call failed")
.blocking_get()
.expect("Creation async task failed")
.expect("Creation produced None");
}
The WebViewControlProcess instantiation works, and the CreateWebViewControlAsync function does seem to care about the value it received as host_window_handle (pass it 0, or one off from the actual HWND value, and it complains). Yet the IAsyncOperation stays determinedly at AsyncStatus.Started (0), and so the blocking_get() call hangs indefinitely.
A full, runnable demonstration of the issue (with a bit more instrumentation).
I get the feeling that the WebViewControlProcess is at fault: its ProcessId is stuck at 0, and it doesn’t look to have spawned any subprocess. The ProcessExited event does not seem to be being fired (I attached something to it immediately after instantiation, is there opportunity for it to be fired before that?). Calling Terminate() fails as one might expect in such a situation, E_FAIL.
Have I missed some sort of initialization for using Windows.Web.UI.Interop? Or is there some other reason why it’s not working?
It turned out that the problem was threading-related: the winit crate was doing its event loop in a different thread, and I did not realise this; I had erroneously assumed winit to be a harmless abstraction, which it turned out not quite to be.
I discovered this when I tried minimising and porting a known-functioning C++ example, this time doing all the Win32 API calls manually rather than using winit, so that the translation was correct. I got it to work, and discovered this:
The IAsyncOperation is fulfilled in the event loop, deep inside a DispatchMessageW call. That is when the Completion handler is called. Thus, for the operation to complete, you must run an event loop on the same thread. (An event loop on another thread doesn’t do anything.) Otherwise, it stays in the Started state.
Fortunately, winit is already moving to a new event loop which operates in the same thread, with the Windows implementation having landed a few days ago; when I migrated my code to use the eventloop-2.0 branch of winit, and to using the Completed handler instead of blocking_get(), it all started working.
I shall clarify about the winrt crate’s blocking_get() call which would normally be the obvious solution while prototyping: you can’t use it in this case because it causes deadlock, since it blocks until the IAsyncOperation completes, but the IAsyncOperation will not complete until you process messages in the event loop (DispatchMessageW), which will never happen because you’re blocking the thread.
Try to initialize WebViewProcessControl with winrt::init_apartment(); And it may needs a single-threaded apartment(according to the this answer).
More attention on Microsoft Edge Developer Guide:
Lastly, power users might notice the apppearance of the Desktop App
Web Viewer (previously named Win32WebViewHost), an internal system app
representing the Win32 WebView, in the following places:
● In the Windows 10 Action Center. The source of these notifications
should be understood as from a WebView hosted from a Win32 app.
● In the device access settings UI
(Settings->Privacy->Camera/Location/Microphone). Disabling any of
these settings denies access from all WebViews hosted in Win32 apps.

How to find out caller info?

This will require some background. I am using Detours to intercept system calls. For those of who don't know what Detours is - it is a tool which redirects call to system functions to a detour function which allows us to do whatever we want to do before and after the actual system call is made. What I want to know is that if it is possible to find out somehow any info about the dll/module which has made this system call? Does any win32 api function help me do this?
Lets say traceapi.dll makes a system call to GetModuleFileNameW() inside kernel32.dll. Detour will intercept this call and redirect control to a detour function (say Mine_GetModuleFileNameW()). Now inside Mine_GetModuleFileNameW(), is it possible to find out that this call originated from traceapi?
call ZwQuerySystemInformation with first argument SystemProcessesAndThreadsInformation.
once you have the returned buf, typecast it to PSYTSTEM+PROCESS_INFORMATION and use its field to extract your info.
status = ZwQuerySystemInformation (
SystemProcessesAndThreadsInformation, buf, bufsize, NULL);
PSYSTEM_PROCESS_INFORMATION proc_info = (PSYSTEM_PROCESS_INFORMATION) buf;
proc_info->ProcessName, which is a UNICODE_STRING will give you the calling process name.
Please note that the structure and field I am talking about is not documented and might change in future release of windows. However, I am using it and it works fine on WIN XP and above.
I don't know how many stack frames will be on the stack that are owned by Detours code. Easy to find out in the debugger, the odds are good that there are none. That makes it easy, use the _ReturnAddress intrinsic to get the caller's address. VirtualQuery() to get the base address, cast it to HMODULE and use GetModuleFileName(). Well, the non-detoured one :)
If there are Detours stack frames then it gets a lot harder. StackWalk64() to skip them, perilous if there are FPO frames present.

Multiple mice on OS X

I am developing an OS X application that is supposed to take input from two mice. I want to read the motion of each mouse independently. What would be the best way to do this?
If that is not possible, is there a way to disable/enable either of the mice programmatically?
The HID Class Device Interface is definitely what you need. There are basically two steps:
First you need to find the mouse devices. To do this you need to construct a matching dictionary and then search the IO Registry with it. There is some sample code here, you will need to add some additional elements to the dictionary so you just get the mice instead of the all HID devices on the system. Something like this should do the trick:
// Set up a matching dictionary to search the I/O Registry by class
// name for all HID class devices`
hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
// Add key for device usage page - 0x01 for "Generic Desktop"
UInt32 usagePage = 0x01;
CFNumberRef usagePageRef = ::CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &usagePage );
::CFDictionarySetValue( hidMatchDictionary, CFSTR( kIOHIDPrimaryUsagePageKey ), usagePageRef );
::CFRelease( usagePageRef );
// Add key for device usage - 0x02 for "Mouse"
UInt32 usage = 0x02;
CFNumberRef usageRef = ::CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &usage );
::CFDictionarySetValue( hidMatchDictionary, CFSTR( kIOHIDPrimaryUsageKey ), usageRef );
::CFRelease( usageRef );
You then need to listen to the X/Y/button queues from the devices you found above. This sample code should point you in the right direction. Using the callbacks is much more efficient than polling!
The HID code looks much more complex than it is - it's made rather "wordy" by the CF stuff.
It looks like the HID Manager is what you're looking for.
You're going to want to check out the I/O Kit and HID (Human Interface Device) manager stuff.
HID manager is part of I/O Kit, so looking into there might be useful. There are two APIs for HID management, the older API is a bit more painful and then you have the new 10.5 and above API which is a bit more comfortable.
Important thing to understand is this isn't going to probably be just a quick fix, it may take some significant work to get it running. If you can assume you'll have 10.5 or better installed, using the Leopard API will definitely help.
Also; depending on how you accomplish what you're doing, may be important for you to hide the mouse cursor as it may still move a lot even if you're receiving the information from both mice. If your application grabs the screen, I'd use CoreGraphics to disable the cursor and just draw my own.
You might also consider finding a wrapper for one of these APIs, an example can be found in this question.
Unless you can force one of the mice to not be dealt with as a mouse, both will continue to control the pointer. However, you can use IOKit to write a custom USB HID driver to allow your app to read from one or both of the mice (although this would probably interfere with using them as normal mice). Building Customized User Client Drivers for USB Devices would be a good place to start for how to interact directly with USB mice.
You could look at the USB/PS-2 device interrupt.
Even if you don't want to rewrite a so called driver, it could be usefull since all the mice send their data through.
You could also check this page that could give some hints http://multicursor-wm.sourceforge.net/
maybe it's a solution for you to use usb->rsr232 converter and go by reading the serial port by yourself ?

Resources