1 /** @file 2 * @brief Internal APIs for Bluetooth Hearing Access Profile. 3 */ 4 5 /* 6 * Copyright (c) 2022 Codecoup 7 * 8 * SPDX-License-Identifier: Apache-2.0 9 */ 10 11 #include <stdbool.h> 12 #include <stdint.h> 13 14 #include <zephyr/bluetooth/conn.h> 15 #include <zephyr/bluetooth/gatt.h> 16 #include <zephyr/bluetooth/uuid.h> 17 #include <zephyr/sys/atomic.h> 18 #include <zephyr/sys/util_macro.h> 19 20 /* Control Point opcodes */ 21 #define BT_HAS_OP_READ_PRESET_REQ 0x01 22 #define BT_HAS_OP_READ_PRESET_RSP 0x02 23 #define BT_HAS_OP_PRESET_CHANGED 0x03 24 #define BT_HAS_OP_WRITE_PRESET_NAME 0x04 25 #define BT_HAS_OP_SET_ACTIVE_PRESET 0x05 26 #define BT_HAS_OP_SET_NEXT_PRESET 0x06 27 #define BT_HAS_OP_SET_PREV_PRESET 0x07 28 #define BT_HAS_OP_SET_ACTIVE_PRESET_SYNC 0x08 29 #define BT_HAS_OP_SET_NEXT_PRESET_SYNC 0x09 30 #define BT_HAS_OP_SET_PREV_PRESET_SYNC 0x0a 31 32 /* Application error codes */ 33 #define BT_HAS_ERR_INVALID_OPCODE 0x80 34 #define BT_HAS_ERR_WRITE_NAME_NOT_ALLOWED 0x81 35 #define BT_HAS_ERR_PRESET_SYNC_NOT_SUPP 0x82 36 #define BT_HAS_ERR_OPERATION_NOT_POSSIBLE 0x83 37 #define BT_HAS_ERR_INVALID_PARAM_LEN 0x84 38 39 /* Hearing Aid Feature bits */ 40 #define BT_HAS_FEAT_HEARING_AID_TYPE_LSB BIT(0) 41 #define BT_HAS_FEAT_HEARING_AID_TYPE_MSB BIT(1) 42 #define BT_HAS_FEAT_PRESET_SYNC_SUPP BIT(2) 43 #define BT_HAS_FEAT_INDEPENDENT_PRESETS BIT(3) 44 #define BT_HAS_FEAT_DYNAMIC_PRESETS BIT(4) 45 #define BT_HAS_FEAT_WRITABLE_PRESETS_SUPP BIT(5) 46 47 #define BT_HAS_FEAT_HEARING_AID_TYPE_MASK (BT_HAS_FEAT_HEARING_AID_TYPE_LSB | \ 48 BT_HAS_FEAT_HEARING_AID_TYPE_MSB) 49 50 /* Preset Changed Change ID values */ 51 #define BT_HAS_CHANGE_ID_GENERIC_UPDATE 0x00 52 #define BT_HAS_CHANGE_ID_PRESET_DELETED 0x01 53 #define BT_HAS_CHANGE_ID_PRESET_AVAILABLE 0x02 54 #define BT_HAS_CHANGE_ID_PRESET_UNAVAILABLE 0x03 55 56 #define BT_HAS_IS_LAST 0x01 57 58 struct bt_has { 59 /** Hearing Aid Features value */ 60 uint8_t features; 61 62 /** Active preset index value */ 63 uint8_t active_index; 64 65 /* Whether the service has been registered or not */ 66 bool registered; 67 }; 68 69 struct bt_has_cp_hdr { 70 uint8_t opcode; 71 uint8_t data[0]; 72 } __packed; 73 74 struct bt_has_cp_read_presets_req { 75 uint8_t start_index; 76 uint8_t num_presets; 77 } __packed; 78 79 struct bt_has_cp_read_preset_rsp { 80 uint8_t is_last; 81 uint8_t index; 82 uint8_t properties; 83 uint8_t name[0]; 84 } __packed; 85 86 struct bt_has_cp_preset_changed { 87 uint8_t change_id; 88 uint8_t is_last; 89 uint8_t additional_params[0]; 90 } __packed; 91 92 struct bt_has_cp_generic_update { 93 uint8_t prev_index; 94 uint8_t index; 95 uint8_t properties; 96 uint8_t name[0]; 97 } __packed; 98 99 struct bt_has_cp_write_preset_name { 100 uint8_t index; 101 uint8_t name[0]; 102 } __packed; 103 104 struct bt_has_cp_set_active_preset { 105 uint8_t index; 106 } __packed; 107 bt_has_op_str(uint8_t op)108static inline const char *bt_has_op_str(uint8_t op) 109 { 110 switch (op) { 111 case BT_HAS_OP_READ_PRESET_REQ: 112 return "Read preset request"; 113 case BT_HAS_OP_READ_PRESET_RSP: 114 return "Read preset response"; 115 case BT_HAS_OP_PRESET_CHANGED: 116 return "Preset changed"; 117 case BT_HAS_OP_WRITE_PRESET_NAME: 118 return "Write preset name"; 119 case BT_HAS_OP_SET_ACTIVE_PRESET: 120 return "Set active preset"; 121 case BT_HAS_OP_SET_NEXT_PRESET: 122 return "Set next preset"; 123 case BT_HAS_OP_SET_PREV_PRESET: 124 return "Set previous preset"; 125 case BT_HAS_OP_SET_ACTIVE_PRESET_SYNC: 126 return "Set active preset (sync)"; 127 case BT_HAS_OP_SET_NEXT_PRESET_SYNC: 128 return "Set next preset (sync)"; 129 case BT_HAS_OP_SET_PREV_PRESET_SYNC: 130 return "Set previous preset (sync)"; 131 default: 132 return "Unknown"; 133 } 134 } 135 bt_has_change_id_str(uint8_t change_id)136static inline const char *bt_has_change_id_str(uint8_t change_id) 137 { 138 switch (change_id) { 139 case BT_HAS_CHANGE_ID_GENERIC_UPDATE: 140 return "Generic update"; 141 case BT_HAS_CHANGE_ID_PRESET_DELETED: 142 return "Preset deleted"; 143 case BT_HAS_CHANGE_ID_PRESET_AVAILABLE: 144 return "Preset available"; 145 case BT_HAS_CHANGE_ID_PRESET_UNAVAILABLE: 146 return "Preset unavailable"; 147 default: 148 return "Unknown changeId"; 149 } 150 } 151 152 enum has_client_flags { 153 HAS_CLIENT_DISCOVER_IN_PROGRESS, 154 HAS_CLIENT_CP_OPERATION_IN_PROGRESS, 155 156 HAS_CLIENT_NUM_FLAGS, /* keep as last */ 157 }; 158 159 struct bt_has_client { 160 /** Common profile reference object */ 161 struct bt_has has; 162 163 /** Profile connection reference */ 164 struct bt_conn *conn; 165 166 /** Internal flags */ 167 ATOMIC_DEFINE(flags, HAS_CLIENT_NUM_FLAGS); 168 169 /* GATT procedure parameters */ 170 union { 171 struct { 172 struct bt_uuid_16 uuid; 173 union { 174 struct bt_gatt_read_params read; 175 struct bt_gatt_discover_params discover; 176 }; 177 }; 178 struct bt_gatt_write_params write; 179 } params; 180 181 struct bt_gatt_subscribe_params features_subscription; 182 struct bt_gatt_subscribe_params control_point_subscription; 183 struct bt_gatt_subscribe_params active_index_subscription; 184 }; 185