usb: hid: boot protocol

Set_Protocol and Get_Protocol requests are handled now.
Tested with USB3CV.

Signed-off-by: Marcin Szymczyk <Marcin.Szymczyk@nordicsemi.no>
This commit is contained in:
Marcin Szymczyk 2018-12-12 13:53:16 +01:00 committed by Maureen Helm
commit 801b54edb9
5 changed files with 82 additions and 4 deletions

View file

@ -60,6 +60,7 @@ struct usb_hid_descriptor {
typedef int (*hid_cb_t)(struct usb_setup_packet *setup, s32_t *len,
u8_t **data);
typedef void (*hid_int_ready_callback)(void);
typedef void (*hid_protocol_cb_t)(u8_t protocol);
typedef void (*hid_idle_cb_t)(u16_t report_id);
struct hid_ops {
@ -69,6 +70,7 @@ struct hid_ops {
hid_cb_t set_report;
hid_cb_t set_idle;
hid_cb_t set_protocol;
hid_protocol_cb_t protocol_change;
hid_idle_cb_t on_idle;
/*
* int_in_ready is an optional callback that is called when
@ -162,6 +164,10 @@ struct hid_ops {
#define COLLECTION_PHYSICAL 0x00
#define COLLECTION_APPLICATION 0x01
/* Protocols */
#define HID_PROTOCOL_BOOT 0x00
#define HID_PROTOCOL_REPORT 0x01
/* Register HID device */
void usb_hid_register_device(const u8_t *desc, size_t size,
const struct hid_ops *op);

View file

@ -2,6 +2,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_HID=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr HID sample"
CONFIG_USB_HID_BOOT_PROTOCOL=y
CONFIG_LOG=y
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y

View file

@ -99,10 +99,17 @@ static void idle_cb(u16_t report_id)
LOG_DBG("Idle callback: wrote %d bytes with ret %d", wrote, ret);
}
static void protocol_cb(u8_t protocol)
{
LOG_DBG("New protocol: %s", protocol == HID_PROTOCOL_BOOT ?
"boot" : "report");
}
static const struct hid_ops ops = {
.int_in_ready = in_ready_cb,
.status_cb = status_cb,
.on_idle = idle_cb,
.protocol_change = protocol_cb,
};
void main(void)

View file

@ -45,4 +45,29 @@ config USB_HID_REPORTS
Number of HID reports in the instance.
Must be equal or higher than highest report ID (if they are not consecutive).
config USB_HID_BOOT_PROTOCOL
bool
prompt "Enable USB HID Boot Protocol handling"
help
Sets bInterfaceSubClass to 1 and enables Set_Protocol and Get_Protocol
requests handling.
See Chapter 4.2 of Device Class Definition for Human Interface Devices 1.11
for more information.
if USB_HID_BOOT_PROTOCOL
config USB_HID_PROTOCOL_CODE
int "HID protocol code"
default 0
range 0 2
help
Sets bIntefaceProtocol in HID instance.
0 = None
1 = Keyboard
2 = Mouse
See Chapter 4.3 of Device Class Definition for Human Interface Devices 1.11
for more information.
endif # USB_HID_BOOT_PROTOCOL
endif # USB_DEVICE_HID

View file

@ -44,8 +44,13 @@ USBD_CLASS_DESCR_DEFINE(primary) struct usb_hid_config hid_cfg = {
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = HID_CLASS,
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
.bInterfaceSubClass = 1,
.bInterfaceProtocol = CONFIG_USB_HID_PROTOCOL_CODE,
#else
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
#endif
.iInterface = 0,
},
.if0_hid = {
@ -95,6 +100,9 @@ static struct hid_device_info {
bool idle_id_report;
u8_t idle_rate[CONFIG_USB_HID_REPORTS + 1];
#endif
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
u8_t protocol;
#endif
} hid_device;
static int hid_on_get_idle(struct usb_setup_packet *setup, s32_t *len,
@ -133,11 +141,22 @@ static int hid_on_get_report(struct usb_setup_packet *setup, s32_t *len,
static int hid_on_get_protocol(struct usb_setup_packet *setup, s32_t *len,
u8_t **data)
{
LOG_DBG("Get Protocol callback");
/* TODO: Do something. */
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
if (setup->wValue) {
LOG_ERR("wValue should be 0");
return -ENOTSUP;
}
u32_t size = sizeof(hid_device.protocol);
LOG_DBG("Get Protocol callback, protocol: %d", hid_device.protocol);
*data = &hid_device.protocol;
len = &size;
return 0;
#else
return -ENOTSUP;
#endif
}
static int hid_on_set_idle(struct usb_setup_packet *setup, s32_t *len,
@ -205,11 +224,28 @@ static int hid_on_set_report(struct usb_setup_packet *setup, s32_t *len,
static int hid_on_set_protocol(struct usb_setup_packet *setup, s32_t *len,
u8_t **data)
{
LOG_DBG("Set Protocol callback");
/* TODO: Do something. */
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
u16_t protocol = sys_le16_to_cpu(setup->wValue);
if (protocol > HID_PROTOCOL_REPORT) {
LOG_ERR("Unsupported protocol: %u", protocol);
return -ENOTSUP;
}
LOG_DBG("Set Protocol callback, protocol: %u", protocol);
if (hid_device.protocol != protocol) {
hid_device.protocol = protocol;
if (hid_device.ops && hid_device.ops->protocol_change) {
hid_device.ops->protocol_change(protocol);
}
}
return 0;
#else
return -ENOTSUP;
#endif
}
static void usb_set_hid_report_size(u16_t size)
@ -264,6 +300,9 @@ static void hid_status_cb(enum usb_dc_status_code status, const u8_t *param)
break;
case USB_DC_RESET:
LOG_DBG("USB device reset detected");
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
hid_device.protocol = HID_PROTOCOL_REPORT;
#endif
#ifdef CONFIG_USB_DEVICE_SOF
hid_clear_idle_ctx();
#endif