PIC18F47J53 as usb HID Keyboard compatibility issues?

Discussion on projects that are created by users and posted on mikroElektronika website.
Post Reply
Author
Message
jrgdiaz
Posts: 1
Joined: 22 Nov 2017 18:55

PIC18F47J53 as usb HID Keyboard compatibility issues?

#1 Post by jrgdiaz » 22 Nov 2017 19:00

Hello, i was searching for some sample code to help me get started on creating a device that would emulate a USB HID Keyboard, i found some code browsing the Internet The code was shared by Emil Enchev on libstock. I tested it on a PIC18F47J53, the code works great for Windows7 (the microcontroller is detected and i'm able to reproduce some typing on screen). On Linux the device is detected as a Keyboard right away, which is great but i'm not able to reproduce typing on screen, which is odd. so i did some research and stumbled upon a tool that is able to listen for keyboard events at kernel level, the tool is called "evtest", when i plug the microcontroller in and the code begins to run, evtest is able to pick up the microcontroller's "keyboard" events but no typing is shown on screen :( I did some more research on the issue and found out that Linux's X.org server (which is used to map kernel level keycodes into actual ASCII for screen display) might not be interpreting the microcontrollers keycodes correctly. How can i get the microcontroller to send keyboard events that Linux will interpret correctly and display them on screen? Any help or example that would point me in the right way to achieve compatibility with Linux is appreciated :). I tested it on two Linux distros (Arch and Ubuntu) but no luck. The following code is the usb descriptor i found on the link, maybe it's missing something?

Code: Select all

const unsigned int USB_VENDOR_ID = 0x4406;
const unsigned int USB_PRODUCT_ID = 0x0007;
const char USB_SELF_POWER = 0x80; // Self powered 0xC0, 0x80 bus powered
const char USB_MAX_POWER = 50; // Bus power required in units of 2 mA
const char HID_INPUT_REPORT_BYTES = 64;
const char HID_OUTPUT_REPORT_BYTES = 64;
const char USB_TRANSFER_TYPE = 0x03; //0x03 Interrupt
const char EP_IN_INTERVAL = 1;
const char EP_OUT_INTERVAL = 1;

const char USB_INTERRUPT = 1;
const char USB_HID_EP = 1;
const char USB_HID_RPT_SIZE = 63;

/* Device Descriptor */
const struct {
    char bLength; // bLength - Descriptor size in bytes (12h)
    char bDescriptorType; // bDescriptorType - The constant DEVICE (01h)
    unsigned int bcdUSB; // bcdUSB - USB specification release number (BCD)
    char bDeviceClass; // bDeviceClass - Class Code
    char bDeviceSubClass; // bDeviceSubClass - Subclass code
    char bDeviceProtocol; // bDeviceProtocol - Protocol code
    char bMaxPacketSize0; // bMaxPacketSize0 - Maximum packet size for endpoint 0
    unsigned int idVendor; // idVendor - Vendor ID
    unsigned int idProduct; // idProduct - Product ID
    unsigned int bcdDevice; // bcdDevice - Device release number (BCD)
    char iManufacturer; // iManufacturer - Index of string descriptor for the manufacturer
    char iProduct; // iProduct - Index of string descriptor for the product.
    char iSerialNumber; // iSerialNumber - Index of string descriptor for the serial number.
    char bNumConfigurations; // bNumConfigurations - Number of possible configurations
} device_dsc = {
      0x12, // bLength
      0x01, // bDescriptorType
      0x0200, // bcdUSB
      0x00, // bDeviceClass
      0x00, // bDeviceSubClass
      0x00, // bDeviceProtocol
      8, // bMaxPacketSize0
      USB_VENDOR_ID, // idVendor
      USB_PRODUCT_ID, // idProduct
      0x0001, // bcdDevice
      0x01, // iManufacturer
      0x02, // iProduct
      0x00, // iSerialNumber
      0x01 // bNumConfigurations
  };

/* Configuration 1 Descriptor */
const char configDescriptor1[]= {
    // Configuration Descriptor
    0x09, // bLength - Descriptor size in bytes
    0x02, // bDescriptorType - The constant CONFIGURATION (02h)
    0x29,0x00, // wTotalLength - The number of bytes in the configuration descriptor and all of its subordinate descriptors
    1, // bNumInterfaces - Number of interfaces in the configuration
    1, // bConfigurationValue - Identifier for Set Configuration and Get Configuration requests
    0, // iConfiguration - Index of string descriptor for the configuration
    USB_SELF_POWER, // bmAttributes - Self/bus power and remote wakeup settings
    USB_MAX_POWER, // bMaxPower - Bus power required in units of 2 mA

    // Interface Descriptor
    0x09, // bLength - Descriptor size in bytes (09h)
    0x04, // bDescriptorType - The constant Interface (04h)
    0, // bInterfaceNumber - Number identifying this interface
    0, // bAlternateSetting - A number that identifies a descriptor with alternate settings for this bInterfaceNumber.
    2, // bNumEndpoint - Number of endpoints supported not counting endpoint zero
    0x03, // bInterfaceClass - Class code
    0, // bInterfaceSubclass - Subclass code
    0, // bInterfaceProtocol - Protocol code
    0, // iInterface - Interface string index

    // HID Class-Specific Descriptor
    0x09, // bLength - Descriptor size in bytes.
    0x21, // bDescriptorType - This descriptor's type: 21h to indicate the HID class.
    0x11,0x01, // bcdHID - HID specification release number (BCD).
    0x00, // bCountryCode - Numeric expression identifying the country for localized hardware (BCD) or 00h.
    1, // bNumDescriptors - Number of subordinate report and physical descriptors.
    0x22, // bDescriptorType - The type of a class-specific descriptor that follows
    USB_HID_RPT_SIZE,0x00, // wDescriptorLength - Total length of the descriptor identified above.

    // Endpoint Descriptor
    0x07, // bLength - Descriptor size in bytes (07h)
    0x05, // bDescriptorType - The constant Endpoint (05h)
    USB_HID_EP | 0x80, // bEndpointAddress - Endpoint number and direction
    USB_TRANSFER_TYPE, // bmAttributes - Transfer type and supplementary information 
    0x40,0x00, // wMaxPacketSize - Maximum packet size supported
    EP_IN_INTERVAL, // bInterval - Service interval or NAK rate

    // Endpoint Descriptor
    0x07, // bLength - Descriptor size in bytes (07h)
    0x05, // bDescriptorType - The constant Endpoint (05h)
    USB_HID_EP, // bEndpointAddress - Endpoint number and direction
    USB_TRANSFER_TYPE, // bmAttributes - Transfer type and supplementary information
    0x40,0x00, // wMaxPacketSize - Maximum packet size supported 
    EP_OUT_INTERVAL // bInterval - Service interval or NAK rate
};

const struct {
  char report[];
}hid_rpt_desc =
  {

 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x01, // LOGICAL_MAXIMUM (1)
 0x75, 0x01, // REPORT_SIZE (1)
 0x95, 0x08, // REPORT_COUNT (8)
 0x81, 0x02, // INPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x08, // REPORT_SIZE (8)
 0x81, 0x03, // INPUT (Cnst,Var,Abs)
 0x95, 0x05, // REPORT_COUNT (5)
 0x75, 0x01, // REPORT_SIZE (1)
 0x05, 0x08, // USAGE_PAGE (LEDs)
 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
 0x29, 0x05, // USAGE_MAXIMUM (Kana)
 0x91, 0x02, // OUTPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x03, // REPORT_SIZE (3)
 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
 0x95, 0x06, // REPORT_COUNT (6)
 0x75, 0x08, // REPORT_SIZE (8)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x65, // LOGICAL_MAXIMUM (101)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, // INPUT (Data,Ary,Abs)
 0xc0 // End Collection


  };

//Language code string descriptor
const struct {
  char bLength;
  char bDscType;
  unsigned int string[1];
  } strd1 = {
      4,
      0x03,
      {0x0409}
    };


//Manufacturer string descriptor
const struct{
  char bLength;
  char bDscType;
  unsigned int string[10];
  }strd2={
    22, //sizeof this descriptor string
    0x03,
    {'T','U',' ','G','a','b','r','o','v','o'}
  };

//Product string descriptor
const struct{
  char bLength;
  char bDscType;
  unsigned int string[15];
}strd3={
    32, //sizeof this descriptor string
    0x03,
    {'U','S','B',' ','M','a','n','i','p','u','l','a','t','o','r'}
 };

//Array of configuration descriptors
const char* USB_config_dsc_ptr[1];

//Array of string descriptors
const char* USB_string_dsc_ptr[3];

void USB_Init_Desc(){
  USB_config_dsc_ptr[0] = &configDescriptor1;
  USB_string_dsc_ptr[0] = (const char*)&strd1;
  USB_string_dsc_ptr[1] = (const char*)&strd2;
  USB_string_dsc_ptr[2] = (const char*)&strd3;
}

Forward Edit  #1

Post Reply

Return to “User Projects”