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

View file

@ -2,6 +2,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_HID=y CONFIG_USB_DEVICE_HID=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr HID sample" CONFIG_USB_DEVICE_PRODUCT="Zephyr HID sample"
CONFIG_USB_HID_BOOT_PROTOCOL=y
CONFIG_LOG=y CONFIG_LOG=y
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=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); 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 = { static const struct hid_ops ops = {
.int_in_ready = in_ready_cb, .int_in_ready = in_ready_cb,
.status_cb = status_cb, .status_cb = status_cb,
.on_idle = idle_cb, .on_idle = idle_cb,
.protocol_change = protocol_cb,
}; };
void main(void) void main(void)

View file

@ -45,4 +45,29 @@ config USB_HID_REPORTS
Number of HID reports in the instance. Number of HID reports in the instance.
Must be equal or higher than highest report ID (if they are not consecutive). 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 endif # USB_DEVICE_HID

View file

@ -44,8 +44,13 @@ USBD_CLASS_DESCR_DEFINE(primary) struct usb_hid_config hid_cfg = {
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 1, .bNumEndpoints = 1,
.bInterfaceClass = HID_CLASS, .bInterfaceClass = HID_CLASS,
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
.bInterfaceSubClass = 1,
.bInterfaceProtocol = CONFIG_USB_HID_PROTOCOL_CODE,
#else
.bInterfaceSubClass = 0, .bInterfaceSubClass = 0,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
#endif
.iInterface = 0, .iInterface = 0,
}, },
.if0_hid = { .if0_hid = {
@ -95,6 +100,9 @@ static struct hid_device_info {
bool idle_id_report; bool idle_id_report;
u8_t idle_rate[CONFIG_USB_HID_REPORTS + 1]; u8_t idle_rate[CONFIG_USB_HID_REPORTS + 1];
#endif #endif
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
u8_t protocol;
#endif
} hid_device; } hid_device;
static int hid_on_get_idle(struct usb_setup_packet *setup, s32_t *len, 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, static int hid_on_get_protocol(struct usb_setup_packet *setup, s32_t *len,
u8_t **data) u8_t **data)
{ {
LOG_DBG("Get Protocol callback"); #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
if (setup->wValue) {
LOG_ERR("wValue should be 0");
return -ENOTSUP;
}
/* TODO: Do something. */ 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; return -ENOTSUP;
#endif
} }
static int hid_on_set_idle(struct usb_setup_packet *setup, s32_t *len, 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, static int hid_on_set_protocol(struct usb_setup_packet *setup, s32_t *len,
u8_t **data) u8_t **data)
{ {
LOG_DBG("Set Protocol callback"); #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
u16_t protocol = sys_le16_to_cpu(setup->wValue);
/* TODO: Do something. */ 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; return -ENOTSUP;
#endif
} }
static void usb_set_hid_report_size(u16_t size) 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; break;
case USB_DC_RESET: case USB_DC_RESET:
LOG_DBG("USB device reset detected"); LOG_DBG("USB device reset detected");
#ifdef CONFIG_USB_HID_BOOT_PROTOCOL
hid_device.protocol = HID_PROTOCOL_REPORT;
#endif
#ifdef CONFIG_USB_DEVICE_SOF #ifdef CONFIG_USB_DEVICE_SOF
hid_clear_idle_ctx(); hid_clear_idle_ctx();
#endif #endif