Jump to content

Archived

This topic is now archived and is closed to further replies.

Alias

[Version 1] Teensy Keyboard Letters

Recommended Posts

So I was browsing the Teensy code documentation and came along this page http://www.pjrc.com/teensy/usb_keyboard.html . On the page it displays a table to show the C definitions for key presses. However their is no lowercase/uppercase keys, I assume that the definition for KEY_A is in fact lowercase and to make it uppercase you first have to press shift. This seems rather inefficient, wouldn't it be better to hardcode more definitions for lower/upper case letters such as KEY_a as well as KEY_A or would it be better to have a function that converts to upper/lower case, something along the lines of...

char upper(char herp)
{
	return (char) (((int) herp) - 32);
}

What do you reckon would be more easier/efficient to use?

Share this post


Link to post
Share on other sites

Depends if HID keyboard even differentiate between them.

I would set up a USB keyboard and sniff the traffic (Couple of programs around to do this, some VM's do it too.) under 4 different scenarios. (Same sentence for example.)

1. Lowercase

2. Uppercase (holding down shift)

3. Caps lock on without shift

4. Caps lock on while holding shift.

Even if there are codes there that aren't in the libraries, it would be trivially easy to add them. (If not boring.)

Share this post


Link to post
Share on other sites

Irongeek's code made use of a Keyboard.print function, have a look at that.

Share this post


Link to post
Share on other sites
Depends if HID keyboard even differentiate between them.

I would set up a USB keyboard and sniff the traffic (Couple of programs around to do this, some VM's do it too.) under 4 different scenarios. (Same sentence for example.)

1. Lowercase

2. Uppercase (holding down shift)

3. Caps lock on without shift

4. Caps lock on while holding shift.

Even if there are codes there that aren't in the libraries, it would be trivially easy to add them. (If not boring.)

There no need to go to the trouble of reverse engineering, since the HID key codes are a published standard. Here's the official document.

http://www.usb.org/developers/devclass_docs/Hut1_12.pdf

The keyboard codes are in chapter 10, starting on page 53.

It's also worth mentioning the HID report descriptor, found inside your Arduino directory at hardware/teensy/cores/teensy_hid/usb.c starting on line 77, claims the 8 bytes sent will encode usage numbers 224 to 231 (control, shift, alt, gui; both left and right) in the first 8 bit field, followed by 8 unused bits, and then 6 bytes encoding usage numbers 0 to 104. If you want to send codes greater than 104, this bit should be edited:

        0x15, 0x00,          //   Logical Minimum (0),
        0x25, 0x68,          //   Logical Maximum(104),
        0x05, 0x07,          //   Usage Page (Key Codes),
        0x19, 0x00,          //   Usage Minimum (0),
        0x29, 0x68,          //   Usage Maximum (104),
        0x81, 0x00,          //   Input (Data, Array),

Change the two 0x68 to whatever maximum usage code you want.

The format itself, 8 bits for the modifier keys, 8 reserved bits, then 6 bytes for the normal keys is called the "boot protocol". Most PC bios hard code this format, so they do not need to read the HID report descriptor. Below, you'll find the "bInterfaceSubClass" field is set to inform the host this keyboard implements the boot protocol, so it's compatible with your bios before the operating system is loaded.

In theory, you could change bInterfaceSubClass to 0 and create your own packet format, and document it with the HID report descriptor. You could do things like switch to a larger packet size to send more than 6 keys at once. In fact, you could switch to a 16 byte packet and dedicate a bit to every single usage code. As long as the HID report descriptor properly specifies your format, at least in theory, the operating system should use it. (but in practice, with windows people have found doing strange things sometimes will crash the entire HID driver in Windows.... best to use either Linux or at least a PS2 keyboard and mouse if you must develop on Windows!)

But no matter what you change in the report descriptor, ultimately you're going to map data in the HID report (aka. USB packet) to those usage codes in chapter 10. There simply aren't separate codes for uppercase and lowercase, and of course they codes are nothing like ASCII, so subtracting 32 would be pointless (and would integer underflow, since the A-Z codes are 4 to 29). How the host's HID keyboard driver interprets those codes depends on the presence of other codes, like 225 and 229, and its internal state, likely influenced by codes like 57.

A really interesting experiment might be to create a HID device that resembles something definitely not a keyboard, where bInterfaceSubClass and bInterfaceProtocol are set to 0, and the HID report descriptor top level usage is not set to 1 (generic desktop) and the top level usage page is not set to 6 (keyboard)... but inside the descriptor define some data fields that map to usage page 7 (key codes, chapter 10). I wonder which operating systems would route those codes through as keystrokes?

That's probably way more than you ever wanted to think about low-level HID keyboard usage codes, but then if you're going to use the low-level API that gives you direct control over the raw USB communication, you've got to play by the codes that the driver receiving those messages expects.

Working in ASCII is a lot easier, and that's why I wrote Keyboard.print(). Of course, all it does is translate ASCII into those codes. If you want to hack on that, it's available inside hardware/teensy/cores/teensy_hid/usb_api.cpp

Share this post


Link to post
Share on other sites

MIND. JUST. BLOWN.

Cheers for you help :lol:

Share this post


Link to post
Share on other sites

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...