user600: I have an Arduino Pro Micro (ATMega32u4) that I want to use as an IR receiver for a media PC and need to send codes like Volume Up, Media Home, Play, etc. But when I look up the scan codes for those and send them to Keyboard.press() it just prints out '0' every time.
Any way to send those keyboard commands?

user3917: Keyboard.press() presses a key and “holds it down” until a Keyboard.release() or releaseAll() is issued.  That is, Keyboard.press() isn't appropriate for simulation of just tapping and releasing a key, unless you follow it with a delay and a release.
Also see Keyboard.write().  But note the following, from Keyboard.write()'s documentation:

Only ASCII characters that are on the keyboard are supported. For example, ASCII 8 (backspace) would work, but ASCII 25 (Substitution) would not.

On my linux system, xev (used via xev -event keyboard) shows the following data for media keys labeled as shown.
  Excerpt from info displayed by xev           Picture
keycode 180 (keysym 0x1008ff18, XF86HomePage)   house
keycode 179 (keysym 0x1008ff81, XF86Tools)   quarter-notes
keycode 163 (keysym 0x1008ff19, XF86Mail)      envelope
keycode 172 (keysym 0x1008ff14, XF86AudioPlay)  >/||
keycode 122 (keysym 0x1008ff11, XF86AudioLowerVolume)  speaker
keycode 123 (keysym 0x1008ff13, XF86AudioRaiseVolume)  speaker
keycode 121 (keysym 0x1008ff12, XF86AudioMute)  x'd-speaker
keycode 148 (keysym 0x1008ff1d, XF86Calculator)  Calculator


user510: It is indeed possible and also without the requirement to modify the Arduino environment itself. Just register an HID descriptor for the "report ID" for "Consumer Control" (the code is 4 (constant kHID_ReportID_ConsumerControl), where the "report ID" code for keyboard and mouse are 2 and 1, respectively):
static HIDSubDescriptor node(HID_ReportDescriptor_ConsumerControl,
                             sizeof(HID_ReportDescriptor_ConsumerControl));

HID().AppendDescriptor(&node);

After the registration, HID().SendReport() now works for "report ID" equal to 4 (the first parameter), and the audio volume can be changed, etc.
The registration needs to done once and can be put into the init() function, for instance, after the Keyboard.begin(); and Mouse.begin(); calls.
Usage
Example usage, increasing the audio volume by one step:
uint8_t data[2];
data[0] = kVolumeUp;
data[1] = 0;
HID().SendReport(kHID_ReportID_ConsumerControl, data, 2);

The constants are at the end.
Notes
"Consumer Control" has the multimedia controls Volume up, Volume down, Mute, Play, etc.
The registration is similar to the way the constructors for the built-in keyboard and mouse libraries do it. HID_ReportDescriptor_ConsumerControl and constants are listed at the end because it is quite long, but they must come first (for instance, in the beginning of the file).
All this could be packaged into a reusable form. Here I have demonstrated it in a paste-and-forget form to keep it short.
HID().SendReport() looks strange, but HID() is a global function that returns an instance of the class HID_ (all built into the standard Arduino libraries, presumably to avoid some initialisation order problems with global/static objects - I thought Scott Meyers had solved that a long time ago (47. in the first book)).
HID().SendReport() can also be used to circumvent the limitation of a presumption of a US keyboard. E.g. using code 100, page 56 (and kHID_ReportID_Keyboard, like in the standard class keyboard_) to emulate the 102th key on European keyboards (e.g. a Spanish keyboard).
Only volume up and volume down were tested.
Definition of HID_ReportDescriptor_ConsumerControl and constants:

// For direct use of USB HID (yes, 3 is left out)
const uint8_t kHID_ReportID_Mouse           =  1;
const uint8_t kHID_ReportID_Keyboard        =  2;
const uint8_t kHID_ReportID_ConsumerControl =  4;
const uint8_t kHID_ReportID_SystemControl   =  5;
const uint8_t kHID_ReportID_Gamepad         =  6;
const uint8_t kHID_ReportID_MouseAbsolute   =  7;
const uint8_t kHID_ReportID_NKRO_keyboard   =  8;
const uint8_t kHID_ReportID_TeensyKeyboard  =  9;
const uint8_t kHID_ReportID_SurfaceDial     = 10;

// For use in "Consumer Control". They are bit coded.
const uint8_t kVolumeUp   = 1 << 0; // Bit 0
const uint8_t kVolumeDown = 1 << 1; // Bit 1
const uint8_t kVolumeMute = 1 << 2; // Bit 2


static const uint8_t HID_ReportDescriptor_ConsumerControl[] PROGMEM =
{
    0x05, 0x0c,                           // Usage Page ("Consumer Devices")
    0x09, 0x01,                           // Usage (Consumer Control)
    0xa1, 0x01,                           // Collection (Application)
    0x85, kHID_ReportID_ConsumerControl,  // "Report ID"
    0x15, 0x00,                           // Logical Minimum (0)
    0x25, 0x01,                           // Logical Maximum (1)
    0x09, 0xe9,                           // Usage (Volume Up)
    0x09, 0xea,                           // Usage (Volume Down)
    0x75, 0x01,                           // Report Size (1)
    0x95, 0x02,                           // Report Count (2)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xe2,                           // Usage (Mute)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb0,                           // Usage (Play)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb1,                           // Usage (Pause)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb7,                           // Usage (Stop)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb5,                           // Usage (Next)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb6,                           // Usage (Previous)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb3,                           // Usage (Fast Forward)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb4,                           // Usage (Rewind)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x95, 0x06,                           // Report Count (6) Number of bits remaining in byte
    0x81, 0x07,                           // Input (Constant, Variable, Relative)
    0xc0                                  // End Collection
}; // Table for USB HID "Consumer Control" (for audio volume control, etc.)

Platform
This was tested with:

Arduino Leonardo (already used as a macro keyboard, using an old PS/2 keyboard. Two new macro keys were assigned for testing audio volume up / down).
The Arduino Leonardo connected to an extra current port of a D-Link USB hub (necessary, for unknown reasons - probably a local problem)
Arduino IDE v. 1.18.10
Linux, Ubuntu 19.10 (Eoan Ermine), but with the buggy GNOME replaced by Cinnamon.


user71716: If you are getting zeros, the most probably cause is it's the library for the IR. Reinstall or update the library. Sometimes you have to reinstall more than one time. That should work.
About media keys, the keyboard library doesn't have media keys functionality, so you need to use another one. This one worked for me: https://github.com/NicoHood/HID
After you install this library, you have to change your code. The code for pressing media keys is different. You have to use Consumer.write, for example, Consumer.write(MEDIA_VOLUME_UP) for volume up. You can find the name of every key here: https://github.com/NicoHood/HID/wiki/Consumer-API
For normal keys, just use Keyboard.write(). If you want, I can send you the code I made to do this.

user1357: You have to do some tweaks to the usbkeyboard libraries that comes with the IDE. 
For a video tutorial, take a look at this:
Arduino Leonardo as a multimedia keyboard
Which uses the information from this site, if you prefer text only:
Arduino Leonardo multimedia keys
The Leonardo and ProMicro both use the ATMega32u4 and should both work with theses tweaks. If you need more functionality than the ones that this tweak gives you, you have to dig down into usb descriptors on usb.org for the commands you need.

600: <p>I have an Arduino Pro Micro (ATMega32u4) that I want to use as an IR receiver for a media PC and need to send codes like Volume Up, Media Home, Play, etc. But when I look up the scan codes for those and send them to Keyboard.press() it just prints out '0' every time.</p>

<p>Any way to send those keyboard commands?</p>
 3917: <p><a href="http://arduino.cc/en/Reference/KeyboardPress" rel="nofollow">Keyboard.press()</a> presses a key and “holds it down” until a <a href="http://arduino.cc/en/Reference/KeyboardRelease" rel="nofollow">Keyboard.release()</a> or releaseAll() is issued.  That is, Keyboard.press() isn't appropriate for simulation of just tapping and releasing a key, unless you follow it with a delay and a release.</p>

<p>Also see <a href="http://arduino.cc/en/Reference/KeyboardWrite" rel="nofollow">Keyboard.write()</a>.  But note the following, from Keyboard.write()'s documentation:</p>

<blockquote>
  <p>Only ASCII characters that are on the keyboard are supported. For example, ASCII 8 (backspace) would work, but ASCII 25 (Substitution) would not.</p>
</blockquote>

<p>On my linux system, <code>xev</code> (used via <code>xev -event keyboard</code>) shows the following data for media keys labeled as shown.</p>

<pre><code>  Excerpt from info displayed by xev           Picture
keycode 180 (keysym 0x1008ff18, XF86HomePage)   house
keycode 179 (keysym 0x1008ff81, XF86Tools)   quarter-notes
keycode 163 (keysym 0x1008ff19, XF86Mail)      envelope
keycode 172 (keysym 0x1008ff14, XF86AudioPlay)  &gt;/||
keycode 122 (keysym 0x1008ff11, XF86AudioLowerVolume)  speaker
keycode 123 (keysym 0x1008ff13, XF86AudioRaiseVolume)  speaker
keycode 121 (keysym 0x1008ff12, XF86AudioMute)  x'd-speaker
keycode 148 (keysym 0x1008ff1d, XF86Calculator)  Calculator
</code></pre>
 510: <p>It is indeed possible and also without the requirement to modify the Arduino environment itself. Just <em><strong>register an HID descriptor</strong></em> for the &quot;report ID&quot; for &quot;Consumer Control&quot; (the code is 4 (constant <code>kHID_ReportID_ConsumerControl</code>), where the &quot;report ID&quot; code for keyboard and mouse are 2 and 1, respectively):</p>
<pre><code>static HIDSubDescriptor node(HID_ReportDescriptor_ConsumerControl,
                             sizeof(HID_ReportDescriptor_ConsumerControl));

HID().AppendDescriptor(&amp;node);
</code></pre>
<p>After the registration, <code>HID().SendReport()</code> now works for &quot;report ID&quot; equal to 4 (the first parameter), and the audio volume can be changed, etc.</p>
<p>The registration needs to done once and can be put into the init() function, for instance, after the <code>Keyboard.begin();</code> and <code>Mouse.begin();</code> calls.</p>
<h3>Usage</h3>
<p>Example usage, increasing the audio volume by one step:</p>
<pre><code>uint8_t data[2];
data[0] = kVolumeUp;
data[1] = 0;
HID().SendReport(kHID_ReportID_ConsumerControl, data, 2);
</code></pre>
<p>The constants are at the end.</p>
<h3>Notes</h3>
<p>&quot;Consumer Control&quot; has the multimedia controls <em>Volume up</em>, <em>Volume down</em>, <em>Mute</em>, <em>Play</em>, etc.</p>
<p>The registration is similar to the way the constructors for the built-in <a href="https://www.arduino.cc/reference/en/language/functions/usb/keyboard/" rel="nofollow noreferrer">keyboard</a> and <a href="https://www.arduino.cc/reference/en/language/functions/usb/mouse/" rel="nofollow noreferrer">mouse</a> libraries do it. <code>HID_ReportDescriptor_ConsumerControl</code> and constants are listed at the end because it is quite long, but they must come first (for instance, in the beginning of the file).</p>
<p>All this could be packaged into a reusable form. Here I have demonstrated it in a paste-and-forget form to keep it short.</p>
<p><code>HID().SendReport()</code> looks strange, but <code>HID()</code> is a global function that returns an instance of the class <code>HID_</code> (all built into the standard Arduino libraries, presumably to avoid some initialisation order problems with global/static objects - I thought Scott Meyers had solved that a long time ago (47. in the first book)).</p>
<p><code>HID().SendReport()</code> can also be used to circumvent the limitation of a presumption of a US keyboard. E.g. using <a href="https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=56" rel="nofollow noreferrer">code 100</a>, page 56 (and kHID_ReportID_Keyboard, like in the standard class <code>keyboard_</code>) to emulate the 102th key on European keyboards (e.g. <a href="https://en.wikipedia.org/wiki/IBM_PC_keyboard#Keyboard_layouts" rel="nofollow noreferrer">a Spanish keyboard</a>).</p>
<p>Only volume up and volume down were tested.</p>
<h3>Definition of <code>HID_ReportDescriptor_ConsumerControl</code> and constants:</h3>
<pre><code>
// For direct use of USB HID (yes, 3 is left out)
const uint8_t kHID_ReportID_Mouse           =  1;
const uint8_t kHID_ReportID_Keyboard        =  2;
const uint8_t kHID_ReportID_ConsumerControl =  4;
const uint8_t kHID_ReportID_SystemControl   =  5;
const uint8_t kHID_ReportID_Gamepad         =  6;
const uint8_t kHID_ReportID_MouseAbsolute   =  7;
const uint8_t kHID_ReportID_NKRO_keyboard   =  8;
const uint8_t kHID_ReportID_TeensyKeyboard  =  9;
const uint8_t kHID_ReportID_SurfaceDial     = 10;

// For use in &quot;Consumer Control&quot;. They are bit coded.
const uint8_t kVolumeUp   = 1 &lt;&lt; 0; // Bit 0
const uint8_t kVolumeDown = 1 &lt;&lt; 1; // Bit 1
const uint8_t kVolumeMute = 1 &lt;&lt; 2; // Bit 2


static const uint8_t HID_ReportDescriptor_ConsumerControl[] PROGMEM =
{
    0x05, 0x0c,                           // Usage Page (&quot;Consumer Devices&quot;)
    0x09, 0x01,                           // Usage (Consumer Control)
    0xa1, 0x01,                           // Collection (Application)
    0x85, kHID_ReportID_ConsumerControl,  // &quot;Report ID&quot;
    0x15, 0x00,                           // Logical Minimum (0)
    0x25, 0x01,                           // Logical Maximum (1)
    0x09, 0xe9,                           // Usage (Volume Up)
    0x09, 0xea,                           // Usage (Volume Down)
    0x75, 0x01,                           // Report Size (1)
    0x95, 0x02,                           // Report Count (2)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xe2,                           // Usage (Mute)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb0,                           // Usage (Play)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb1,                           // Usage (Pause)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb7,                           // Usage (Stop)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb5,                           // Usage (Next)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb6,                           // Usage (Previous)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb3,                           // Usage (Fast Forward)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x09, 0xb4,                           // Usage (Rewind)
    0x95, 0x01,                           // Report Count (1)
    0x81, 0x06,                           // Input (Data, Variable, Relative)

    0x95, 0x06,                           // Report Count (6) Number of bits remaining in byte
    0x81, 0x07,                           // Input (Constant, Variable, Relative)
    0xc0                                  // End Collection
}; // Table for USB HID &quot;Consumer Control&quot; (for audio volume control, etc.)
</code></pre>
<h3>Platform</h3>
<p>This was tested with:</p>
<ul>
<li><a href="https://store.arduino.cc/arduino-leonardo-with-headers" rel="nofollow noreferrer">Arduino Leonardo</a> (already used as a macro keyboard, using an old <a href="https://en.wikipedia.org/wiki/PS/2_port" rel="nofollow noreferrer">PS/2</a> keyboard. Two new macro keys were assigned for testing audio volume up / down).</li>
<li>The Arduino Leonardo connected to an <em>extra current</em> port of a <a href="https://en.wikipedia.org/wiki/D-Link" rel="nofollow noreferrer">D-Link</a> USB hub (necessary, for unknown reasons - probably a local problem)</li>
<li>Arduino IDE v. 1.18.10</li>
<li>Linux, <a href="https://en.wikipedia.org/wiki/Ubuntu_version_history#Ubuntu_19.10_(Eoan_Ermine)" rel="nofollow noreferrer">Ubuntu 19.10</a> (Eoan Ermine), but with <a href="https://askubuntu.com/questions/1188960/copy-and-paste-issue-with-ubuntu-19-10/1197042#comment2027077_1197042">the buggy GNOME</a> replaced by <a href="https://en.wikipedia.org/wiki/Cinnamon_(desktop_environment)" rel="nofollow noreferrer">Cinnamon</a>.</li>
</ul>
 71716: <p>If you are getting zeros, the most probably cause is it's the library for the IR. Reinstall or update the library. Sometimes you have to reinstall more than one time. That should work.</p>
<p>About media keys, the keyboard library doesn't have media keys functionality, so you need to use another one. This one worked for me: <a href="https://github.com/NicoHood/HID" rel="nofollow noreferrer">https://github.com/NicoHood/HID</a></p>
<p>After you install this library, you have to change your code. The code for pressing media keys is different. You have to use <em>Consumer.write</em>, for example, <em>Consumer.write(MEDIA_VOLUME_UP)</em> for volume up. You can find the name of every key here: <a href="https://github.com/NicoHood/HID/wiki/Consumer-API" rel="nofollow noreferrer">https://github.com/NicoHood/HID/wiki/Consumer-API</a></p>
<p>For normal keys, just use Keyboard.write(). If you want, I can send you the code I made to do this.</p>
 1357: <p>You have to do some tweaks to the usbkeyboard libraries that comes with the IDE. </p>

<p>For a video tutorial, take a look at this:</p>

<p><a href="https://www.youtube.com/watch?v=ubORsI4uWuo" rel="nofollow">Arduino Leonardo as a multimedia keyboard</a></p>

<p>Which uses the information from this site, if you prefer text only:</p>

<p><a href="http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/" rel="nofollow">Arduino Leonardo multimedia keys</a></p>

<p>The Leonardo and ProMicro both use the ATMega32u4 and should both work with theses tweaks. If you need more functionality than the ones that this tweak gives you, you have to dig down into usb descriptors on usb.org for the commands you need.</p>
