title: Generic keyboard emulation using Arduino Leonardo
body: <p>I am trying to use an <a href="http://arduino.cc/en/Main/arduinoBoardLeonardo" rel="nofollow">Arduino Leonardo</a> for keyboard emulation since that is one of its advertised features. I have been playing with the Leonardo and wrote a very simple sketch based off the Blink example.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>// Pin 13 has an LED connected on most Arduino boards.
  int led = 13;
  
  // The setup routine runs once when you press reset:
  void setup()
  {
      // Initialize the digital pin as an output.
      pinMode(led, OUTPUT);
  }
  
  // The loop routine runs over and over again forever:
  void loop()
  {
      delay(5000);              // Wait for five seconds
      digitalWrite(led, HIGH);  // Turn the LED on (HIGH is the voltage level)
      delay(100);               // Wait for a secondA
      digitalWrite(led, LOW);   // Turn the LED off by making the voltage LOW
      Keyboard.write('A');      // Write an A using keyboard emulator
  }
  </code></pre>
  
  <p>Now this example works great on my Windows XP machine. It is recognized as a generic <a href="http://en.wikipedia.org/wiki/Human_interface_device" rel="nofollow">HID</a> keyboard and will type an 'A' every five seconds.</p>
  
  <p>The targeted environment is running DOS so to my knowledge I need to get the Arduino Leonardo recognized by the BIOS on this machine, which it is not and it does not type the 'A' in DOS.</p>
  
  <p>I have been making modifications to the USB device descriptor of the Leonardo, trying to make it match a Dell L100 as much as possible. The modifications I've made haven't helped, and I suspect it is because the Leonardo is a composite device which exposes the serial communication, keyboard emulation, and mouse emulation on the same USB port. The source code for the USB descriptors/configuration is available to be edited and is located at:</p>
  
  <ul>
  <li>Arduino_Installation\hardware\arduino\cores\arduino\HID.cpp</li>
  <li>Arduino_Installation\hardware\arduino\cores\arduino\USBDesc.h</li>
  <li>Arduino_Installation\hardware\arduino\cores\arduino\USBCore.h</li>
  <li>Arduino_Installation\hardware\arduino\cores\arduino\USBCore.cpp</li>
  </ul>
  
  <p>The following is a dump from USB Device Viewer for the Leonardo:</p>
  
  <pre><code>[Port3]  :  USB Composite Device
  
            ---===&gt;Device Information&lt;===---
  English product name: "Arduino Leonardo"
  
  ConnectionStatus:
  Current Config Value:              0x01  -&gt; Device Bus Speed: Full
  Device Address:                    0x03
  Open Pipes:                           4
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x81  -&gt; Direction: IN - EndpointID: 1
  bmAttributes:                      0x03  -&gt; Interrupt Transfer Type
  wMaxPacketSize:                  0x0010 = 0x10 bytes
  bInterval:                         0x40
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x02  -&gt; Direction: OUT - EndpointID: 2
  bmAttributes:                      0x02  -&gt; Bulk Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x00
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x83  -&gt; Direction: IN - EndpointID: 3
  bmAttributes:                      0x02  -&gt; Bulk Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x00
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x84  -&gt; Direction: IN - EndpointID: 4
  bmAttributes:                      0x03  -&gt; Interrupt Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x01
  
            ===&gt;Device Descriptor&lt;===
  bLength:                           0x12
  bDescriptorType:                   0x01
  bcdUSB:                          0x0110
  bDeviceClass:                      0x00
  *!*ERROR: device class should be Multi-interface Function 0xEF
            When IAD descriptor is used
  bDeviceSubClass:                   0x00
  *!*ERROR: device SubClass should be USB Common Sub Class 2
            When IAD descriptor is used
  bDeviceProtocol:                   0x00
  *!*ERROR: device Protocol should be USB IAD Protocol 1
            When IAD descriptor is used
  bMaxPacketSize0:                   0x40 = (64) Bytes
  idVendor:                        0x2341 = Vendor ID not listed with USB.org as of 03-19-2008
  idProduct:                       0x8036
  bcdDevice:                       0x0100
  iManufacturer:                     0x01
       English (United States)  "Arduino LLC"
  iProduct:                          0x02
       English (United States)  "Arduino Leonardo"
  iSerialNumber:                     0x00
  bNumConfigurations:                0x01
  
            ===&gt;Configuration Descriptor&lt;===
  bLength:                           0x09
  bDescriptorType:                   0x02
  wTotalLength:                    0x0064  -&gt; Validated
  bNumInterfaces:                    0x03
  bConfigurationValue:               0x01
  iConfiguration:                    0x00
  bmAttributes:                      0x80  -&gt; Bus Powered
  MaxPower:                          0xFA = 500 mA
  
            ===&gt;IAD Descriptor&lt;===
  bLength:                           0x08
  bDescriptorType:                   0x0B
  bFirstInterface:                   0x00
  bInterfaceCount:                   0x02
  bFunctionClass:                    0x02  -&gt; This is Communications (CDC Control) USB Device Interface Class
  bFunctionSubClass:                 0x01
  bFunctionProtocol:                 0x01
  iFunction:                         0x00
  
            ===&gt;Interface Descriptor&lt;===
  bLength:                           0x09
  bDescriptorType:                   0x04
  bInterfaceNumber:                  0x00
  bAlternateSetting:                 0x00
  bNumEndpoints:                     0x01
  bInterfaceClass:                   0x02  -&gt; This is Communications (CDC Control) USB Device Interface Class
  bInterfaceSubClass:                0x01
  bInterfaceProtocol:                0x00
  CAUTION:  This may be an invalid bInterfaceProtocol
  iInterface:                        0x00
    -&gt; This is a Communications (CDC Control) USB Device Interface Class
  
            ===&gt;Descriptor Hex Dump&lt;===
  bLength:                           0x05
  bDescriptorType:                   0x24
  05 24 00 10 01
    -&gt; This is a Communications (CDC Control) USB Device Interface Class
  
            ===&gt;Descriptor Hex Dump&lt;===
  bLength:                           0x05
  bDescriptorType:                   0x24
  05 24 01 01 01
    -&gt; This is a Communications (CDC Control) USB Device Interface Class
  
            ===&gt;Descriptor Hex Dump&lt;===
  bLength:                           0x04
  bDescriptorType:                   0x24
  04 24 02 06
    -&gt; This is a Communications (CDC Control) USB Device Interface Class
  
            ===&gt;Descriptor Hex Dump&lt;===
  bLength:                           0x05
  bDescriptorType:                   0x24
  05 24 06 00 01
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x81  -&gt; Direction: IN - EndpointID: 1
  bmAttributes:                      0x03  -&gt; Interrupt Transfer Type
  wMaxPacketSize:                  0x0010 = 0x10 bytes
  bInterval:                         0x40
  
            ===&gt;Interface Descriptor&lt;===
  bLength:                           0x09
  bDescriptorType:                   0x04
  bInterfaceNumber:                  0x01
  bAlternateSetting:                 0x00
  bNumEndpoints:                     0x02
  bInterfaceClass:                   0x0A  -&gt; This is a CDC Data USB Device Interface Class
  bInterfaceSubClass:                0x01
  bInterfaceProtocol:                0x00
  CAUTION:  This may be an invalid bInterfaceProtocol
  iInterface:                        0x00
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x02  -&gt; Direction: OUT - EndpointID: 2
  bmAttributes:                      0x02  -&gt; Bulk Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x00
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x83  -&gt; Direction: IN - EndpointID: 3
  bmAttributes:                      0x02  -&gt; Bulk Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x00
  
            ===&gt;Interface Descriptor&lt;===
  bLength:                           0x09
  bDescriptorType:                   0x04
  bInterfaceNumber:                  0x02
  bAlternateSetting:                 0x00
  bNumEndpoints:                     0x01
  bInterfaceClass:                   0x03  -&gt; HID Interface Class
  bInterfaceSubClass:                0x01
  bInterfaceProtocol:                0x00
  CAUTION:  This may be an invalid bInterfaceProtocol
  iInterface:                        0x00
  
            ===&gt;HID Descriptor&lt;===
  bLength:                           0x09
  bDescriptorType:                   0x21
  bcdHID:                          0x0101
  bCountryCode:                      0x00
  bNumDescriptors:                   0x01
  bDescriptorType:                   0x22
  wDescriptorLength:               0x0065
  
            ===&gt;Endpoint Descriptor&lt;===
  bLength:                           0x07
  bDescriptorType:                   0x05
  bEndpointAddress:                  0x84  -&gt; Direction: IN - EndpointID: 4
  bmAttributes:                      0x03  -&gt; Interrupt Transfer Type
  wMaxPacketSize:                  0x0040 = 0x40 bytes
  bInterval:                         0x01
  </code></pre>
  
  <p>How could I get this Leonardo recognized by a BIOS as a generic keyboard?</p>