Implementing power negotiation to support iOS 10 and iOS 11 devices

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?

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.

2 Likes

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!

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:

1 Like

As an update to this topic, I have been able to use the the new iPad Pro without issue (plugged directly into the USB C port).

Besides disabling all LED modes, what other things could help to mitigate the power that the M01 uses? For instance, if I take mousekeys out of my firmware, would that have an impact?

1 Like

LEDs are by far the most power-hungry. Anything else pales in comparison, to the point of being almost immeasurable. The next thing that could result in a significant drop in power use would be if we aggressively put the keyboards MCU to sleep when idle. That’s far from trivial, though, so I don’t expect it to happen anytime soon.

In other words, to save power, disable LEDs. You can keep anything else on, because they won’t matter much, as far as power goes.

2 Likes

I was thinking about this yesterday, and wondering if it could be done by conditionally calling delay(100) (for example) in the main loop based on a timeout from the last key event. A plugin that does that should be quite simple; would that result in a non-negligible reduction in power draw from the host?