本篇文章介紹HID over GATT device的製作。在前篇文章介紹classic HID custom keypad製作,但是若HID device移除電源後再接上電源,HID host不能再次自動連上。修改HID SDP paramter hid_reconnect_initiate=0後,雖然在Android與Linux Debian能運作正常,但在iPhone與Windows下卻無法正常運作。
本篇文章測試HID over GATT是否能正常運作。
一、HID over GATT:
在HID over GATT profile文件中說明, HID device需具備三個必要services: HID service, battery service and device information service。 如下圖所示。
(source SIG HID over GATT profile)
此三種service在BTstack library中均有implement。宣告GATT service時直接import即可。
HID device Class of service UUID and HID keyboard APPERANCE可由SIG assigned numbers文件查出,別為0x1812與0x03C1。
三、定義HID device keyboard descriptior:
hid keyboard descriptor定義input data為:modifier(1 byte), reserved byte(1 byte)與keycode(6 bytes)。output data為:5 bits+3 bits。
四、定義輸入ascii character與scan code對照表:
由HID report input 輸入的character需轉為scan code。
- 由keypad輸入字元:get_new_keypad_value() :定義在4x4 keypad driver中。
- 字元存入ring buffer中,並呼叫hids_device_request_can_send_now_event(): key_input()。
- 在HIDS_SUBEVENT_CAN_SEND_NOW將字元的modifier與keycode送出:typing_can_send_now();
- typing_can_send_now():由ring buffer讀取輸入的字元,查表取得modifier與keycode,呼叫send_report(modifier, keycode),送出hid report後,再次呼叫hids_device_request_can_send_now_event()執行下次送出hid report。
- send_report():
uint8_t report[] = { modifier, 0, keycode, 0, 0, 0, 0, 0};
送出HID descriptor所定義的input的8 bytes。
詳細程式碼附於文末。
七、成果展示影片:
八、程式碼:
pico_keypad library程式碼,請參閱前篇文章內容。
/* this file was modified from hog_keyboard_demo.c */
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "btstack.h"
#include "ble/gatt-service/battery_service_server.h"
#include "ble/gatt-service/device_information_service_server.h"
#include "ble/gatt-service/hids_device.h"
#include "hog_custom_keypad.h"
#include "inttypes.h"
#include "keypad.h"
#define BACKSPACE_BUTTON 16
#define RETURN_BUTTON 17
// from USB HID Specification 1.1, Appendix B.1
const uint8_t hid_descriptor_keyboard_boot_mode[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xa1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID 1
// Modifier byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0xe0, // Usage Minimum (Keyboard LeftControl)
0x29, 0xe7, // Usage Maxium (Keyboard Right GUI)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Reserved byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x03, // Input (Constant, Variable, Absolute)
// LED report + padding
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maxium (Kana)
0x91, 0x02, // Output (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x03, // Output (Constant, Variable, Absolute)
// Keycodes
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xff, // Logical Maximum (1)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (Reserved (no event indicated))
0x29, 0xff, // Usage Maxium (Reserved)
0x81, 0x00, // Input (Data, Array)
0xc0, // End collection
};
//
#define CHAR_ILLEGAL 0xff
#define CHAR_RETURN '\n'
#define CHAR_ESCAPE 27
#define CHAR_TAB '\t'
#define CHAR_BACKSPACE 0x7f
// Simplified US Keyboard with Shift modifier
/**
* English (US)
*/
static const uint8_t keytable_us_none [] = {
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 0-3 */
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', /* 4-13 */
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 14-23 */
'u', 'v', 'w', 'x', 'y', 'z', /* 24-29 */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', /* 30-39 */
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', /* 40-44 */
'-', '=', '[', ']', '\\', CHAR_ILLEGAL, ';', '\'', 0x60, ',', /* 45-54 */
'.', '/', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 55-60 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 61-64 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 65-68 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 69-72 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 73-76 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 77-80 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 81-84 */
'*', '-', '+', '\n', '1', '2', '3', '4', '5', /* 85-97 */
'6', '7', '8', '9', '0', '.', 0xa7, /* 97-100 */
};
static const uint8_t keytable_us_shift[] = {
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 0-3 */
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 4-13 */
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 14-23 */
'U', 'V', 'W', 'X', 'Y', 'Z', /* 24-29 */
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', /* 30-39 */
CHAR_RETURN, CHAR_ESCAPE, CHAR_BACKSPACE, CHAR_TAB, ' ', /* 40-44 */
'_', '+', '{', '}', '|', CHAR_ILLEGAL, ':', '"', 0x7E, '<', /* 45-54 */
'>', '?', CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 55-60 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 61-64 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 65-68 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 69-72 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 73-76 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 77-80 */
CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, CHAR_ILLEGAL, /* 81-84 */
'*', '-', '+', '\n', '1', '2', '3', '4', '5', /* 85-97 */
'6', '7', '8', '9', '0', '.', 0xb1, /* 97-100 */
};
static btstack_packet_callback_registration_t hci_event_callback_registration;
static btstack_packet_callback_registration_t sm_event_callback_registration;
static uint8_t battery = 100;
static hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
static uint8_t protocol_mode = HID_PROTOCOL_MODE_REPORT;
const uint8_t adv_data[] = {
// Flags general discoverable, BR/EDR not supported
0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
// Name
0x0d, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'H', 'I', 'D', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd',
// 16-bit Service UUIDs
0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE & 0xff, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE >> 8,
// Appearance HID - Keyboard (Category 15, Sub-Category 1)
0x03, BLUETOOTH_DATA_TYPE_APPEARANCE, 0xC1, 0x03,
};
const uint8_t adv_data_len = sizeof(adv_data);
// Buffer for 30 characters
static uint8_t key_input_storage[30];
static btstack_ring_buffer_t key_input_buffer;
// HID Keyboard lookup
static int lookup_keycode(uint8_t character, const uint8_t * table, int size, uint8_t * keycode){
int i;
for (i=0;i<size;i++){
if (table[i] != character) continue;
*keycode = i;
return 1;
}
return 0;
}
static int keycode_and_modifer_us_for_character(uint8_t character, uint8_t * keycode, uint8_t * modifier){
int found;
found = lookup_keycode(character, keytable_us_none, sizeof(keytable_us_none), keycode);
if (found) {
*modifier = 0; // none
return 1;
}
found = lookup_keycode(character, keytable_us_shift, sizeof(keytable_us_shift), keycode);
if (found) {
*modifier = 2; // shift
return 1;
}
return 0;
}
// HID Report sending
static void send_report(int modifier, int keycode){
uint8_t report[] = { modifier, 0, keycode, 0, 0, 0, 0, 0};
switch (protocol_mode){
case 0:
hids_device_send_boot_keyboard_input_report(con_handle, report, sizeof(report));
break;
case 1:
hids_device_send_input_report(con_handle, report, sizeof(report));
break;
default:
break;
}
}
static enum {
W4_INPUT,
W4_CAN_SEND_FROM_BUFFER,
W4_CAN_SEND_KEY_UP,
} state;
static void typing_can_send_now(void){
switch (state){
case W4_CAN_SEND_FROM_BUFFER:
while (1){
uint8_t c;
uint32_t num_bytes_read;
btstack_ring_buffer_read(&key_input_buffer, &c, 1, &num_bytes_read);
if (num_bytes_read == 0){
state = W4_INPUT;
break;
}
uint8_t modifier;
uint8_t keycode;
int found = keycode_and_modifer_us_for_character(c, &keycode, &modifier);
if (!found) continue;
printf("sending: %c\n", c);
send_report(modifier, keycode);
state = W4_CAN_SEND_KEY_UP;
hids_device_request_can_send_now_event(con_handle);
break;
}
break;
case W4_CAN_SEND_KEY_UP:
send_report(0, 0);
if (btstack_ring_buffer_bytes_available(&key_input_buffer)){
state = W4_CAN_SEND_FROM_BUFFER;
hids_device_request_can_send_now_event(con_handle);
} else {
state = W4_INPUT;
}
break;
default:
break;
}
}
void key_input(char character){
uint8_t c = character;
btstack_ring_buffer_write(&key_input_buffer, &c, 1);
// start sending
if (state == W4_INPUT && con_handle != HCI_CON_HANDLE_INVALID){
state = W4_CAN_SEND_FROM_BUFFER;
hids_device_request_can_send_now_event(con_handle);
}
}
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
if (packet_type != HCI_EVENT_PACKET) return;
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_DISCONNECTION_COMPLETE:
con_handle = HCI_CON_HANDLE_INVALID;
printf("Disconnected\n");
break;
case SM_EVENT_JUST_WORKS_REQUEST:
printf("Just Works requested\n");
sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
break;
case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
printf("Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet));
sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
break;
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
printf("Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet));
break;
case HCI_EVENT_HIDS_META:
switch (hci_event_hids_meta_get_subevent_code(packet)){
case HIDS_SUBEVENT_INPUT_REPORT_ENABLE:
con_handle = hids_subevent_input_report_enable_get_con_handle(packet);
printf("Report Characteristic Subscribed %u\n", hids_subevent_input_report_enable_get_enable(packet));
break;
case HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE:
con_handle = hids_subevent_boot_keyboard_input_report_enable_get_con_handle(packet);
printf("Boot Keyboard Characteristic Subscribed %u\n", hids_subevent_boot_keyboard_input_report_enable_get_enable(packet));
break;
case HIDS_SUBEVENT_PROTOCOL_MODE:
protocol_mode = hids_subevent_protocol_mode_get_protocol_mode(packet);
printf("Protocol Mode: %s mode\n", hids_subevent_protocol_mode_get_protocol_mode(packet) ? "Report" : "Boot");
break;
case HIDS_SUBEVENT_CAN_SEND_NOW:
typing_can_send_now();
break;
default:
break;
}
break;
default:
break;
}
}
void key_button_callback(uint gpio, uint32_t events) {
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL, false);
gpio_acknowledge_irq(gpio, events);
if (gpio == BACKSPACE_BUTTON ) {
busy_wait_ms(100);
printf("%d\n", events);
key_input(CHAR_BACKSPACE); //Backspace key
}
if (gpio == RETURN_BUTTON) {
busy_wait_ms(200);
key_input(CHAR_RETURN); // return key
}
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL, true);
}
int main()
{
stdio_init_all();
if (cyw43_arch_init()) {
printf("cyw43_arch_init error\n");
return 0;
}
//0. initialize keypad
keypad_init();
// backspace & return key
gpio_init(BACKSPACE_BUTTON);
gpio_init(RETURN_BUTTON);
gpio_pull_up(BACKSPACE_BUTTON);
gpio_pull_up(RETURN_BUTTON);
gpio_set_irq_enabled_with_callback(BACKSPACE_BUTTON, GPIO_IRQ_EDGE_FALL, true, key_button_callback);
gpio_set_irq_enabled_with_callback(RETURN_BUTTON, GPIO_IRQ_EDGE_FALL, true, key_button_callback);
//1. initialize ring buffer for key input
btstack_ring_buffer_init(&key_input_buffer, key_input_storage, sizeof(key_input_storage));
//2. l2cap initialize
l2cap_init();
//3. setup SM: Display only
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING);
//4. setup ATT server
att_server_init(profile_data, NULL, NULL);
//5. setup battery service
battery_service_server_init(battery);
//6. setup device information service
device_information_service_server_init();
//7. setup HID Device service
hids_device_init(0, hid_descriptor_keyboard_boot_mode, sizeof(hid_descriptor_keyboard_boot_mode));
//8. setup advertisements
uint16_t adv_int_min = 0x0030;
uint16_t adv_int_max = 0x0030;
uint8_t adv_type = 0;
bd_addr_t null_addr;
memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
gap_advertisements_enable(1);
//9. register for HCI events
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
//10. register for SM events
sm_event_callback_registration.callback = &packet_handler;
sm_add_event_handler(&sm_event_callback_registration);
//11. register for HIDS
hids_device_register_packet_handler(packet_handler);
hci_power_control(HCI_POWER_ON);
uint8_t c;
while(1) {
if (con_handle == HCI_CON_HANDLE_INVALID) continue;
c=get_new_keypad_value();
if (c) {
key_input(c);
}
}
return 0;
}
- hog_custom_keypad.gatt
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "HID Keyboard"
CHARACTERISTIC, GATT_DATABASE_HASH, READ,
// add Battery Service
#import <battery_service.gatt>
// add Device ID Service
#import <device_information_service.gatt>
// add HID Service
#import <hids.gatt>
- CMakeLists.txt
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/duser/pico/pico-sdk")
set(PICO_BOARD pico_w CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
project(hog_custom_keypad C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(hog_custom_keypad hog_custom_keypad.c )
pico_set_program_name(hog_custom_keypad "hog_custom_keypad")
pico_set_program_version(hog_custom_keypad "0.1")
pico_enable_stdio_uart(hog_custom_keypad 1)
pico_enable_stdio_usb(hog_custom_keypad 0)
# Add the standard library to the build
target_link_libraries(hog_custom_keypad
pico_stdlib
pico_cyw43_arch_none
pico_btstack_cyw43
pico_btstack_ble)
# Add the standard include files to the build
target_include_directories(hog_custom_keypad PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
pico_btstack_make_gatt_header(hog_custom_keypad PRIVATE "${CMAKE_CURRENT_LIST_DIR}/hog_custom_keypad.gatt")
# Add any user requested libraries
add_subdirectory(pico_keypad)
target_link_libraries(hog_custom_keypad
pico_keypad)
pico_add_extra_outputs(hog_custom_keypad)
- btstack_config.h
#ifndef _PICO_BTSTACK_BTSTACK_CONFIG_H
#define _PICO_BTSTACK_BTSTACK_CONFIG_H
// BTstack features that can be enabled
#ifdef ENABLE_BLE
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
#endif
#ifdef ENABLE_MESH
// Mesh Config
#define ENABLE_MESH_ADV_BEARER
#define ENABLE_MESH_GATT_BEARER
#define ENABLE_MESH_PB_ADV
#define ENABLE_MESH_PB_GATT
#define ENABLE_MESH_PROXY_SERVER
#define ENABLE_MESH_RELAY
#define ENABLE_MESH_PROVISIONER
#define MAX_NR_MESH_SUBNETS 2
#define MAX_NR_MESH_TRANSPORT_KEYS 16
#define MAX_NR_MESH_VIRTUAL_ADDRESSES 16
// allow for one NetKey update
#define MAX_NR_MESH_NETWORK_KEYS (MAX_NR_MESH_SUBNETS+1)
#endif
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define ENABLE_PRINTF_HEXDUMP
#define ENABLE_SCO_OVER_HCI
// BTstack configuration. buffers, sizes, ...
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
#define MAX_NR_AVDTP_CONNECTIONS 1
#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
#define MAX_NR_AVRCP_CONNECTIONS 2
#define MAX_NR_BNEP_CHANNELS 1
#define MAX_NR_BNEP_SERVICES 1
#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
#define MAX_NR_GATT_CLIENTS 1
#define MAX_NR_HCI_CONNECTIONS 2
#define MAX_NR_HID_HOST_CONNECTIONS 1
#define MAX_NR_HIDS_CLIENTS 1
#define MAX_NR_HFP_CONNECTIONS 1
#define MAX_NR_L2CAP_CHANNELS 4
#define MAX_NR_L2CAP_SERVICES 3
#define MAX_NR_RFCOMM_CHANNELS 1
#define MAX_NR_RFCOMM_MULTIPLEXERS 1
#define MAX_NR_RFCOMM_SERVICES 1
#define MAX_NR_SERVICE_RECORD_ITEMS 4
#define MAX_NR_SM_LOOKUP_ENTRIES 3
#define MAX_NR_WHITELIST_ENTRIES 16
#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
#define MAX_NR_CONTROLLER_SCO_PACKETS 3
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
#define HCI_HOST_ACL_PACKET_LEN 1024
#define HCI_HOST_ACL_PACKET_NUM 3
#define HCI_HOST_SCO_PACKET_LEN 120
#define HCI_HOST_SCO_PACKET_NUM 3
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
#define NVM_NUM_DEVICE_DB_ENTRIES 16
#define NVM_NUM_LINK_KEYS 16
// We don't give btstack a malloc, so use a fixed-size ATT DB.
#define MAX_ATT_DB_SIZE 512
// BTstack HAL configuration
#define HAVE_EMBEDDED_TIME_MS
// map btstack_assert onto Pico SDK assert()
#define HAVE_ASSERT
// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
#define ENABLE_SOFTWARE_AES128
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
//#define HAVE_BTSTACK_STDIN
// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packets
//#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100
#ifdef ENABLE_CLASSIC
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
#endif
#define HAVE_MALLOC
// BTstack configuration. buffers, sizes, ...
#define HCI_INCOMING_PRE_BUFFER_SIZE 6
#endif // _PICO_BTSTACK_BTSTACK_CONFIG_H
沒有留言:
張貼留言