Using HIDs
Pages: 1 2
Dave Higton (1515) 3526 posts |
There are two entirely unrelated reasons I have for using USB HIDs in RISC OS, and I’m interested in knowing what level of integration I can get with RISC OS. It’s an area where I know less than I would like (and less than some people possibly expect me to know).
|
Colin (478) 2433 posts |
the usbmouse module passes events onto KeyV and PointerV |
Theo Markettos (89) 919 posts |
Does usbmouse need registering as the official driver with *Configure MouseType? There’s one thing to be said for the Simtec USB driver, that it injects events directly into PointerV without disturbing the existing mouse driver so you can have a quadrature and a USB mouse at the same time, and hotplugging works sensibly. I don’t know what happens if you have a relative pointing device (eg a mouse) and an absolute device (graphics tablet, touchscreen) operational at the same time. Do the random buttons appear as a separate endpoint that you could hand over to a HID driver (if such existed), or do you have to drive them in your audio/whatever driver? What does XAT’s !HID do? |
Colin (478) 2433 posts |
As far as I can see usbmouse just injects events directly into the PointerV – See Jeffrey Lee’s comment below. You can have any number of mice (a plague :-))
It appears that if you open an endpoint which is used by the internal keyboard/mouse drivers the internal drivers are disconnected. |
Jeffrey Lee (213) 6048 posts |
The only code for parsing USB HID streams is in the USB module, and there’s no way of passing it data to process (unless you feel like writing a fake USB host controller driver!)
Negative; it only sends events to PointerV if it’s the configured mouse type (look for the ‘enabled’ flag) |
Dave Higton (1515) 3526 posts |
They are a separate interrupt mode endpoint. There are two aspects to using HIDs: one is getting the HID descriptor information (which has to be requested from the device by the host), the other is getting the stream of events, which have to be interpreted according to the descriptors. I’d like to know how the existing modules can deal with both those aspects. If reading the descriptors is tightly integrated with the USB HID class, it’s going to be difficult, because you can’t communicate with a Bluetooth device directly, even though the dongle is USB; there are other layers in the way. If, on the other hand, there is a more generalised way to communicate, it may be much easier to integrate. Don’t forget the keyboard. I’ve done far more work with a Bluetooth keyboard than mouse. |
Colin (478) 2433 posts |
The other alternative is to use hid.h and hid.c from the sources. They are both NetBSD licenced |
Dave Higton (1515) 3526 posts |
Or, alternatively, writing another way in to the USB module. Would it make sense to add that? I can imagine calls to register a new device, deregister it, supply its HID descriptors, and supply a data stream stripped of its excess layers. I don’t like the idea of duplicating what is already there – which, in the case of a keyboard, is quite a lot, according to what I’ve read (international keyboard handler, etc.) |
Colin (478) 2433 posts |
If you look at usbkboard.c next to usbmouse.c I pointed out earlier. If you were happy with the licence you could just strip out the usb parts (mainly attach, detach and setting up an interrupt pipe) and use the bits you need. Its not that big a file – the mapping table looks a time saver. |
nemo (145) 2546 posts |
There are already key codes for the obvious multimedia keys, but supporting arbitrary keys is something I worked quite extensively on. DeepKeys implements a deep keyboard buffer, so the keyboard driver (or other software of course) can put novel keycodes into the buffer (via insV) and have them delivered all the way through Wimp_KeyPress exactly as you’d expect. The intention was to support virtual keys such as the “scan” button many scanners have, or whatever exciting keys new keyboards came with… but then USB happened and everyone stopped making interesting keyboards packed full of extra buttons. My Cerilica MMK keyboard driver modules supported a large number of additional virtual keys by supporting three modifier keys on all of its multimedia keys. So the MMK had something like 100 additional keys, plus its rotary encoder (which also acted as eight separate knobs thanks to modifers). Deepkeys also treats the Logo key as a modifier, so that could have been doubled. I should also point out that contrary to popular expectation, OS_Byte is not restricted to byte-sized parameters – when DeepKeys is present, keyboard related calls such as 138 and 129 can take virtual key numbers, so this works as expected: >SYS"OS_Byte",138,0,12345:PRINT GET 12345 >SYS"OS_Byte",138,0,67890:SYS"OS_Byte",129,255,0TO,K%:PRINTK% 67890 Note however that things like TaskWindow predate DeepKeys and hence don’t expect keypresses to be larger than a byte – in that case it’s the TaskWindow_Input message that is the problem. Anyway, it is therefore also possible to extend the number of internal keys (INKEY) provided one keeps b7 clear. DeepKeys does not currently implement any such extension, and the OS routine ANDs the key number with &7F before checking its keys pressed table, but that’s an implementation detail and easily tweaked. (Aside: I could have put such a filter in DeepKeys to establish the principle and clean-up the interface, but it didn’t seem quite right at the time, and the perenial vector-claimant-ordering problem that DeepKeys made so obvious isn’t solved without VectorExtend, and I haven’t made an RO5 version of the latter yet.) TL;DR: You can coin new internal keys and new keypress codes. Someone should really define some ranges for these things (ie reserved for OS, Third party allocations, dynamic allocations, etc) and allocate them properly if people are going to make use of that functionality. |
nemo (145) 2546 posts |
The other aspect of HID support that the MMK keyboard prompted (plus the work I did with Paul @ XAT on multi-wheel mice) was the concept of multiple and various knobs, sliders, pointers and sensors such as graphics tablet tilt, pressure and rotation. MMK’s ‘volume’ knob behaved as eight separate up/down controls, and could be used by applications (Vantage allowed you to rotate the object you were dragging for example) or modules (we shipped a number of CD drive control modules). However, supporting such novel input devices is a pain: I think it was Spacetech who did a graphics tablet which supported X, Y and pressure. The X,Y could be mapped to PointerV but not the pressure, so they introduced a dedicated API which PhotoDesk used for example. We were considering releasing a tablet that also had lean and rotation – and so we’d have had to map X,Y to PointerV, X,Y and Pressure to a Spacetech-compatible API clone, and X,Y,Pressure,Lean and Rotation to some new API. And what happened if you plugged in a second tablet, or a second mouse? We solved this with a module called Channels. This introduced the concept of physical and virtual controls – a graphics tablet would provide say three physical channels – TabletX, TabletY and TabletPressure — but applications would read and respond to a number of virtual channels – PointerX, PointerY and PointerPressure for example. There were then CLI and GUI utils to map physical to logical channels. This way applications would not be constrained to a particular proprietary API, and users could make use of whatever peripherals or simulations they had available. Ultimately we decided not to bother with the graphics tablet, but I’ve often thought the Channels module would be a useful API for dealing with this kind of problem. |
nemo (145) 2546 posts |
Theo said:
Which is both good, and bad. It’s good if you want both mice to fight over the pointer, it’s bad if you were hoping to get some additional functionality. |
WPB (1391) 352 posts |
Is this module something you could release, Nemo? It sounds like a nice idea. |
Rick Murray (539) 13840 posts |
It depends, I guess, on what exactly you are expecting? When I plug the graphics tablet into my PC, both the touchpad and the tablet control the mouse. Buttons on the pen map to mouse keys. However for applications that understand the pen, there is the extra option of tip pressure. I don’t know how the Windows API handles this, it “just works” (once you’ve scoured the ’net to match USB device IDs up to suitable drivers, that is :-) ). What I feel might be an option to consider is ExtUserInteractionV (plus associated Wimp support) for a generalised user- colicky-pokey-proddy sort of input.
As a side shoot of this, the question of buttons on external devices (that “scan” button again). Should this be reported as a user interaction, or a fake key press?
…many keyboards have additional buttons. My cheap bog standard has buttons for sleep and … a couple of other things. Don’t work with RISC OS so I have paid attention. What I suspect is, in the USB era, people realise that their keyboard’s value isn’t necessarily defined by how much extra stuff it has. Or, alternatively, maybe now that more and more people use Linux, there is less desire for a pile of proprietary crap that only comes with drivers and tools for Windows. My old ps/2 keyboard on the PC has loads of extra keys. None of them work, I never bothered to find/download the right driver for XP. And there, perhaps, is the crux of the matter. What use are all the whizz-bangs when they aren’t universal? I would like to think that things improved in the USB era, but I am writing this on an iPad Mini, an Apple creation which means it almost bends over backwards to be incompatible with everything else. <sigh> |
Dave Higton (1515) 3526 posts |
I’ve had two mice connected at the same time. There’s no problem, unless for some odd reason two people are trying to use them at the same time. That’s the only time you get odd effects. Otherwise, one mouse is stationary, and it does not contribute movement or events. I’ve had a graphics tablet and pen (absolute) and mouse (relative) connected at the same time. Again, no problem if only one is being used. When the pen is not close to the tablet’s surface, the tablet stops sending positions, so the mouse can move the pointer from where the tablet left off. And vice versa: when the pen gets close to the surface again, the mouse cursor jumps to the tablet’s position. |
Theo Markettos (89) 919 posts |
I wonder if this is a different class of keypress. For example, note that Ctrl-F12 is the ‘taskwindow button’, which doesn’t get delivered to the app with input focus (I think) but gets interpreted higher up. So the ‘scan’ button is just a keypress, but one which gets picked up by the app launcher (whatever that is) to launch the scanning program. And then once the scanning program is launched pressing Scan again does a scan/save/bump filename/OK. So it’s not a hotkey hardwired into launching the scanning program, but is context-sensitive depending on which window has focus. Which is what normal keys do. That also means modifier keys can be used with such buttons. For example, shift-Sleep might cause hibernate rather than suspend. Maybe this means a more general framework of ‘making things happen’ when keys are pressed. Which is not just running a command/starting a task – while you’re in a game or a phone call you want to increase the volume, but you don’t want to/can’t start a new task to do it. So maybe attaching keys to lower level routines. One idea. Have KeyAction$< Keycode> variables. Then you can have a command to launch, or a code variable to do something else? Maybe that’s the fallback action if a keypress isn’t claimed by the app with focus (though apps don’t really ‘claim’ keys anyway) |
nemo (145) 2546 posts |
I realise I should no longer be surprised by anything Rick does, but he still gets me sometimes. My lack of enthusiasm for USB keyboards (and I’m typing on the ONE USB keyboard I could find that does have a rotary encoder – I miss my MMK!) is that it’s all very standardised these days. If you’re familiar with video editors such as AVID, then you’ll not be surprised by ostensibly ISO keyboards with crazy coloured keys and non-alphanumeric legends, and Lebedev’s Optimus took that to its logical extreme with video-topped keys, but these keyboards all deliver standard keypresses, and if plugged into RISC OS even in addition to a standard keyboard will still not generate distinguishable keypresses. I regret that we don’t yet have the ability to distinguish if we want to (note that DeepKeys does allow the application to distinguish between Return, Enter and Ctrl-M, and this is analogous).
Oh yes it does.
No, you have that backwards. Keypresses get delivered to the task with the focus. If it doesn’t understand the keypress (by which I mean it chooses not to do something with it) it passes it back to the Wimp with Wimp_ProcessKey. At that point the Wimp offers it to non-focussed windows which have the ‘hot-key’ bit set, which is how ^F12 gets picked up. It is possible for OS-level code to detect and suppress the keypress earlier (sitting on RdchV is one example), but that isn’t appropriate for applications, and would be very unusual. |
nemo (145) 2546 posts |
Theo also said:
Well this is one of the things that DeepKeys does – it augments every keypress event (delivered to tasks) with the state of the modifier keys when the key was pressed. There’s also an extended insV call to allow keypress+modifiers to be inserted into the keyboard buffer for simulation of such effects. |
nemo (145) 2546 posts |
Dave claimed
This is only “no problem” if you didn’t want the two mice to do different things or require two people to use them — for controlling a game for example. That RISC OS can’t yet allow such usage (in the most generic fashion) is regrettable, but what I hoped Channels would address. WPB asked
Chicken and egg – it’s useless without drivers that declare physical channels and software which consumes logical channels. ISTR it has standard mouse channels built in, and also forking, combining and scaling operations. So it is still possible to configure it to drive one pointer with two mice simultaneously, but equally a game with two “pointers” could use the standard Pointer API for one player and the Channels API to read Pointer2_X and Pointer2_Y – which could then be connected to the physical channels provided by a pointing device, or a simulation using keypresses, or a USB game controller etc. I’ll dig it out and re-acquaint myself with it. I imagine it’s been over ten years since I last saw it. |
nemo (145) 2546 posts |
Theo also mentioned:
The MMK keyboard had four application-launching buttons. Pressing them opened a little window with the application icon in it, and it could be launched by pressing Return. This allowed you to have numerous applications on the same button – pressing the hot key cycled through them. And of course it didn’t need to be applications, it could be any kind of file including an Obey file which could do arbitrary commands. However, launching applications like this has to be done within the desktop, you don’t want to be trying to do so when the user has pressed F12 for example. |
Colin (478) 2433 posts |
I wonder what configuring mouse type does and whether it is relevant any more – at least as far as claiming PointerV. You can plug any number of usb mice in and they share the PointerV so it wouldn’t have been a problem with sharing with another mouse type. It seems more consistant to me to share the PointerV with all mouse types. Could you have more than 1 other type of mouse plugged in? However it is useless for mice to share the PointerV as there is only 1 configuration |
Colin (478) 2433 posts |
I don’t see how the HAL is the problem. |
Rick Murray (539) 13840 posts |
While having the interfacing and hardware code in tidy modules is a nice sounding solution, the level of collusion is unlikely to decrease much, for two specific reasons: 1. If every call to hardware uses a SWI, this piles on additional code and exposes the system to delays inherent in the SWI processing. This might work if you have a set of routines which are arranged CLib style via a jump table. But, then, you have just created a HAL only you are calling it something else. 2. So your FIQ routine is called and it wants to talk to hardware. It should do what? Call a SWI and to hell with the consequences? 3. (bonus reason) Is this sort of thing even wise to have as modules? It isn’t as if they will be upgraded independently of the OS itself. Kill the module that handles USB and USB ceases to work. Kill the module that contains the code that marshals interrupts, it’ll all go south in a hurry. Maybe the really low level stuff is best kept out of sight? The collision will be necessary in order to keep things tight. I fully agree that the kernel itself should know nothing about the hardware, and that something else should act as the intermediary between what the kernel wants and what the hardware does. This is not so much tied to the kernel as to the specific platform. A Pi build won’t run in a Beagle even though 99.9% of the code is the same. |
Chris Hall (132) 3554 posts |
I think it works because the OS is modular. The GPL licence struggles with this concept. |
Chris Gransden (337) 1207 posts |
Are you sure? I believe the whole of the RISC OS rom can’t contain any GPL code as it’s classed as being statically linked. There was a GPL violation back in the early Iyonix days which was sorted out. See this old drobe article. If you still think there’s some GPL code lurking then you need to point it out so it can be looked at. |
Pages: 1 2