/********************************************************************************************* * Filename : le_multi_common.c.c * Description : * Author : * Email : zh-jieli.com * Last modifiled : 2017-01-17 11:14 * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. *********************************************************************************************/ // ***************************************************************************** /* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT * * @text All newer operating systems provide GATT Client functionality. * The LE Counter examples demonstrates how to specify a minimal GATT Database * with a custom GATT Service and a custom Characteristic that sends periodic * notifications. */ // ***************************************************************************** #include "system/app_core.h" #include "system/includes.h" #include "app_config.h" #include "btstack/btstack_task.h" #include "btstack/bluetooth.h" #include "btcontroller_modules.h" #include "bt_common.h" #include "le_common.h" #include "btstack/btstack_event.h" #include "le_multi_common.h" #include "btcontroller_config.h" #if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI) #if LE_DEBUG_PRINT_EN /* extern void printf_buf(u8 *buf, u32 len); */ //#define log_info r_printf #define log_info(x, ...) r_printf("[LE_MUL_COMM]" x " ", ## __VA_ARGS__) #define log_info_hexdump put_buf #else #define log_info(...) #define log_info_hexdump(...) #endif #define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey //---------------------------------------------------------------------------------------- #define MULTI_ATT_MTU_SIZE (517) //ATT MTU的值 //ATT发送的包长, note: 20 <= need >= MTU #define MULTI_ATT_LOCAL_PAYLOAD_SIZE (MULTI_ATT_MTU_SIZE) // //ATT缓存的buffer大小, note: need >= 20,可修改 #define MULTI_ATT_SEND_CBUF_SIZE (512*3) // //共配置的RAM #define MULTI_ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + MULTI_ATT_LOCAL_PAYLOAD_SIZE + MULTI_ATT_SEND_CBUF_SIZE) //note: static u8 multi_att_ram_buffer[MULTI_ATT_RAM_BUFSIZE] __attribute__((aligned(4))); u16 server_con_handle[SUPPORT_MAX_SERVER]; u16 client_con_handle[SUPPORT_MAX_CLIENT]; extern const int config_le_sm_support_enable; extern const int config_btctler_le_master_multilink; extern const int config_le_gatt_server_num; extern const int config_le_gatt_client_num; extern const int config_le_hci_connection_num; extern void reset_PK_cb_register_ext(void (*reset_pk)(u32 *, u16)); extern void sm_set_master_request_pair(int enable); //---------------------------------------------------------------------------------------- s8 mul_get_dev_index(u16 handle, u8 role) { s8 i; u16 *group_handle; u8 count; if (MULTI_ROLE_SERVER == role) { group_handle = server_con_handle; count = SUPPORT_MAX_SERVER; } else { group_handle = client_con_handle; count = SUPPORT_MAX_CLIENT; } for (i = 0; i < count; i++) { if (handle == group_handle[i]) { return i; } } return MULTI_INVAIL_INDEX; } s8 mul_get_idle_dev_index(u8 role) { s8 i; u16 *group_handle; u8 count; if (MULTI_ROLE_SERVER == role) { group_handle = server_con_handle; count = SUPPORT_MAX_SERVER; } else { group_handle = client_con_handle; count = SUPPORT_MAX_CLIENT; } for (i = 0; i < count; i++) { if (0 == group_handle[i]) { return i; } } return MULTI_INVAIL_INDEX; } s8 mul_del_dev_index(u16 handle, u8 role) { s8 i; u16 *group_handle; u8 count; if (MULTI_ROLE_SERVER == role) { group_handle = server_con_handle; count = SUPPORT_MAX_SERVER; } else { group_handle = client_con_handle; count = SUPPORT_MAX_CLIENT; } for (i = 0; i < count; i++) { if (handle == group_handle[i]) { group_handle[i] = 0; return i; } } return MULTI_INVAIL_INDEX; } bool mul_dev_have_connected(u8 role) { s8 i; u16 *group_handle; u8 count; if (MULTI_ROLE_SERVER == role) { group_handle = server_con_handle; count = SUPPORT_MAX_SERVER; } else { group_handle = client_con_handle; count = SUPPORT_MAX_CLIENT; } for (i = 0; i < count; i++) { if (group_handle[i]) { return true; } } return false; } u16 mul_dev_get_conn_handle(u8 index, u8 role) { u16 *group_handle; u8 count; if (MULTI_ROLE_SERVER == role) { group_handle = server_con_handle; count = SUPPORT_MAX_SERVER; } else { group_handle = client_con_handle; count = SUPPORT_MAX_CLIENT; } if (index < count) { return group_handle[index]; } else { return 0; } } u8 mul_dev_get_handle_role(u16 handle) { u8 i; for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { if (handle == client_con_handle[i]) { return MULTI_ROLE_CLIENT; } } return MULTI_ROLE_SERVER; } /* #define SM_EVENT_PAIR_PROCESS 0xDF */ void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { sm_just_event_t *event = (void *)packet; u32 tmp32; switch (packet_type) { case HCI_EVENT_PACKET: switch (hci_event_packet_get_type(packet)) { case SM_EVENT_JUST_WORKS_REQUEST: case SM_EVENT_PASSKEY_DISPLAY_NUMBER: case SM_EVENT_PASSKEY_INPUT_NUMBER: case SM_EVENT_PAIR_PROCESS: #if SUPPORT_MAX_SERVER if (mul_dev_get_handle_role(event->con_handle) == MULTI_ROLE_SERVER) { trans_cbk_sm_packet_handler(packet_type, channel, packet, size); } #endif #if SUPPORT_MAX_CLIENT if (mul_dev_get_handle_role(event->con_handle) == MULTI_ROLE_CLIENT) { client_cbk_sm_packet_handler(packet_type, channel, packet, size); } #endif break; default: break; } } } /* LISTING_START(packetHandler): Packet Handler */ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { u8 role = 0xff; switch (packet_type) { case HCI_EVENT_PACKET: switch (hci_event_packet_get_type(packet)) { case ATT_EVENT_CAN_SEND_NOW: if (0 == packet[1]) { role = MULTI_ROLE_SERVER; } else { role = MULTI_ROLE_CLIENT; } break; case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: role = MULTI_ROLE_SERVER; break; case ATT_EVENT_MTU_EXCHANGE_COMPLETE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 2)); break; case GAP_EVENT_ADVERTISING_REPORT: role = MULTI_ROLE_CLIENT; break; case HCI_EVENT_LE_META: switch (hci_event_le_meta_get_subevent_code(packet)) { case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: if (hci_subevent_le_enhanced_connection_complete_get_role(packet)) { role = MULTI_ROLE_SERVER; } else { role = MULTI_ROLE_CLIENT; } break; case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: if (hci_subevent_le_connection_complete_get_role(packet)) { role = MULTI_ROLE_SERVER; } else { role = MULTI_ROLE_CLIENT; } break; //参数更新完成 case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 4)); break; case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 3)); break; case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 4)); break; } break; case HCI_EVENT_DISCONNECTION_COMPLETE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 3)); break; case HCI_EVENT_VENDOR_REMOTE_TEST: log_info("HCI_EVENT_VENDOR_REMOTE_TEST: %d,%d\n", packet[1], packet[2]); break; case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 2)); break; case HCI_EVENT_ENCRYPTION_CHANGE: role = mul_dev_get_handle_role(little_endian_read_16(packet, 3)); break; } break; default: break; } #if SUPPORT_MAX_SERVER if (role == 0xff || role == MULTI_ROLE_SERVER) { trans_cbk_packet_handler(packet_type, channel, packet, size); } #endif #if SUPPORT_MAX_CLIENT if (role == 0xff || role == MULTI_ROLE_CLIENT) { client_cbk_packet_handler(packet_type, channel, packet, size); } #endif } //重设passkey回调函数,在这里可以重新设置passkey //passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 /* static void reset_passkey_cb(u32 *key) */ static void ble_cbk_passkey_input(u32 *key, u16 conn_handle) { #if SUPPORT_MAX_SERVER if (mul_dev_get_handle_role(conn_handle) == MULTI_ROLE_SERVER) { trans_deal_passkey_input(key, conn_handle); } #endif #if SUPPORT_MAX_CLIENT if (mul_dev_get_handle_role(conn_handle) == MULTI_ROLE_CLIENT) { client_deal_passkey_input(key, conn_handle); } #endif } void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) { //setup SM: Display only sm_init(); sm_set_io_capabilities(io_type); #if SUPPORT_MAX_CLIENT if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { sm_set_master_io_capabilities(IO_CAPABILITY_KEYBOARD_ONLY); } #endif sm_set_authentication_requirements(auth_req); sm_set_encryption_key_size_range(min_key_size, 16); #if SUPPORT_MAX_SERVER sm_set_request_security(security_en); #endif #if SUPPORT_MAX_CLIENT sm_set_master_request_pair(security_en); #endif sm_event_callback_set(&cbk_sm_packet_handler); if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { /* reset_PK_cb_register(reset_passkey_cb); */ reset_PK_cb_register_ext(ble_cbk_passkey_input); } } void ble_profile_init(void) { #if SUPPORT_MAX_SERVER && SUPPORT_MAX_CLIENT ble_stack_gatt_role(2); #elif SUPPORT_MAX_CLIENT ble_stack_gatt_role(1); #else ble_stack_gatt_role(0); #endif ble_vendor_set_default_att_mtu(MULTI_ATT_MTU_SIZE); if (config_le_sm_support_enable) { le_device_db_init(); #if PASSKEY_ENTER_ENABLE ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); #else ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); #endif } #if SUPPORT_MAX_SERVER server_profile_init(); #endif #if SUPPORT_MAX_CLIENT client_profile_init(); #endif // register for HCI events hci_event_callback_set(&cbk_packet_handler); /* ble_l2cap_register_packet_handler(packet_cbk); */ /* sm_event_packet_handler_register(packet_cbk); */ le_l2cap_register_packet_handler(&cbk_packet_handler); ble_op_multi_att_send_init(multi_att_ram_buffer, MULTI_ATT_RAM_BUFSIZE, MULTI_ATT_LOCAL_PAYLOAD_SIZE); } //统一接口,关闭模块 void ble_module_enable(u8 en) { log_info("mode_en:%d\n", en); #if SUPPORT_MAX_SERVER ble_trans_module_enable(en); #endif #if SUPPORT_MAX_CLIENT ble_client_module_enable(en); #endif } void ble_app_disconnect(void) { #if SUPPORT_MAX_SERVER ble_multi_trans_disconnect(); #endif #if SUPPORT_MAX_CLIENT ble_multi_client_disconnect(); #endif } void bt_ble_init(void) { int error_reset = 0; //log_info("%s,%d\n", __FUNCTION__, __LINE__); //log_info("ble_file: %s", __FILE__); /*确认配置是否ok*/ if (config_le_hci_connection_num && att_send_check_multi_dev(config_le_gatt_server_num, config_le_gatt_client_num)) { log_info("no support more device!!!\n"); error_reset = 1; } if (error_reset) { printf("======error config!!!\n"); ASSERT(0); while (1); } #if SUPPORT_MAX_SERVER bt_multi_trans_init(); #endif #if SUPPORT_MAX_CLIENT bt_multi_client_init(); #endif } void bt_ble_exit(void) { #if SUPPORT_MAX_SERVER bt_multi_trans_exit(); #endif #if SUPPORT_MAX_CLIENT bt_multi_client_exit(); #endif } #endif