AnsweredAssumed Answered

USB HID Keyboard Device, Interrupts, and NAK

Question asked by Brad Hughes on Aug 8, 2016
Latest reply on Aug 9, 2016 by Brad Hughes

Hi Everyone!

 

I have a KDS 3.2.0 project setup for a client with SDK 2.0.

 

The USB descriptor structure is a USB Composite device with one USB HID device. The HID device had one HID report that includes descriptors for two different TLC report IDs. One report is for keyboard (report ID = 1) and one of the reports is for volume (report ID = 2).

 

For the second report ID, I've implemented Consumer Device Control to control volume. On the hardware, there are two buttons: vol up and vol down.

 

(By the way - the USB descriptor, enumeration, and HID report descriptors are all correct and debugged (using a Total Phase USB Debugger.))

 

Here's the report descriptor just for fun:

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls) 0x09, 0x06,        // Usage (Keyboard) 0xA1, 0x01,        // Collection (Application) 0x85, 0x01,        //   Report ID (1) 0x75, 0x01,        //   Report Size (1) 0x95, 0x08,        //   Report Count (8) 0x05, 0x07,        //   Usage Page (Kbrd/Keypad) 0x19, 0xE0,        //   Usage Minimum (0xE0) 0x29, 0xE7,        //   Usage Maximum (0xE7) 0x15, 0x00,        //   Logical Minimum (0) 0x25, 0x01,        //   Logical Maximum (1) 0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x01,        //   Report Count (1) 0x75, 0x08,        //   Report Size (8) 0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x06,        //   Report Count (6) 0x75, 0x08,        //   Report Size (8) 0x15, 0x00,        //   Logical Minimum (0) 0x25, 0xFF,        //   Logical Maximum (255) 0x05, 0x07,        //   Usage Page (Kbrd/Keypad) 0x19, 0x00,        //   Usage Minimum (0x00) 0x29, 0xFF,        //   Usage Maximum (0xFF) 0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0,              // End Collection 0x05, 0x0C,        // Usage Page (Consumer) 0x09, 0x01,        // Usage (Consumer Control) 0xA1, 0x01,        // Collection (Application) 0x85, 0x02,        //   Report ID (2) 0x05, 0x0C,        //   Usage Page (Consumer) 0x19, 0x00,        //   Usage Minimum (Unassigned) 0x2A, 0xFF, 0x03,  //   Usage Maximum (0x03FF) 0x95, 0x01,        //   Report Count (1) 0x75, 0x10,        //   Report Size (16) 0x15, 0x00,        //   Logical Minimum (0) 0x27, 0xFF, 0x03, 0x00, 0x00,  //   Logical Maximum (1023) 0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0,              // End Collection

 

In order to get expected O/S (Windows, Mac, Linux, etc...) volume control behavior, I need to only send reports when the key is initially pressed - and then send no reports until the key is released.

 

For example:

* user presses volume up key *

[Interrupt] IN 0x02 0xE9 0x00

[Interrupt] NAK

[Interrupt] NAK

...

* user releases volume up key *

[Interrupt] NAK 0x00 0x00

 

In hid_keyboard.c, the example's code structure is setup so that USB_DeviceHidKeyboardCallback gets called back when the interrupt comes from the USB subsystem to transmit a packet for my endpoint. If the device is attached, then USB_DeviceHidKeyboardAction is called. The examples always send data back with USB_DeviceHidSend.

 

If I don't call USB_DeviceHidSend, the device seems to stop communicating with the host altogether. No future events are communicated, (nor is USB_DeviceHidKeyboardCallback ever called again.)

 

I tried calling USB_DeviceHidSend with length = 0, and yielded USB errors (since this is an invalid report based on my report descriptor.)

 

Instead of always sending back DATA, I need to send back a NAK, indicating to the USB Host that nothing has changed. Any USB gurus or experts know if there a way to do this?

 

I did a search through the source code for NAK and didn't find much... and I read through the USB FS reference manual and didn't see much by way of setting any registers that would yield a NAK.

 

My workaround right now is to send a report for the keyboard - report ID = 1. Anyone aware of why this might be a bad idea?

 

Thanks in advance, folks!

Outcomes