Implementing power negotiation to support iOS 10 and iOS 11 devices


(Andrew Gallagher) #1

Theoretically, I should be able to use a model01 on an iOS device. In practice though, it throws an error about requiring too much power. I know the LED effects are turned off at startup to minimise power draw, but is there any way we can reduce the requirements further?


(Jesse) #2

Yup. This is something Apple changed in iOS 10 to be a bit stricter. The fix involves changing something that’s hardcoded deep in the Arduino core. It’s 100% doable with a little bit of time and a little bit of cleverness.

The tracking ticket is https://github.com/keyboardio/Kaleidoscope/issues/14, though the details are still in my head. If you (or anyone else) wants to take a stab at this, I’d be happy to braindump about what needs to happen.


(Mike Phillips) #3

I’m interested in pursuing this. Still learning my way around the Arduino environment at the moment, but I was hoping to use the Model 01 with my iPad Pro.

So far, I’ve found the hardcoded power value, so the power error message is no longer an issue.

I still see two issues I’d like to resolve, plus a cleaner power request.

First, something is causing a message “Cannot use device: Model 01: Connected device is not supported.” I’m guessing this is from some combination of the other devices supported (mouse, serial), so assume that this would need host OS fingerprinting support for iOS. This may also solve a particularly annoying issue where the onscreen keyboard stays up even when the Model 01 is plugged in and actively providing input.

Second, with some form of negotiation or fingerprinting, it would be nice to be able to disable LED modes that draw enough power to trigger the iPad to shut off the USB connector and turning off the keyboard. (The power up LED key display doesn’t, but the effects like digital rain do.)

Thanks!


(Gergely Nagy) #4

FWIW, this isn’t trivial to implement correctly, and includes forking the Arduino AVR core. What you really want, is to figure out if negotiating 500mA is possible, and if not, fall back to 100mA, and disable stuff that needs more (LEDs, mostly). If that still fails to enumerate, disable mouse keys, serial and perhaps some other things too.

For this to work, you need to be able to detect when enumeration fails - that’s non-trivial in itself. Basically, you need to start a timer when setting up the USB endpoints, and if protocol negotiation or status LED settings don’t happen within a timeout, assume you need to restart with reduced capabilities.

Arduino’s AVR core currently supports none of these, nor does it provide enough of an interface to do any of this.

It’s not for the faint of heart… :slight_smile: