Some initial BEL HoG support.
This commit is contained in:
parent
04fe57d3a3
commit
73bea6218e
13 changed files with 523 additions and 160 deletions
|
@ -12,7 +12,10 @@ project(zmk)
|
||||||
target_include_directories(app PRIVATE include)
|
target_include_directories(app PRIVATE include)
|
||||||
target_sources(app PRIVATE src/kscan.c)
|
target_sources(app PRIVATE src/kscan.c)
|
||||||
target_sources(app PRIVATE src/keymap.c)
|
target_sources(app PRIVATE src/keymap.c)
|
||||||
|
target_sources(app PRIVATE src/hid.c)
|
||||||
|
target_sources(app PRIVATE src/ble.c)
|
||||||
target_sources(app PRIVATE src/usb_hid.c)
|
target_sources(app PRIVATE src/usb_hid.c)
|
||||||
|
target_sources(app PRIVATE src/hog.c)
|
||||||
target_sources(app PRIVATE src/endpoints.c)
|
target_sources(app PRIVATE src/endpoints.c)
|
||||||
target_sources(app PRIVATE src/main.c)
|
target_sources(app PRIVATE src/main.c)
|
||||||
target_sources(app PRIVATE src/handlers.c)
|
target_sources(app PRIVATE src/handlers.c)
|
||||||
|
|
22
prj.conf
22
prj.conf
|
@ -1,9 +1,29 @@
|
||||||
CONFIG_KSCAN=y
|
CONFIG_KSCAN=y
|
||||||
CONFIG_KSCAN_GPIO=y
|
CONFIG_KSCAN_GPIO=y
|
||||||
# CONFIG_LOG=y
|
|
||||||
# CONFIG_ZMK_KSCAN_LOG_LEVEL_DBG=y
|
# CONFIG_ZMK_KSCAN_LOG_LEVEL_DBG=y
|
||||||
# CONFIG_ZMK_USB_HID_LOG_LEVEL_DBG=y
|
# CONFIG_ZMK_USB_HID_LOG_LEVEL_DBG=y
|
||||||
CONFIG_USB=y
|
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="ZMK Firmware"
|
CONFIG_USB_DEVICE_PRODUCT="ZMK Firmware"
|
||||||
|
CONFIG_BT=y
|
||||||
|
CONFIG_BT_SMP=y
|
||||||
|
CONFIG_BT_PERIPHERAL=y
|
||||||
|
CONFIG_BT_GATT_DIS=y
|
||||||
|
# HID GATT notifications sent this way are *not* picked up by Linux, and possibly others.
|
||||||
|
CONFIG_BT_GATT_NOTIFY_MULTIPLE=n
|
||||||
|
CONFIG_BT_GATT_BAS=y
|
||||||
|
CONFIG_BT_DEVICE_NAME="ZMK Keyboard"
|
||||||
|
CONFIG_BT_DEVICE_APPEARANCE=961
|
||||||
|
CONFIG_BT_FIXED_PASSKEY=y
|
||||||
|
|
||||||
|
# Incresed stack due to settings API usage
|
||||||
|
# CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
|
||||||
|
#
|
||||||
|
# CONFIG_BT_SETTINGS=y
|
||||||
|
# CONFIG_FLASH=y
|
||||||
|
# CONFIG_FLASH_PAGE_LAYOUT=y
|
||||||
|
# CONFIG_FLASH_MAP=y
|
||||||
|
# CONFIG_NVS=y
|
||||||
|
# CONFIG_SETTINGS=y
|
||||||
|
# CONFIG_SETTINGS_NONE=n
|
||||||
|
|
136
src/ble.c
Normal file
136
src/ble.c
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
|
||||||
|
#include <settings/settings.h>
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/conn.h>
|
||||||
|
#include <bluetooth/hci.h>
|
||||||
|
#include <bluetooth/uuid.h>
|
||||||
|
#include <bluetooth/gatt.h>
|
||||||
|
|
||||||
|
static void connected(struct bt_conn *conn, u8_t err)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("Failed to connect to %s (%u)\n", addr, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Connected %s\n", addr);
|
||||||
|
|
||||||
|
// if (bt_conn_set_security(conn, BT_SECURITY_L0))
|
||||||
|
// {
|
||||||
|
// printk("Failed to set security\n");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disconnected(struct bt_conn *conn, u8_t reason)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
printk("Disconnected from %s (reason 0x%02x)\n", addr, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void security_changed(struct bt_conn *conn, bt_security_t level,
|
||||||
|
enum bt_security_err err)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
printk("Security changed: %s level %u\n", addr, level);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printk("Security failed: %s level %u err %d\n", addr, level,
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_conn_cb conn_callbacks = {
|
||||||
|
.connected = connected,
|
||||||
|
.disconnected = disconnected,
|
||||||
|
.security_changed = security_changed,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
printk("Passkey for %s: %06u\n", addr, passkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void auth_cancel(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
printk("Pairing cancelled: %s\n", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
|
||||||
|
.passkey_display = auth_passkey_display,
|
||||||
|
.passkey_entry = NULL,
|
||||||
|
.cancel = auth_cancel,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct bt_data zmk_ble_ad[] = {
|
||||||
|
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||||
|
BT_DATA_BYTES(BT_DATA_UUID16_ALL,
|
||||||
|
0x12, 0x18, /* HID Service */
|
||||||
|
0x0f, 0x18), /* Battery Service */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void zmk_ble_ready(int err)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("Bluetooth init failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Bluetooth initialized\n");
|
||||||
|
|
||||||
|
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("Advertising failed to start (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_ble_init()
|
||||||
|
{
|
||||||
|
if (IS_ENABLED(CONFIG_SETTINGS))
|
||||||
|
{
|
||||||
|
settings_load();
|
||||||
|
}
|
||||||
|
int err = bt_enable(zmk_ble_ready);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("BLUETOOTH FAILED");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// err = bt_passkey_set(1234);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("Set passkey failed: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_conn_cb_register(&conn_callbacks);
|
||||||
|
bt_conn_auth_cb_register(&zmk_ble_auth_cb_display);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
4
src/ble.h
Normal file
4
src/ble.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int zmk_ble_init();
|
|
@ -1,16 +1,52 @@
|
||||||
|
|
||||||
#include "endpoints.h"
|
#include "endpoints.h"
|
||||||
|
#include "hid.h"
|
||||||
#include "usb_hid.h"
|
#include "usb_hid.h"
|
||||||
|
#include "hog.h"
|
||||||
|
|
||||||
|
int zmk_endpoints_init()
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = zmk_usb_hid_init();
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("USB HID Init Failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zmk_hog_init();
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printk("HOG Init Failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
|
int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
|
||||||
{
|
{
|
||||||
|
struct zmk_hid_report *report;
|
||||||
if (key_event.pressed)
|
if (key_event.pressed)
|
||||||
{
|
{
|
||||||
zmk_usb_hid_press_key(key_event.key);
|
zmk_hid_press_key(key_event.key);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
zmk_usb_hid_release_key(key_event.key);
|
zmk_hid_release_key(key_event.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
report = zmk_hid_get_report();
|
||||||
|
|
||||||
|
// if (zmk_usb_hid_send_report(report) != 0)
|
||||||
|
// {
|
||||||
|
// // LOG_DBG("USB Send Failed");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (zmk_hog_send_report(report) != 0)
|
||||||
|
{
|
||||||
|
// LOG_DBG("HID Over GATTP Send Failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
|
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
|
||||||
|
int zmk_endpoints_init();
|
||||||
int zmk_endpoints_send_key_event(struct zmk_key_event key_event);
|
int zmk_endpoints_send_key_event(struct zmk_key_event key_event);
|
56
src/hid.c
Normal file
56
src/hid.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
|
static struct zmk_hid_report report = {
|
||||||
|
.modifiers = 0,
|
||||||
|
.keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
|
|
||||||
|
#define KEY_OFFSET 0x02
|
||||||
|
#define MAX_KEYS 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define TOGGLE_BOOT_KEY(match, val) \
|
||||||
|
for (int idx = 0; idx < MAX_KEYS; idx++) \
|
||||||
|
{ \
|
||||||
|
if (report.boot.keys[idx + KEY_OFFSET] != match) \
|
||||||
|
{ \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
report.boot.keys[idx + KEY_OFFSET] = val; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TOGGLE_KEY(code, val) WRITE_BIT(report.keys[code / 8], code % 8, val)
|
||||||
|
|
||||||
|
int zmk_hid_press_key(zmk_key code)
|
||||||
|
{
|
||||||
|
if (code > ZMK_HID_MAX_KEYCODE)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOGGLE_BOOT_KEY(0U, code);
|
||||||
|
|
||||||
|
TOGGLE_KEY(code, true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int zmk_hid_release_key(zmk_key code)
|
||||||
|
{
|
||||||
|
if (code > ZMK_HID_MAX_KEYCODE)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOGGLE_BOOT_KEY(code, 0U);
|
||||||
|
|
||||||
|
TOGGLE_KEY(code, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zmk_hid_report *zmk_hid_get_report()
|
||||||
|
{
|
||||||
|
return &report;
|
||||||
|
}
|
107
src/hid.h
Normal file
107
src/hid.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <usb/usb_device.h>
|
||||||
|
#include <usb/class/usb_hid.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
|
#define ZMK_HID_MAX_KEYCODE KC_APP
|
||||||
|
|
||||||
|
static const u8_t zmk_hid_report_desc[] = {
|
||||||
|
/* USAGE_PAGE (Generic Desktop) */
|
||||||
|
HID_GI_USAGE_PAGE,
|
||||||
|
USAGE_GEN_DESKTOP,
|
||||||
|
/* USAGE (Keyboard) */
|
||||||
|
HID_LI_USAGE,
|
||||||
|
USAGE_GEN_DESKTOP_KEYBOARD,
|
||||||
|
/* COLLECTION (Application) */
|
||||||
|
HID_MI_COLLECTION,
|
||||||
|
COLLECTION_APPLICATION,
|
||||||
|
/* REPORT ID (1) */
|
||||||
|
HID_GI_REPORT_ID,
|
||||||
|
0x01,
|
||||||
|
/* USAGE_PAGE (Keypad) */
|
||||||
|
HID_GI_USAGE_PAGE,
|
||||||
|
USAGE_GEN_DESKTOP_KEYPAD,
|
||||||
|
/* USAGE_MINIMUM (Keyboard LeftControl) */
|
||||||
|
HID_LI_USAGE_MIN(1),
|
||||||
|
0xE0,
|
||||||
|
/* USAGE_MAXIMUM (Keyboard Right GUI) */
|
||||||
|
HID_LI_USAGE_MAX(1),
|
||||||
|
0xE7,
|
||||||
|
/* LOGICAL_MINIMUM (0) */
|
||||||
|
HID_GI_LOGICAL_MIN(1),
|
||||||
|
0x00,
|
||||||
|
/* LOGICAL_MAXIMUM (1) */
|
||||||
|
HID_GI_LOGICAL_MAX(1),
|
||||||
|
0x01,
|
||||||
|
|
||||||
|
/* REPORT_SIZE (1) */
|
||||||
|
HID_GI_REPORT_SIZE,
|
||||||
|
0x01,
|
||||||
|
/* REPORT_COUNT (8) */
|
||||||
|
HID_GI_REPORT_COUNT,
|
||||||
|
0x08,
|
||||||
|
/* INPUT (Data,Var,Abs) */
|
||||||
|
HID_MI_INPUT,
|
||||||
|
0x02,
|
||||||
|
|
||||||
|
/* USAGE_PAGE (Keypad) */
|
||||||
|
HID_GI_USAGE_PAGE,
|
||||||
|
USAGE_GEN_DESKTOP_KEYPAD,
|
||||||
|
/* LOGICAL_MINIMUM (0) */
|
||||||
|
HID_GI_LOGICAL_MIN(1),
|
||||||
|
0x00,
|
||||||
|
/* LOGICAL_MAXIMUM (101) */
|
||||||
|
HID_GI_LOGICAL_MAX(1),
|
||||||
|
0x01,
|
||||||
|
/* USAGE_MINIMUM (Reserved) */
|
||||||
|
HID_LI_USAGE_MIN(1),
|
||||||
|
0x00,
|
||||||
|
/* USAGE_MAXIMUM (Keyboard Application) */
|
||||||
|
HID_LI_USAGE_MAX(1),
|
||||||
|
ZMK_HID_MAX_KEYCODE,
|
||||||
|
/* REPORT_SIZE (8) */
|
||||||
|
HID_GI_REPORT_SIZE,
|
||||||
|
0x01,
|
||||||
|
/* REPORT_COUNT (6) */
|
||||||
|
HID_GI_REPORT_COUNT,
|
||||||
|
ZMK_HID_MAX_KEYCODE + 1,
|
||||||
|
/* INPUT (Data,Ary,Abs) */
|
||||||
|
HID_MI_INPUT,
|
||||||
|
0x02,
|
||||||
|
/* USAGE_PAGE (Keypad) */
|
||||||
|
HID_GI_USAGE_PAGE,
|
||||||
|
USAGE_GEN_DESKTOP_KEYPAD,
|
||||||
|
/* REPORT_SIZE (8) */
|
||||||
|
HID_GI_REPORT_SIZE,
|
||||||
|
0x02,
|
||||||
|
/* REPORT_COUNT (6) */
|
||||||
|
HID_GI_REPORT_COUNT,
|
||||||
|
0x01,
|
||||||
|
/* INPUT (Cnst,Var,Abs) */
|
||||||
|
HID_MI_INPUT,
|
||||||
|
0x03,
|
||||||
|
/* END_COLLECTION */
|
||||||
|
HID_MI_COLLECTION_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct zmk_hid_boot_report
|
||||||
|
// {
|
||||||
|
// u8_t modifiers;
|
||||||
|
// u8_t _unused;
|
||||||
|
// u8_t keys[6];
|
||||||
|
// } __packed;
|
||||||
|
|
||||||
|
struct zmk_hid_report
|
||||||
|
{
|
||||||
|
u8_t modifiers;
|
||||||
|
u8_t keys[13];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
int zmk_hid_press_key(zmk_key key);
|
||||||
|
int zmk_hid_release_key(zmk_key key);
|
||||||
|
|
||||||
|
struct zmk_hid_report *zmk_hid_get_report();
|
136
src/hog.c
Normal file
136
src/hog.c
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
#include <settings/settings.h>
|
||||||
|
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/gatt.h>
|
||||||
|
|
||||||
|
#include "ble.h"
|
||||||
|
#include "hog.h"
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
|
int zmk_hog_init()
|
||||||
|
{
|
||||||
|
return zmk_ble_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HIDS_REMOTE_WAKE = BIT(0),
|
||||||
|
HIDS_NORMALLY_CONNECTABLE = BIT(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hids_info
|
||||||
|
{
|
||||||
|
u16_t version; /* version number of base USB HID Specification */
|
||||||
|
u8_t code; /* country HID Device hardware is localized for. */
|
||||||
|
u8_t flags;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct hids_report
|
||||||
|
{
|
||||||
|
u8_t id; /* report id */
|
||||||
|
u8_t type; /* report type */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
static struct hids_info info = {
|
||||||
|
.version = 0x0000,
|
||||||
|
.code = 0x00,
|
||||||
|
.flags = HIDS_NORMALLY_CONNECTABLE & HIDS_REMOTE_WAKE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HIDS_INPUT = 0x01,
|
||||||
|
HIDS_OUTPUT = 0x02,
|
||||||
|
HIDS_FEATURE = 0x03,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct hids_report input = {
|
||||||
|
.id = 0x01,
|
||||||
|
.type = HIDS_INPUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool host_requests_notification = false;
|
||||||
|
static u8_t ctrl_point;
|
||||||
|
// static u8_t proto_mode;
|
||||||
|
|
||||||
|
static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
|
||||||
|
{
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
|
||||||
|
{
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_report));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
|
||||||
|
{
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, zmk_hid_report_desc, sizeof(zmk_hid_report_desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
|
||||||
|
{
|
||||||
|
struct zmk_hid_report *report = zmk_hid_get_report();
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, report, sizeof(struct zmk_hid_report));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static ssize_t write_proto_mode(struct bt_conn *conn,
|
||||||
|
// const struct bt_gatt_attr *attr,
|
||||||
|
// const void *buf, u16_t len, u16_t offset,
|
||||||
|
// u8_t flags)
|
||||||
|
// {
|
||||||
|
// printk("PROTO CHANGED\n");
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
static void input_ccc_changed(const struct bt_gatt_attr *attr, u16_t value)
|
||||||
|
{
|
||||||
|
host_requests_notification = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t write_ctrl_point(struct bt_conn *conn,
|
||||||
|
const struct bt_gatt_attr *attr,
|
||||||
|
const void *buf, u16_t len, u16_t offset,
|
||||||
|
u8_t flags)
|
||||||
|
{
|
||||||
|
u8_t *value = attr->user_data;
|
||||||
|
|
||||||
|
if (offset + len > sizeof(ctrl_point))
|
||||||
|
{
|
||||||
|
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(value + offset, buf, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HID Service Declaration */
|
||||||
|
BT_GATT_SERVICE_DEFINE(hog_svc,
|
||||||
|
BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
|
||||||
|
// BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
|
||||||
|
// BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode),
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ,
|
||||||
|
BT_GATT_PERM_READ, read_hids_info, NULL, &info),
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ,
|
||||||
|
BT_GATT_PERM_READ, read_hids_report_map, NULL, NULL),
|
||||||
|
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
|
||||||
|
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
|
||||||
|
BT_GATT_PERM_READ_AUTHEN,
|
||||||
|
// BT_GATT_PERM_READ,
|
||||||
|
read_hids_input_report, NULL, NULL),
|
||||||
|
BT_GATT_CCC(input_ccc_changed,
|
||||||
|
BT_GATT_PERM_READ_AUTHEN | BT_GATT_PERM_WRITE_AUTHEN),
|
||||||
|
// BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
|
||||||
|
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ,
|
||||||
|
read_hids_report_ref, NULL, &input),
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT,
|
||||||
|
BT_GATT_CHRC_WRITE_WITHOUT_RESP,
|
||||||
|
BT_GATT_PERM_WRITE,
|
||||||
|
NULL, write_ctrl_point, &ctrl_point));
|
||||||
|
|
||||||
|
int zmk_hog_send_report(struct zmk_hid_report *report)
|
||||||
|
{
|
||||||
|
return bt_gatt_notify(NULL, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_report));
|
||||||
|
};
|
9
src/hog.h
Normal file
9
src/hog.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "keys.h"
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
|
int zmk_hog_init();
|
||||||
|
|
||||||
|
int zmk_hog_send_report(struct zmk_hid_report *report);
|
11
src/main.c
11
src/main.c
|
@ -10,20 +10,21 @@
|
||||||
|
|
||||||
#include "zmk.h"
|
#include "zmk.h"
|
||||||
#include "kscan.h"
|
#include "kscan.h"
|
||||||
#include "usb_hid.h"
|
#include "endpoints.h"
|
||||||
|
|
||||||
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
|
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
printk("Welcome to ZMK!\n");
|
printk("Welcome to ZMK!\n");
|
||||||
|
|
||||||
if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) {
|
if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0)
|
||||||
printk("Keyboard Scan Init Failed\n");
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zmk_usb_hid_init() < 0) {
|
if (zmk_endpoints_init())
|
||||||
printk("USB HID Init Failed\n");
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
152
src/usb_hid.c
152
src/usb_hid.c
|
@ -5,167 +5,23 @@
|
||||||
#include <usb/class/usb_hid.h>
|
#include <usb/class/usb_hid.h>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
#include "hid.h"
|
||||||
#include "keymap.h"
|
#include "keymap.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(zmk_usb_hid, CONFIG_ZMK_USB_HID_LOG_LEVEL);
|
LOG_MODULE_REGISTER(zmk_usb_hid, CONFIG_ZMK_USB_HID_LOG_LEVEL);
|
||||||
|
|
||||||
#define MAX_KEYCODE KC_APP
|
|
||||||
|
|
||||||
static const u8_t hid_report_desc[] = {
|
|
||||||
/* USAGE_PAGE (Generic Desktop) */
|
|
||||||
HID_GI_USAGE_PAGE,
|
|
||||||
USAGE_GEN_DESKTOP,
|
|
||||||
/* USAGE (Keyboard) */
|
|
||||||
HID_LI_USAGE,
|
|
||||||
USAGE_GEN_DESKTOP_KEYBOARD,
|
|
||||||
/* COLLECTION (Application) */
|
|
||||||
HID_MI_COLLECTION,
|
|
||||||
COLLECTION_APPLICATION,
|
|
||||||
/* USAGE_PAGE (Keypad) */
|
|
||||||
HID_GI_USAGE_PAGE,
|
|
||||||
USAGE_GEN_DESKTOP_KEYPAD,
|
|
||||||
/* USAGE_MINIMUM (Keyboard LeftControl) */
|
|
||||||
HID_LI_USAGE_MIN(1),
|
|
||||||
0xE0,
|
|
||||||
/* USAGE_MAXIMUM (Keyboard Right GUI) */
|
|
||||||
HID_LI_USAGE_MAX(1),
|
|
||||||
0xE7,
|
|
||||||
/* LOGICAL_MINIMUM (0) */
|
|
||||||
HID_GI_LOGICAL_MIN(1),
|
|
||||||
0x00,
|
|
||||||
/* LOGICAL_MAXIMUM (1) */
|
|
||||||
HID_GI_LOGICAL_MAX(1),
|
|
||||||
0x01,
|
|
||||||
/* REPORT_SIZE (1) */
|
|
||||||
HID_GI_REPORT_SIZE,
|
|
||||||
0x01,
|
|
||||||
/* REPORT_COUNT (8) */
|
|
||||||
HID_GI_REPORT_COUNT,
|
|
||||||
0x08,
|
|
||||||
/* INPUT (Data,Var,Abs) */
|
|
||||||
HID_MI_INPUT,
|
|
||||||
0x02,
|
|
||||||
/* USAGE_PAGE (Keypad) */
|
|
||||||
HID_GI_USAGE_PAGE,
|
|
||||||
USAGE_GEN_DESKTOP_KEYPAD,
|
|
||||||
/* REPORT_SIZE (8) */
|
|
||||||
HID_GI_REPORT_SIZE,
|
|
||||||
0x08,
|
|
||||||
/* REPORT_COUNT (1) */
|
|
||||||
HID_GI_REPORT_COUNT,
|
|
||||||
0x07,
|
|
||||||
/* INPUT (Cnst,Var,Abs) */
|
|
||||||
HID_MI_INPUT,
|
|
||||||
0x03,
|
|
||||||
|
|
||||||
/* USAGE_PAGE (Keypad) */
|
|
||||||
HID_GI_USAGE_PAGE,
|
|
||||||
USAGE_GEN_DESKTOP_KEYPAD,
|
|
||||||
/* LOGICAL_MINIMUM (0) */
|
|
||||||
HID_GI_LOGICAL_MIN(1),
|
|
||||||
0x00,
|
|
||||||
/* LOGICAL_MAXIMUM (101) */
|
|
||||||
HID_GI_LOGICAL_MAX(1),
|
|
||||||
0x01,
|
|
||||||
/* USAGE_MINIMUM (Reserved) */
|
|
||||||
HID_LI_USAGE_MIN(1),
|
|
||||||
0x00,
|
|
||||||
/* USAGE_MAXIMUM (Keyboard Application) */
|
|
||||||
HID_LI_USAGE_MAX(1),
|
|
||||||
MAX_KEYCODE,
|
|
||||||
/* REPORT_SIZE (8) */
|
|
||||||
HID_GI_REPORT_SIZE,
|
|
||||||
0x01,
|
|
||||||
/* REPORT_COUNT (6) */
|
|
||||||
HID_GI_REPORT_COUNT,
|
|
||||||
MAX_KEYCODE + 1,
|
|
||||||
/* INPUT (Data,Ary,Abs) */
|
|
||||||
HID_MI_INPUT,
|
|
||||||
0x02,
|
|
||||||
/* USAGE_PAGE (Keypad) */
|
|
||||||
HID_GI_USAGE_PAGE,
|
|
||||||
USAGE_GEN_DESKTOP_KEYPAD,
|
|
||||||
/* REPORT_SIZE (8) */
|
|
||||||
HID_GI_REPORT_SIZE,
|
|
||||||
0x02,
|
|
||||||
/* REPORT_COUNT (6) */
|
|
||||||
HID_GI_REPORT_COUNT,
|
|
||||||
0x01,
|
|
||||||
/* INPUT (Cnst,Var,Abs) */
|
|
||||||
HID_MI_INPUT,
|
|
||||||
0x03,
|
|
||||||
/* END_COLLECTION */
|
|
||||||
HID_MI_COLLECTION_END,
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum usb_dc_status_code usb_status;
|
static enum usb_dc_status_code usb_status;
|
||||||
|
|
||||||
static struct device *hid_dev;
|
static struct device *hid_dev;
|
||||||
struct boot_report
|
|
||||||
{
|
|
||||||
u8_t modifiers;
|
|
||||||
u8_t _unused;
|
|
||||||
u8_t keys[6];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct extended_report
|
int zmk_usb_hid_send_report(const struct zmk_hid_report *report)
|
||||||
{
|
|
||||||
u8_t keys[13];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct hid_report
|
|
||||||
{
|
|
||||||
struct boot_report boot;
|
|
||||||
struct extended_report extended;
|
|
||||||
} __packed report;
|
|
||||||
|
|
||||||
#define KEY_OFFSET 0x02
|
|
||||||
#define MAX_KEYS 6
|
|
||||||
|
|
||||||
#define TOGGLE_BOOT_KEY(match, val) \
|
|
||||||
for (int idx = 0; idx < MAX_KEYS; idx++) \
|
|
||||||
{ \
|
|
||||||
if (report.boot.keys[idx + KEY_OFFSET] != match) \
|
|
||||||
{ \
|
|
||||||
continue; \
|
|
||||||
} \
|
|
||||||
report.boot.keys[idx + KEY_OFFSET] = val; \
|
|
||||||
break; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TOGGLE_EXT_KEY(code, val) WRITE_BIT(report.extended.keys[code / 8], code % 8, val)
|
|
||||||
|
|
||||||
int zmk_usb_hid_press_key(zmk_key code)
|
|
||||||
{
|
{
|
||||||
if (usb_status == USB_DC_SUSPEND)
|
if (usb_status == USB_DC_SUSPEND)
|
||||||
{
|
{
|
||||||
return usb_wakeup_request();
|
return usb_wakeup_request();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code > MAX_KEYCODE)
|
return hid_int_ep_write(hid_dev, (u8_t *)report, sizeof(struct zmk_hid_report), NULL);
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TOGGLE_BOOT_KEY(0U, code);
|
|
||||||
|
|
||||||
TOGGLE_EXT_KEY(code, true);
|
|
||||||
|
|
||||||
return hid_int_ep_write(hid_dev, (u8_t *)&report, sizeof(report), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int zmk_usb_hid_release_key(zmk_key code)
|
|
||||||
{
|
|
||||||
if (code > MAX_KEYCODE)
|
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TOGGLE_BOOT_KEY(code, 0U);
|
|
||||||
|
|
||||||
TOGGLE_EXT_KEY(code, false);
|
|
||||||
|
|
||||||
return hid_int_ep_write(hid_dev, (u8_t *)&report, sizeof(report), NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params)
|
void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params)
|
||||||
|
@ -185,7 +41,7 @@ int zmk_usb_hid_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_hid_register_device(hid_dev,
|
usb_hid_register_device(hid_dev,
|
||||||
hid_report_desc, sizeof(hid_report_desc),
|
zmk_hid_report_desc, sizeof(zmk_hid_report_desc),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
usb_hid_init(hid_dev);
|
usb_hid_init(hid_dev);
|
||||||
|
|
|
@ -5,12 +5,10 @@
|
||||||
#include <usb/class/usb_hid.h>
|
#include <usb/class/usb_hid.h>
|
||||||
|
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
int zmk_usb_hid_init();
|
int zmk_usb_hid_init();
|
||||||
|
|
||||||
// TODO: Modifiers!
|
int zmk_usb_hid_send_report(const struct zmk_hid_report *report);
|
||||||
|
|
||||||
int zmk_usb_hid_press_key(zmk_key key);
|
|
||||||
int zmk_usb_hid_release_key(zmk_key key);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue