mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 02:38:35 -07:00
@@ -12,6 +12,7 @@ typedef enum {
|
|||||||
HidSvcGattCharacteristicReportMap,
|
HidSvcGattCharacteristicReportMap,
|
||||||
HidSvcGattCharacteristicInfo,
|
HidSvcGattCharacteristicInfo,
|
||||||
HidSvcGattCharacteristicCtrlPoint,
|
HidSvcGattCharacteristicCtrlPoint,
|
||||||
|
HidSvcGattCharacteristicLed,
|
||||||
HidSvcGattCharacteristicCount,
|
HidSvcGattCharacteristicCount,
|
||||||
} HidSvcGattCharacteristicId;
|
} HidSvcGattCharacteristicId;
|
||||||
|
|
||||||
@@ -53,6 +54,22 @@ static bool
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LED Descriptor params for BadBT
|
||||||
|
|
||||||
|
static uint8_t led_desc_context_buf[2] = {HID_SVC_REPORT_COUNT + 1, 2};
|
||||||
|
|
||||||
|
static FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_led = {
|
||||||
|
.uuid_type = UUID_TYPE_16,
|
||||||
|
.uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID,
|
||||||
|
.max_length = HID_SVC_REPORT_REF_LEN,
|
||||||
|
.data_callback.fn = hid_svc_char_desc_data_callback,
|
||||||
|
.data_callback.context = led_desc_context_buf,
|
||||||
|
.security_permissions = ATTR_PERMISSION_NONE,
|
||||||
|
.access_permissions = ATTR_ACCESS_READ_WRITE,
|
||||||
|
.gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS,
|
||||||
|
.is_variable = CHAR_VALUE_LEN_CONSTANT,
|
||||||
|
};
|
||||||
|
|
||||||
static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = {
|
static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = {
|
||||||
[HidSvcGattCharacteristicProtocolMode] =
|
[HidSvcGattCharacteristicProtocolMode] =
|
||||||
{.name = "Protocol Mode",
|
{.name = "Protocol Mode",
|
||||||
@@ -96,6 +113,21 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris
|
|||||||
.security_permissions = ATTR_PERMISSION_NONE,
|
.security_permissions = ATTR_PERMISSION_NONE,
|
||||||
.gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE,
|
.gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE,
|
||||||
.is_variable = CHAR_VALUE_LEN_CONSTANT},
|
.is_variable = CHAR_VALUE_LEN_CONSTANT},
|
||||||
|
[HidSvcGattCharacteristicLed] =
|
||||||
|
{
|
||||||
|
.name =
|
||||||
|
"HID LED State", // LED Characteristic and descriptor for BadBT to get numlock state for altchars
|
||||||
|
.data_prop_type = FlipperGattCharacteristicDataFixed,
|
||||||
|
.data.fixed.length = 1,
|
||||||
|
.uuid.Char_UUID_16 = REPORT_CHAR_UUID,
|
||||||
|
.uuid_type = UUID_TYPE_16,
|
||||||
|
.char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE,
|
||||||
|
.security_permissions = ATTR_PERMISSION_NONE,
|
||||||
|
.gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE |
|
||||||
|
GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP,
|
||||||
|
.is_variable = CHAR_VALUE_LEN_CONSTANT,
|
||||||
|
.descriptor_params = &hid_svc_char_descr_led,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_template = {
|
static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_template = {
|
||||||
@@ -128,6 +160,9 @@ typedef struct {
|
|||||||
FlipperGattCharacteristicInstance input_report_chars[HID_SVC_INPUT_REPORT_COUNT];
|
FlipperGattCharacteristicInstance input_report_chars[HID_SVC_INPUT_REPORT_COUNT];
|
||||||
FlipperGattCharacteristicInstance output_report_chars[HID_SVC_OUTPUT_REPORT_COUNT];
|
FlipperGattCharacteristicInstance output_report_chars[HID_SVC_OUTPUT_REPORT_COUNT];
|
||||||
FlipperGattCharacteristicInstance feature_report_chars[HID_SVC_FEATURE_REPORT_COUNT];
|
FlipperGattCharacteristicInstance feature_report_chars[HID_SVC_FEATURE_REPORT_COUNT];
|
||||||
|
// led state
|
||||||
|
HidLedStateEventCallback led_state_event_callback;
|
||||||
|
void* led_state_ctx;
|
||||||
} HIDSvc;
|
} HIDSvc;
|
||||||
|
|
||||||
static HIDSvc* hid_svc = NULL;
|
static HIDSvc* hid_svc = NULL;
|
||||||
@@ -144,6 +179,34 @@ static SVCCTL_EvtAckStatus_t hid_svc_event_handler(void* event) {
|
|||||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||||
// Process notification confirmation
|
// Process notification confirmation
|
||||||
ret = SVCCTL_EvtAckFlowEnable;
|
ret = SVCCTL_EvtAckFlowEnable;
|
||||||
|
} else if(blecore_evt->ecode == ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE) {
|
||||||
|
// LED Characteristic and descriptor for BadBT to get numlock state for altchars
|
||||||
|
//
|
||||||
|
// Process write request
|
||||||
|
aci_gatt_write_permit_req_event_rp0* req =
|
||||||
|
(aci_gatt_write_permit_req_event_rp0*)blecore_evt->data;
|
||||||
|
|
||||||
|
furi_check(hid_svc->led_state_event_callback && hid_svc->led_state_ctx);
|
||||||
|
|
||||||
|
// this check is likely to be incorrect, it will actually work in our case
|
||||||
|
// but we need to investigate gatt api to see what is the rules
|
||||||
|
// that specify attibute handle value from char handle (or the reverse)
|
||||||
|
if(req->Attribute_Handle == (hid_svc->chars[HidSvcGattCharacteristicLed].handle + 1)) {
|
||||||
|
hid_svc->led_state_event_callback(req->Data[0], hid_svc->led_state_ctx);
|
||||||
|
aci_gatt_write_resp(
|
||||||
|
req->Connection_Handle,
|
||||||
|
req->Attribute_Handle,
|
||||||
|
0x00, /* write_status = 0 (no error))*/
|
||||||
|
0x00, /* err_code */
|
||||||
|
req->Data_Length,
|
||||||
|
req->Data);
|
||||||
|
aci_gatt_write_char_value(
|
||||||
|
req->Connection_Handle,
|
||||||
|
hid_svc->chars[HidSvcGattCharacteristicLed].handle,
|
||||||
|
req->Data_Length,
|
||||||
|
req->Data);
|
||||||
|
ret = SVCCTL_EvtAckFlowEnable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -164,19 +227,17 @@ void hid_svc_start() {
|
|||||||
PRIMARY_SERVICE,
|
PRIMARY_SERVICE,
|
||||||
2 + /* protocol mode */
|
2 + /* protocol mode */
|
||||||
(4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) +
|
(4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) +
|
||||||
(3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 +
|
(3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + 2 +
|
||||||
2, /* Service + Report Map + HID Information + HID Control Point */
|
4, /* Service + Report Map + HID Information + HID Control Point + LED state */
|
||||||
&hid_svc->svc_handle);
|
&hid_svc->svc_handle);
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to add HID service: %d", status);
|
FURI_LOG_E(TAG, "Failed to add HID service: %d", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain previously defined characteristic order
|
for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) {
|
||||||
flipper_gatt_characteristic_init(
|
flipper_gatt_characteristic_init(
|
||||||
hid_svc->svc_handle,
|
hid_svc->svc_handle, &hid_svc_chars[i], &hid_svc->chars[i]);
|
||||||
&hid_svc_chars[HidSvcGattCharacteristicProtocolMode],
|
}
|
||||||
&hid_svc->chars[HidSvcGattCharacteristicProtocolMode]);
|
|
||||||
|
|
||||||
uint8_t protocol_mode = 1;
|
uint8_t protocol_mode = 1;
|
||||||
flipper_gatt_characteristic_update(
|
flipper_gatt_characteristic_update(
|
||||||
hid_svc->svc_handle,
|
hid_svc->svc_handle,
|
||||||
@@ -218,12 +279,6 @@ void hid_svc_start() {
|
|||||||
&hid_report_chars[report_type_idx].chars[report_idx]);
|
&hid_report_chars[report_type_idx].chars[report_idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup remaining characteristics
|
|
||||||
for(size_t i = HidSvcGattCharacteristicReportMap; i < HidSvcGattCharacteristicCount; i++) {
|
|
||||||
flipper_gatt_characteristic_init(
|
|
||||||
hid_svc->svc_handle, &hid_svc_chars[i], &hid_svc->chars[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) {
|
bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) {
|
||||||
@@ -259,6 +314,15 @@ bool hid_svc_update_info(uint8_t* data) {
|
|||||||
hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &data);
|
hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context) {
|
||||||
|
furi_assert(hid_svc);
|
||||||
|
furi_assert(callback);
|
||||||
|
furi_assert(context);
|
||||||
|
|
||||||
|
hid_svc->led_state_event_callback = callback;
|
||||||
|
hid_svc->led_state_ctx = context;
|
||||||
|
}
|
||||||
|
|
||||||
bool hid_svc_is_started() {
|
bool hid_svc_is_started() {
|
||||||
return hid_svc != NULL;
|
return hid_svc != NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#define HID_SVC_REPORT_COUNT \
|
#define HID_SVC_REPORT_COUNT \
|
||||||
(HID_SVC_INPUT_REPORT_COUNT + HID_SVC_OUTPUT_REPORT_COUNT + HID_SVC_FEATURE_REPORT_COUNT)
|
(HID_SVC_INPUT_REPORT_COUNT + HID_SVC_OUTPUT_REPORT_COUNT + HID_SVC_FEATURE_REPORT_COUNT)
|
||||||
|
|
||||||
|
typedef uint16_t (*HidLedStateEventCallback)(uint8_t state, void* ctx);
|
||||||
|
|
||||||
void hid_svc_start();
|
void hid_svc_start();
|
||||||
|
|
||||||
void hid_svc_stop();
|
void hid_svc_stop();
|
||||||
@@ -27,3 +29,5 @@ bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16
|
|||||||
|
|
||||||
// Expects data to be of length HID_SVC_INFO_LEN (4 bytes)
|
// Expects data to be of length HID_SVC_INFO_LEN (4 bytes)
|
||||||
bool hid_svc_update_info(uint8_t* data);
|
bool hid_svc_update_info(uint8_t* data);
|
||||||
|
|
||||||
|
void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context);
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ void furi_hal_bt_hid_start() {
|
|||||||
hid_svc_start();
|
hid_svc_start();
|
||||||
}
|
}
|
||||||
// Configure HID Keyboard
|
// Configure HID Keyboard
|
||||||
//hid_svc_register_led_state_callback(furi_hal_bt_hid_led_state_cb, &hid_host_led_state);
|
hid_svc_register_led_state_callback(furi_hal_bt_hid_led_state_cb, &hid_host_led_state);
|
||||||
|
|
||||||
kb_report = malloc(sizeof(FuriHalBtHidKbReport));
|
kb_report = malloc(sizeof(FuriHalBtHidKbReport));
|
||||||
mouse_report = malloc(sizeof(FuriHalBtHidMouseReport));
|
mouse_report = malloc(sizeof(FuriHalBtHidMouseReport));
|
||||||
@@ -228,7 +228,7 @@ void furi_hal_bt_hid_stop() {
|
|||||||
furi_assert(mouse_report);
|
furi_assert(mouse_report);
|
||||||
furi_assert(consumer_report);
|
furi_assert(consumer_report);
|
||||||
|
|
||||||
//hid_svc_register_led_state_callback(NULL, NULL);
|
hid_svc_register_led_state_callback(NULL, NULL);
|
||||||
// Stop all services
|
// Stop all services
|
||||||
if(dev_info_svc_is_started()) {
|
if(dev_info_svc_is_started()) {
|
||||||
dev_info_svc_stop();
|
dev_info_svc_stop();
|
||||||
|
|||||||
Reference in New Issue
Block a user