Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State of the Analog SDK #14

Open
PastaJ36 opened this Issue Feb 28, 2019 · 17 comments

Comments

Projects
None yet
6 participants
@PastaJ36
Copy link
Member

PastaJ36 commented Feb 28, 2019

There’s a lot happening in the Analog keyboard world. Outside of Wooting there’s a new player on the market and there are rumours of even more coming. Wooting’s goal is to make that analog doesn’t go the way as RGB for games did, a painfully divided closed system.

This Analog SDK should be the answer towards a simple, compatible solution. Sadly I feel like the current state of the analog SDK is not able to provide this, so I want to start a discussion about how we can make it better.

This post is just about the Analog SDK, there is also a mirrored RGB SDK post here. If you want to know why we split the Analog and RGB SDK, please read this gist.

Goal of the Analog SDK

The analog SDK wants to be as close as possible to an ideal USB driver. It’s important to distinguish between a user side (somebody that buys an analog keyboard) and application side (the developer that adds code to support analog keyboard in an application).

Ideally a user should be able to buy an analog keyboard, plug it in and be done with it. Drivers will be installed automatically. Once the user enters an application it will just follow normal keyboard mappings, but there’s analog support.

On the developer side it should work like interfacing with a normal keyboard with an analog edge. After an analog keyboard is detected the API can mirror how it works in most applications: getAnalogValue(keyCode)

Why not just develop a USB driver?

USB driver are notoriously hard to develop. It requires deep understanding of the OS and even if you down one, you have two other to go. Besides that having plug and play install requires certification for every USB device. This hurts adaption, especially for smaller / community sized keyboard makers.

Requirements of the Analog SDK

  1. Easy interfacing for developers with support for different languages.
  2. Ability to add new devices to SDK, reflected in existing SDK installs.
  3. Possibility to update to support an evolving standard.
  4. Ability to read custom key codes (i.e. FN key, Macro keys, Wooting Mode key).

Can the current way fit the requirements?

Currently the SDK builds to a DLL which a developer adds to the application. This makes the developer responsible to keep up to date with new devices and/or new updates to the SDK.

We could make it possible to improve the current way and add better interfacing and read custom key codes. Requirement 3 could even be met by having some separate device database. That adds a whole new layer of complications though.

What else can we do?

Making the developer responsible can really hurt adoption. We’re already asking developers to add support for our SDK, so we should make it as easy as possible for them.

I think we should move to the user installing the SDK. The install can be part of the configuration software of the keyboard vendor and/or a separate install.

Making this move also allows us to reconsider how we want the SDK to look like. I think we should revisit the concept and design a new system that will fit all the requirements.

I think I’ve written enough for now. I’ll come back with a definition of the firmware side, specifically for requirement 4. The current DLL setup just feels like it’s missing the mark now and I’m very curious what your suggestions are.

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Feb 28, 2019

In short I think that the hardware layer has to be separated from the analog interface at all. Now the interface is only capable of using the vendor id and product id from wooting. I think the best way should be to have a unique identifier that it is not vendor or product based.

I would prefer a special HID usage and usage page code for this along with a standardised report. So the interfaces can see every product that are offer this. Additional the interface has to be capable of handling multiple devices that are connected.

With that a other vendor has just to offer the same HID Descriptor and a vaild Report for the interface like any generic mouse, keyboard or joystick / gamepad are handling it today. Later the report can be different through vendors as long the interface would be updated for newer report types. So write an interface that scans only for a special usage and usage page and interpret the report from it.

To have a special standardised usage and usage page for it, it would be maybe the best to claim one from the USB Implementers Forum, I guess.

This would be a really big step to unify all analog keyboards and create a standardised interface for all.

But in order to make this real you have to talk to the other vendors so all parties agree with that. Otherwise it would be a standard which no one uses it...

@GottZ

This comment has been minimized.

Copy link

GottZ commented Feb 28, 2019

i think the analog and rgb communication should be unified and the analog and rgb sdk should then just be two separate sdk clients to that backend service.

WootingKb/wooting-rgb-sdk#13 sure has some discussion going on now about this.

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Feb 28, 2019

With that I have in mind there are no back services. The new Analog SDK would be just an interface like Direct Input from Mirosoft. It would scan for the special usage and usage page, would scan the report from it and would listen to the data that is send from the device. Everytime it would receive data it would update an internal structur that other programs can read from it. So even when other vendors creates a new / different report for it, the interface has just be updated for this to interpret it correctly.

Like Direct Input from Microsoft, this interface just reads the reports for joysticks and gamepads (usage page "Generic Desktop" and usage "Joystick") and interpret the report so it's regardless if the joystick send only positive values or negatives too, or sends 8 bit values or 12 bit ones. The output will be always between 0 and 65536 there the center is 32767.

Edit:
But yes I don't mention the way how applications have access to that interface. Theoretical they can use it directly in form of a DLL or something like that, or someone create a service for it and other programs are just using this service. But this doesn't really matter I think, because the first step has to be a unified interface on the lower level to identify all analog keyboards the same way.

Edit 2:
For now I have something like that in mind just for inspiration (the behaviour is similar to the currect from Wooting):
`
USAGE_PAGE (Generic Desktop)
USAGE (Analog Keyboard)
COLLECTION (Apllication)
USAGE_PAGE (Keyboard)

// The current quantity of the pressed keys in the current report
USAGE (Quantity)
LOGICAL_MINIMUM (-1)
LOGICAL_MAXIMUM (16)
REPORT_SIZE (8)
REPORT_COUNT (1)

// THIS IS APLIED FOR EVERY CURRENT PRESSED KEY
// The scancode of a pressed key
USAGE (ScanCode)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (128) // I don't know how a Scancode look like :-(
REPORT_SIZE (8)
REPORT_COUNT (1)

// The depth of the pressed key
USAGE (Value)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (255)
PHYSICAL_MINIMUM (150) // 1.5 mm for the lowest actuation point that the key is capable of a press
PHYSICAL_MAXIMUM (360) // 3.6 mm for the highest actuaction point that the key is capable of a press
REPORT_SIZE (8)
REPORT_COUNT (1)

END_COLLECTION
`

This defines a real travel range from 1.5 mm to 3.6 mm where the value zero is below 1.5 mm, one is at 1.5 mm, two hundred fifty four is at 3.6 mm and two hundred fifty five is above 3.6 mm.

Edit 3:
With that characteristic it would be possible to just send 16 values per report but without a limitation to a 16 KeyRollOver. If nothing is changed the Quantity would be zero. If more than 16 keys are pressed the output would be devided into multiple reports whitout any loss. Like a keypress on a normal keyboard a current value will be stored until a release / change will be registered. To prevent some strange behaviour a zero value for a Scancode can be send in multiple reports so the interface can be shure that the key is released and not forgotten. And a Quantity of -1 can be indicate that all keys are released.

@evilC

This comment has been minimized.

Copy link

evilC commented Feb 28, 2019

I think we have already covered this in Discord, but I will repeat it here for completeness.
The keyCode in getAnalogValue(keyCode) IMHO should not be a wooting-specific number. At the moment, this is a proprietary wooting code which holds zero meaning for every other keyboard manufacturer and application out there.
IMHO it should be an actual scan code (In the range 1..512, with >256 signifying extended key code).
Furthermore, APIs should be key name agnostic (ie not like the current .NET wrapper, which says that the key to the right of tab is always called "Q", when it isn't).
As far as I am aware, the windows function GetKeyNameTextW should return the layout-specific name for a given ScanCode

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Feb 28, 2019

I wrote Scancode and not Keycode, so there is the problem? But if you mean for the currect SDK I agree with you :-)

And the language of the keyboard doesn't matter in my opinion. Windows translate it for the normal keyboard, so it would be the same here. The application has to check if a Scancode is a "Y" or a "Z", or a "Q" or a "A". The keyboard itself don't has to deal with the layout, you have to set the layout in Windows or the application itself. Because maybe you have an english ISO but want to act it as a german layout, because you change the keycaps.

@evilC

This comment has been minimized.

Copy link

evilC commented Feb 28, 2019

I wrote Scancode and not Keycode, so there is the problem? But if you mean for the currect SDK I agree with you :-)

To clarify, I was purely talking about the current SDK, I wasn't referring to what you wrote

@GottZ

This comment has been minimized.

Copy link

GottZ commented Feb 28, 2019

nice and dandy.
complaint: keylogging.
windows restricts keyboard access to non elevated applications already thus we should not break that. maybe with a killswitch in profiles

@evilC

This comment has been minimized.

Copy link

evilC commented Feb 28, 2019

windows restricts keyboard access to non elevated applications already

This is incorrect / ambiguous.
Windows will not fire keyboard hooks that belong to a non-elevated process while an elevated process is active.
It's entirely possible to sniff keyboard input for non-elevated processes from a non-elevated process.

Proof:
Run the following AHK script unelevated, then go into notepad and hit F12:

#InstallKeybdHook
F12::Msgbox You pressed F12

Wrt disabling the analog API while in password boxes, I do agree that is a potentially scary attack vector however.

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Feb 28, 2019

I agree it is problematic but at least more elegant than now, because the problem exist now too. A killswitch (special mode or key) would be a good idea to toggle the analog mode.

But if there is a special usage for an analog keyboard in the future the operation systems would know about it and it can handle it the way like a normal one. The main goal is to have an analog keyboard in the future just like a normal one. But in order to achieve this there has to be a standard. Think about it if every vendor has to carry about this his own way, this would be terrible.

@GottZ

This comment has been minimized.

Copy link

GottZ commented Feb 28, 2019

that would require getting into the linux and windows kernels.
that will take a while.

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Feb 28, 2019

Like back them when the first mouse came up. Who need such an device like that ;-P

@PastaJ36

This comment has been minimized.

Copy link
Member Author

PastaJ36 commented Mar 1, 2019

I don't think we need something running in the background, as long as there is a clear install path an application (or our own interface application) can find.

@Rocky04 Even though I agree with that a special usage page is the best solution, it is out of reach for us for now. Even just being part of the USB elite club is thousands of dollars. I would much rather start in a "hacking" way and demonstrate interest first. What's the use of setting up a complicated system if nobody uses it?

Plus even if we set up a custom report, we need to write the software to parse the reports on the PC side anyway.

We do need to setup a standard on how to define and use USB reports, I would just use as much out-of-the-box as possible. We could use a customer usage page in the FFxx range, but then we risk opening other devices. Maybe we can combine it with an enumeration, which we can also use to ask for analog device information.

@evilC Yes definitely, that's one of the first things to change in the API. It's what I meant with that example, use a standard keycode, same way as any game engine does it. I'm still thinking how to handle custom keys though.

@evilC

This comment has been minimized.

Copy link

evilC commented Mar 1, 2019

I don't see that we need USB-IF membership, and we don't need a "logo" option (I don't even remember seeing a USB logo on your packaging), so we surely just need a one off VID or PID allocation.
From what I can tell, buying a whole VID is a one-off fee of $5000, or, if Wooting is going the Open Hardware route, you can get a PID for free from OpenMoko or pid.codes

@Rocky04

This comment has been minimized.

Copy link

Rocky04 commented Mar 1, 2019

I thought the Wooting keyboards can't have multiple VIDs or PIDs. So the only way is by setting a class I guess and / or usage (page). But I still think even with that the interface should interpret the HID report.

@aarongeorge

This comment has been minimized.

Copy link

aarongeorge commented Mar 4, 2019

@evilC sorry I'm a few days late, but with regards to the keyCode values, would you expect something like this?

The way that browsers implement this at the moment is that all the "code" values are tied to the QWERTY layout, and the "key" values are tied to the keyboard layout on the OS. E.g. If I had a QWERTY keyboard but had DVORAK as the layout in my OS and then hit the physical Q key, the "key" value would be ' and the "code" value would be KeyQ.

@haata

This comment has been minimized.

Copy link

haata commented Mar 4, 2019

Basically, you can pay $5000 (soon to be $6000) for a VID.
But this doesn't get you membership to vote on/propose new features, that requires membership to the USB-IF, that will soon be $5000 per year (currently $4000).

Reference: I got Input Club setup with a VID last year so we could have as many PIDs as we want.
Even though there are a few smaller keyboard companies that are interested in pushing some additions to the USB spec, they make it super difficult to pool money to get a vote.

https://www.usb.org/getting-vendor-id

@PastaJ36

This comment has been minimized.

Copy link
Member Author

PastaJ36 commented Mar 6, 2019

Thanks for the input @haata. In general I think we shouldn't reach for the maximum straight away and prove there's interest for it first. Make something good, prove that games and users want it, then do it perfect.

Ideally we combine it by designing the SDK in a way to will allow it to grow into a standard that follows USB standards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.