Mac Special Keys

If you’ve used a Mac in the last decade (or two?) you’ve noticed that the function keys are repurposed to do things like previous/next track, volume, brightness, and more.

Modern Macs deal with this by having a function key map for specific keyboards, so macOS knows that your Macbook internal keyboard has certain keys that map to certain functions. Prior to that they (sensibly) used USB HID usages to define the keys.

Is there a way to mimic this with our own USB device?

Usage Pages and Usages

USB HID devices (keyboards, mice, game controllers, etc) describe their capabilities to the host using Usage Pages. These are defined in HID Usage Tables 1.12.

There are many, many possibilities available to use and it would have made sense to just use some of the extra keycodes already there, e.g. use F19 for launchpad. But why bother with that when you could make it more complicated and define your very own set of vendor-specific usages?

Vendor-defined

Thankfully there are a few resources to find out what usages the keys map to. Running

ioreg -l | grep FnFunctionUsageMap

(thanks to this page) shows the map used for an existing keyboard. The first value is the keyboard usage for F1, F2, etc. and the second is the alternate usage. FF01 is the vendor-specific page, 000C is the consumer devices page and is used for volume controls, play/pause, etc.

We can also reference the open source pieces of macOS, the most useful part being AppleHIDUsageTables.h. This shows all of the Apple-specific pages. The file is blank since 10.14. The relevant one for us is the keyboard page, 0xff01. Others are also worth looking into - what’s AppleVendorLisa?

The relevant usages for modern macOS are:

  • 0x03 Function - sends the Fn keycode but has no other effect in this case
  • 0x04 Launchpad
  • 0x10 Exposé All (now Mission Control)
  • 0x20 Brightness Up
  • 0x21 Brightness Down

I already had a HID report for the consumer controls so I just added these onto that, here’s part of the HID descriptor as a C array. It defines a report of one byte with each bit corresponding to a specific usage:

0x05, 0x0c,             // USAGE_PAGE (Consumer Devices)
0x09, 0x01,             // USAGE (consumer control)
0xA1, 0x01,             // COLLECTION (Application)
    0x85, 0x01,         //  REPORT ID 1
    0x15, 0x00,         //   Logical min
    0x25, 0x01,         //   Logical max
    0x75, 0x01,         //   Report size (1)
    0x95, 0x08,         //   Report count (8)
    0x09, 0xb5,         //   Usage: next track
    0x09, 0xb6,         //   Usage: prev track
    0x09, 0xcd,         //   Usage: play/pause
    0x09, 0xe9,         //   Usage: vol up
    0x09, 0xea,         //   Usage: vol down
    0x06, 0x01, 0xff,   // USAGE_PAGE (Vendor-defined, Apple Keyboard)
    0x09, 0x21,         //   Usage: bright down
    0x09, 0x20,         //   Usage: bright up
    0x09, 0x04,         //   Usage: Launchpad
    0x81, 0x02,         // INPUT data, var, abs
0x0c                    // End collection

This works… on a Mac. If that’s all you care about then this is fine, but if you plug it into a Windows machine none of them work. Windows doesn’t know what to do with the vendor-specific piece, so it ignores the entire collection. I ended up using one report for the standard consumer controls and a separate report for the Mac-specific ones.

Arduino Bug Hunt

I spent some time tracking down a strange Arduino bug and made a video about it:

VCFMW, SunUSB

I’m back from VCFMW and had a lot of fun! Met a ton of people, sold a few things, and saw some vintage computers that I never thought I’d see. A BeBox, DataRover, and an LMI Lambda LISP machine (whoa).

While there I released a new product or two, one of which is now up on the website. Check out SunUSB, an adapter that lets you use a USB keyboard and mouse on your Sun workstation. It works with Type 5 and should work with Type 4 as well. It might even work with Type 3 if you have the right cable adapter.

It’s the first of the USB-to-vintage adapters with a two layer keymap because the Sun has a bunch of keys that aren’t on a normal USB keyboard. By default you can press right control to switch the function keys to Stop, Again, Props, Undo, Front, Open, Find, Cut, Copy, Paste, Help, and Power.

I’ll have a keymap editor soon(ish) for it that will let you assign your own keys. That will eventually make its way into the other adapters too, so you’ll be able to program the keymap on your IndigoUSB, NeXTUSB, or any future ones. Speaking of future ones, there will be a couple more very soon…

ADB2USBv8

There’s a new firmware for ADB2USB. This version adds improved enumeration, supporting up to 6 ADB devices. If you wanted to use multiple keyboards at once, now you can! More realistically it will support a separate numpad like the Apple Adjustable Keyboard.

There’s also a new dwfw for Windows that can tell you the current version of the firmware you’re running.

Welcome

Welcome to the dev news piece of drakware. Here I’ll post interesting info about existing products, new products, or random vintage hardware.

Right now I’m working on PS2toUSB, which will be released any day now. It should work with any PS/2 keyboard but there are a ton of different ones out there and I’m sure at least a few have some quirks.

It supports all three scancode sets and the keymap is fully programmable (of course). I’ll look at adding mouse support if that’s something people are interested in, but I’ll have to dig up a PS/2 mouse to test.

Recent