blob: ff2a10b1ba19b152a815904185ed4e0c6b9be07e [file] [log] [blame]
/*
* Copyright (c) 2018 qianfan Zhao
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <board.h>
#include <device.h>
#include <gpio.h>
#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>
/* change this to use another GPIO port */
#ifndef SW0_GPIO_CONTROLLER
#ifdef SW0_GPIO_NAME
#define SW0_GPIO_CONTROLLER SW0_GPIO_NAME
#else
#error SW0_GPIO_NAME or SW0_GPIO_CONTROLLER needs to be set in board.h
#endif
#endif
#define PORT SW0_GPIO_CONTROLLER
/* change this to use another GPIO pin */
#ifdef SW0_GPIO_PIN
#define PIN SW0_GPIO_PIN
#else
#error SW0_GPIO_PIN needs to be set in board.h
#endif
static const u8_t hid_report_desc[] = {
HID_GI_USAGE_PAGE, USAGE_GEN_DESKTOP,
/* USAGE_PAGE (Generic Desktop) 05 01 */
HID_LI_USAGE, USAGE_GEN_DESKTOP_MOUSE,
/* USAGE (Mouse) 09 02 */
HID_MI_COLLECTION, COLLECTION_APPLICATION,
/* COLLECTION (Application) A1 01 */
HID_LI_USAGE, USAGE_GEN_DESKTOP_POINTER,
/* USAGE (Pointer) 09 01 */
HID_MI_COLLECTION, COLLECTION_PHYSICAL,
/* COLLECTION (Physical) A1 00 */
HID_GI_USAGE_PAGE, USAGE_GEN_BUTTON,
/* USAGE_PAGE (Button) 05 09 */
HID_LI_USAGE_MIN(1), 0x01,
/* USAGE_MINIMUM (Button 1) 19 01 */
HID_LI_USAGE_MAX(1), 0x03,
/* USAGE_MAXIMUM (Button 3) 29 03 */
HID_GI_LOGICAL_MIN(1), 0,
/* LOGICAL_MINIMUM (0) 15 00 */
HID_GI_LOGICAL_MAX(1), 1,
/* LOGICAL_MAXIMUM (1) 25 01 */
HID_GI_REPORT_COUNT, 3,
/* REPORT_COUNT (3) 95 03 */
HID_GI_REPORT_SIZE, 1,
/* REPORT_SIZE (1) 75 01 */
HID_MI_INPUT, 0x02,
/* INPUT (Data,Var,Abs) 81 02 */
HID_GI_REPORT_COUNT, 1,
/* REPORT_COUNT (1) 95 01 */
HID_GI_REPORT_SIZE, 5,
/* REPORT_SIZE (5) 75 05 */
HID_MI_INPUT, 0x01,
/* INPUT (Cnst,Ary,Abs) 81 01 */
HID_GI_USAGE_PAGE, USAGE_GEN_DESKTOP,
/* USAGE_PAGE (Generic Desktop) 05 01 */
HID_LI_USAGE, USAGE_GEN_DESKTOP_X,
/* USAGE (X) 09 30 */
HID_LI_USAGE, USAGE_GEN_DESKTOP_Y,
/* USAGE (Y) 09 31 */
HID_LI_USAGE, USAGE_GEN_DESKTOP_WHEEL,
/* USAGE (Wheel) 09 38 */
HID_GI_LOGICAL_MIN(1), -127,
/* LOGICAL_MINIMUM (-127) 15 81 */
HID_GI_LOGICAL_MAX(1), 127,
/* LOGICAL_MAXIMUM (127) 25 7F */
HID_GI_REPORT_SIZE, 8,
/* REPORT_SIZE (8) 75 08 */
HID_GI_REPORT_COUNT, 3,
/* REPORT_COUNT (3) 95 03 */
HID_MI_INPUT, 0x06,
/* INPUT (Data,Var,Rel) 81 06 */
HID_MI_COLLECTION_END,
/* END_COLLECTION C0 */
HID_MI_COLLECTION_END,
/* END_COLLECTION C0 */
};
static int get_report_cb(struct usb_setup_packet *setup, s32_t *len,
u8_t **data)
{
*len = sizeof(hid_report_desc);
*data = (u8_t *)hid_report_desc;
return 0;
}
static struct hid_ops ops = {
.get_report = get_report_cb,
};
static int def_val;
static volatile int status;
static K_SEM_DEFINE(sem, 0, 1); /* starts off "not available" */
#define MOUSE_BTN_LEFT BIT(0)
#define MOUSE_BTN_RIGHT BIT(1)
#define MOUSE_BTN_MIDDLE BIT(2)
void button_pressed(struct device *gpio, struct gpio_callback *cb,
u32_t pins)
{
int cur_val, state = status;
gpio_pin_read(gpio, PIN, &cur_val);
if (def_val != cur_val) {
state |= MOUSE_BTN_LEFT;
} else {
state &= ~MOUSE_BTN_LEFT;
}
if (state != status) {
status = state;
k_sem_give(&sem);
}
}
void main(void)
{
struct device *gpio;
struct gpio_callback gpio_cb;
u8_t report[4] = { 0x00 };
gpio = device_get_binding(PORT);
if (!gpio) {
printk("error\n");
return;
}
gpio_pin_configure(gpio, PIN,
GPIO_DIR_IN | GPIO_INT |
GPIO_INT_EDGE | GPIO_INT_DOUBLE_EDGE);
gpio_pin_read(gpio, PIN, &def_val);
gpio_init_callback(&gpio_cb, button_pressed, BIT(PIN));
gpio_add_callback(gpio, &gpio_cb);
gpio_pin_enable_callback(gpio, PIN);
usb_hid_register_device(hid_report_desc, sizeof(hid_report_desc), &ops);
usb_hid_init();
while (true) {
k_sem_take(&sem, K_FOREVER);
report[0] = status;
usb_write(CONFIG_HID_INT_EP_ADDR, report,
sizeof(report), NULL);
}
}