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:
parent
4446b16e24
commit
801b54edb9
5 changed files with 82 additions and 4 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue