Keyboard library: sending multimedia keys

I got an Arduino Pro Micro and rotary controller with a view to making a USB volume control. Naively, I thought I could simply use Keyboard.write() to send the scan codes for the multimediia keys (Mute 0xE2, Volume Up 0xE9, Volume Down 0xEA) but it seems as though Keyboard.write() treats everything above 128 as modifier keys. Can somebody kindly suggest how I can do it without modifying the standard library?

Best regards - Philip

pleriche:
Can somebody kindly suggest how I can do it without modifying the standard library?

Probably nobody can.

But some people already changed/extended the library

http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/

I don't think so because the function you could use (cf Keyboard/Keyboard.h at master · arduino-libraries/Keyboard · GitHub)

 void sendReport(KeyReport* keys);

is private, so you can't access it from your code

if you follow source code, the write function

size_t Keyboard_::write(uint8_t c)
{ 
uint8_t p = press(c);  // Keydown
release(c);            // Keyup
return p;              // just return the result of press() since release() almost always returns 1
}

calls directly press(c) and the press function does a check on the param if (k >= 136) {k = k - 136;...

size_t Keyboard_::press(uint8_t k) 
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
 k = k - 136;
 } else if (k >= 128) { // it's a modifier key
 _keyReport.modifiers |= (1<<(k-128));
 k = 0;
 } else { // it's a printing key
 k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
 }
if (k & 0x80) { // it's a capital letter or other character reached with shift
 _keyReport.modifiers |= 0x02; // the left shift modifier
 k &= 0x7F;
 }
 }
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && 
 _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
 _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i=0; i<6; i++) {
if (_keyReport.keys[i] == 0x00) {
 _keyReport.keys[i] = k;
break;
 }
 }
if (i == 6) {
setWriteError();
return 0;
 } 
 }
sendReport(&_keyReport);
return 1;
}

and at the end does the sendReport(&_keyReport);

if you could call sendReport with a custom crafted _keyReport then you could may be work your way around this, but as it's a private method, this won't work.

So this is the function that gets called ultimately to pass the keys. its code is

void Keyboard_::sendReport(KeyReport* keys)
{
	HID().SendReport(2,keys,sizeof(KeyReport));
}

so may be you can work your way by subclassing and finding the right way to setup the keys for your code and call in your class HID().SendReport([i][color=pink]something goes here[/color][/i]);...

can you show an example? i tried but i could not make it happen. @J-M-L

@Whandall gave you a link in #1

I found the solution in the HID-Project library. You can see exactly how I did it, including the full sketch, at http://www.instructables.com/id/USB-Volume-Control-and-Caps-Lock-LED-Simple-Cheap-/

Regards - Philip

1 Like

thank you for reply. nice project by the way.