|
3 | 3 |
|
4 | 4 | #include "AlertNotificationClient.h" |
5 | 5 |
|
6 | | - |
7 | 6 | using namespace Pinetime::Controllers; |
8 | 7 | constexpr ble_uuid16_t AlertNotificationClient::ansServiceUuid; |
9 | | - |
10 | 8 | constexpr ble_uuid16_t AlertNotificationClient::supportedNewAlertCategoryUuid; |
11 | | -constexpr ble_uuid16_t AlertNotificationClient::supportedUnreadAlertCategoryUuid ; |
| 9 | +constexpr ble_uuid16_t AlertNotificationClient::supportedUnreadAlertCategoryUuid; |
12 | 10 | constexpr ble_uuid16_t AlertNotificationClient::newAlertUuid; |
13 | 11 | constexpr ble_uuid16_t AlertNotificationClient::unreadAlertStatusUuid; |
14 | 12 | constexpr ble_uuid16_t AlertNotificationClient::controlPointUuid; |
15 | 13 |
|
16 | | -int Pinetime::Controllers::NewAlertSubcribeCallback(uint16_t conn_handle, |
17 | | - const struct ble_gatt_error *error, |
18 | | - struct ble_gatt_attr *attr, |
19 | | - void *arg) { |
20 | | - auto client = static_cast<AlertNotificationClient*>(arg); |
21 | | - return client->OnNewAlertSubcribe(conn_handle, error, attr); |
22 | | -} |
| 14 | +namespace { |
| 15 | + int |
| 16 | + OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, |
| 17 | + void *arg) { |
| 18 | + auto client = static_cast<AlertNotificationClient *>(arg); |
| 19 | + return client->OnDiscoveryEvent(conn_handle, error, service); |
| 20 | + } |
23 | 21 |
|
24 | | -AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask& systemTask, |
25 | | - Pinetime::Controllers::NotificationManager& notificationManager) : |
26 | | - systemTask{systemTask}, notificationManager{notificationManager}{ |
| 22 | + int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error, |
| 23 | + const struct ble_gatt_chr *chr, void *arg) { |
| 24 | + auto client = static_cast<AlertNotificationClient *>(arg); |
| 25 | + return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr); |
| 26 | + } |
| 27 | + |
| 28 | + int OnAlertNotificationDescriptorDiscoveryEventCallback(uint16_t conn_handle, |
| 29 | + const struct ble_gatt_error *error, |
| 30 | + uint16_t chr_val_handle, |
| 31 | + const struct ble_gatt_dsc *dsc, |
| 32 | + void *arg) { |
| 33 | + auto client = static_cast<AlertNotificationClient *>(arg); |
| 34 | + return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc); |
| 35 | + } |
| 36 | + |
| 37 | + int NewAlertSubcribeCallback(uint16_t conn_handle, |
| 38 | + const struct ble_gatt_error *error, |
| 39 | + struct ble_gatt_attr *attr, |
| 40 | + void *arg) { |
| 41 | + auto client = static_cast<AlertNotificationClient *>(arg); |
| 42 | + return client->OnNewAlertSubcribe(conn_handle, error, attr); |
| 43 | + } |
| 44 | +} |
27 | 45 |
|
| 46 | +AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask &systemTask, |
| 47 | + Pinetime::Controllers::NotificationManager ¬ificationManager) : |
| 48 | + systemTask{systemTask}, notificationManager{notificationManager} { |
28 | 49 | } |
29 | 50 |
|
30 | | -bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service) { |
31 | | - if(service == nullptr && error->status == BLE_HS_EDONE) { |
32 | | - NRF_LOG_INFO("ANS Discovery complete"); |
| 51 | +bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, |
| 52 | + const ble_gatt_svc *service) { |
| 53 | + if (service == nullptr && error->status == BLE_HS_EDONE) { |
| 54 | + if (isDiscovered) { |
| 55 | + NRF_LOG_INFO("ANS Discovery found, starting characteristics discovery"); |
| 56 | + |
| 57 | + ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle, |
| 58 | + OnAlertNotificationCharacteristicDiscoveredCallback, this); |
| 59 | + } else { |
| 60 | + NRF_LOG_INFO("ANS not found"); |
| 61 | + onServiceDiscovered(connectionHandle); |
| 62 | + } |
33 | 63 | return true; |
34 | 64 | } |
35 | 65 |
|
36 | | - if(service != nullptr && ble_uuid_cmp(((ble_uuid_t*)&ansServiceUuid), &service->uuid.u) == 0) { |
37 | | - NRF_LOG_INFO("ANS discovered : 0x%x", service->start_handle); |
38 | | - ansStartHandle = service->start_handle; |
39 | | - ansEndHandle = service->end_handle; |
40 | | - isDiscovered = true; |
| 66 | + if (service != nullptr && ble_uuid_cmp(((ble_uuid_t *) &ansServiceUuid), &service->uuid.u) == 0) { |
| 67 | + NRF_LOG_INFO("ANS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); |
| 68 | + ansStartHandle = service->start_handle; |
| 69 | + ansEndHandle = service->end_handle; |
| 70 | + isDiscovered = true; |
41 | 71 | } |
42 | 72 | return false; |
43 | 73 | } |
44 | 74 |
|
45 | 75 | int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, |
46 | | - const ble_gatt_chr *characteristic) { |
47 | | - if(error->status != 0 && error->status != BLE_HS_EDONE) { |
| 76 | + const ble_gatt_chr *characteristic) { |
| 77 | + if (error->status != 0 && error->status != BLE_HS_EDONE) { |
48 | 78 | NRF_LOG_INFO("ANS Characteristic discovery ERROR"); |
| 79 | + onServiceDiscovered(connectionHandle); |
49 | 80 | return 0; |
50 | 81 | } |
51 | 82 |
|
52 | | - if(characteristic == nullptr && error->status == BLE_HS_EDONE) { |
| 83 | + if (characteristic == nullptr && error->status == BLE_HS_EDONE) { |
53 | 84 | NRF_LOG_INFO("ANS Characteristic discovery complete"); |
| 85 | + if (isCharacteristicDiscovered) { |
| 86 | + ble_gattc_disc_all_dscs(connectionHandle, |
| 87 | + newAlertHandle, ansEndHandle, |
| 88 | + OnAlertNotificationDescriptorDiscoveryEventCallback, this); |
| 89 | + } else |
| 90 | + onServiceDiscovered(connectionHandle); |
54 | 91 | } else { |
55 | | - if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) { |
| 92 | + if (characteristic != nullptr && |
| 93 | + ble_uuid_cmp(((ble_uuid_t *) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) { |
56 | 94 | NRF_LOG_INFO("ANS Characteristic discovered : supportedNewAlertCategoryUuid"); |
57 | 95 | supportedNewAlertCategoryHandle = characteristic->val_handle; |
58 | | - } else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) { |
| 96 | + } else if (characteristic != nullptr && |
| 97 | + ble_uuid_cmp(((ble_uuid_t *) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) { |
59 | 98 | NRF_LOG_INFO("ANS Characteristic discovered : supportedUnreadAlertCategoryUuid"); |
60 | 99 | supportedUnreadAlertCategoryHandle = characteristic->val_handle; |
61 | | - } else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&newAlertUuid), &characteristic->uuid.u) == 0) { |
| 100 | + } else if (characteristic != nullptr && |
| 101 | + ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &characteristic->uuid.u) == 0) { |
62 | 102 | NRF_LOG_INFO("ANS Characteristic discovered : newAlertUuid"); |
63 | 103 | newAlertHandle = characteristic->val_handle; |
64 | 104 | newAlertDefHandle = characteristic->def_handle; |
65 | | - } else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&unreadAlertStatusUuid), &characteristic->uuid.u) == 0) { |
| 105 | + isCharacteristicDiscovered = true; |
| 106 | + } else if (characteristic != nullptr && |
| 107 | + ble_uuid_cmp(((ble_uuid_t *) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) { |
66 | 108 | NRF_LOG_INFO("ANS Characteristic discovered : unreadAlertStatusUuid"); |
67 | 109 | unreadAlertStatusHandle = characteristic->val_handle; |
68 | | - } else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&controlPointUuid), &characteristic->uuid.u) == 0) { |
| 110 | + } else if (characteristic != nullptr && |
| 111 | + ble_uuid_cmp(((ble_uuid_t *) &controlPointUuid), &characteristic->uuid.u) == 0) { |
69 | 112 | NRF_LOG_INFO("ANS Characteristic discovered : controlPointUuid"); |
70 | 113 | controlPointHandle = characteristic->val_handle; |
71 | | - }else |
72 | | - NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle); |
73 | | - } |
| 114 | + } else NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle); |
| 115 | + } |
74 | 116 | return 0; |
75 | 117 | } |
76 | 118 |
|
77 | 119 | int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error *error, |
78 | 120 | ble_gatt_attr *attribute) { |
79 | | - if(error->status == 0) { |
| 121 | + if (error->status == 0) { |
80 | 122 | NRF_LOG_INFO("ANS New alert subscribe OK"); |
81 | 123 | } else { |
82 | 124 | NRF_LOG_INFO("ANS New alert subscribe ERROR"); |
83 | 125 | } |
| 126 | + onServiceDiscovered(connectionHandle); |
84 | 127 |
|
85 | 128 | return 0; |
86 | 129 | } |
87 | 130 |
|
88 | 131 | int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error, |
89 | 132 | uint16_t characteristicValueHandle, |
90 | 133 | const ble_gatt_dsc *descriptor) { |
91 | | - if(error->status == 0) { |
92 | | - if(characteristicValueHandle == newAlertHandle && ble_uuid_cmp(((ble_uuid_t*)&newAlertUuid), &descriptor->uuid.u)) { |
93 | | - if(newAlertDescriptorHandle == 0) { |
| 134 | + if (error->status == 0) { |
| 135 | + if (characteristicValueHandle == newAlertHandle && |
| 136 | + ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &descriptor->uuid.u)) { |
| 137 | + if (newAlertDescriptorHandle == 0) { |
94 | 138 | NRF_LOG_INFO("ANS Descriptor discovered : %d", descriptor->handle); |
95 | 139 | newAlertDescriptorHandle = descriptor->handle; |
| 140 | + isDescriptorFound = true; |
96 | 141 | uint8_t value[2]; |
97 | 142 | value[0] = 1; |
98 | 143 | value[1] = 0; |
99 | 144 | ble_gattc_write_flat(connectionHandle, newAlertDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); |
100 | 145 | } |
101 | 146 | } |
| 147 | + } else { |
| 148 | + if (!isDescriptorFound) |
| 149 | + onServiceDiscovered(connectionHandle); |
102 | 150 | } |
103 | 151 | return 0; |
104 | 152 | } |
105 | 153 |
|
106 | 154 | void AlertNotificationClient::OnNotification(ble_gap_event *event) { |
107 | | - if(event->notify_rx.attr_handle == newAlertHandle) { |
| 155 | + if (event->notify_rx.attr_handle == newAlertHandle) { |
108 | 156 | constexpr size_t stringTerminatorSize = 1; // end of string '\0' |
109 | 157 | constexpr size_t headerSize = 3; |
110 | | - const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; |
| 158 | + const auto maxMessageSize{NotificationManager::MaximumMessageSize()}; |
111 | 159 | const auto maxBufferSize{maxMessageSize + headerSize}; |
112 | 160 |
|
113 | 161 | const auto dbgPacketLen = OS_MBUF_PKTLEN(event->notify_rx.om); |
114 | 162 | size_t bufferSize = min(dbgPacketLen + stringTerminatorSize, maxBufferSize); |
115 | | - auto messageSize = min(maxMessageSize, (bufferSize-headerSize)); |
| 163 | + auto messageSize = min(maxMessageSize, (bufferSize - headerSize)); |
116 | 164 |
|
117 | 165 | NotificationManager::Notification notif; |
118 | | - os_mbuf_copydata(event->notify_rx.om, headerSize, messageSize-1, notif.message.data()); |
119 | | - notif.message[messageSize-1] = '\0'; |
| 166 | + os_mbuf_copydata(event->notify_rx.om, headerSize, messageSize - 1, notif.message.data()); |
| 167 | + notif.message[messageSize - 1] = '\0'; |
120 | 168 | notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; |
121 | 169 | notificationManager.Push(std::move(notif)); |
122 | 170 |
|
123 | 171 | systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); |
124 | 172 | } |
125 | 173 | } |
126 | 174 |
|
127 | | -bool AlertNotificationClient::IsDiscovered() const { |
128 | | - return isDiscovered; |
129 | | -} |
130 | | - |
131 | | -uint16_t AlertNotificationClient::StartHandle() const { |
132 | | - return ansStartHandle; |
133 | | -} |
134 | | - |
135 | | -uint16_t AlertNotificationClient::EndHandle() const { |
136 | | - return ansEndHandle; |
| 175 | +void AlertNotificationClient::Reset() { |
| 176 | + ansStartHandle = 0; |
| 177 | + ansEndHandle = 0; |
| 178 | + supportedNewAlertCategoryHandle = 0; |
| 179 | + supportedUnreadAlertCategoryHandle = 0; |
| 180 | + newAlertHandle = 0; |
| 181 | + newAlertDescriptorHandle = 0; |
| 182 | + newAlertDefHandle = 0; |
| 183 | + unreadAlertStatusHandle = 0; |
| 184 | + controlPointHandle = 0; |
| 185 | + isDiscovered = false; |
| 186 | + isCharacteristicDiscovered = false; |
| 187 | + isDescriptorFound = false; |
137 | 188 | } |
138 | 189 |
|
139 | | -uint16_t AlertNotificationClient::NewAlerthandle() const { |
140 | | - return newAlertHandle; |
| 190 | +void AlertNotificationClient::Discover(uint16_t connectionHandle, std::function<void(uint16_t)> onServiceDiscovered) { |
| 191 | + NRF_LOG_INFO("[ANS] Starting discovery"); |
| 192 | + this->onServiceDiscovered = onServiceDiscovered; |
| 193 | + ble_gattc_disc_svc_by_uuid(connectionHandle, &ansServiceUuid.u, OnDiscoveryEventCallback, this); |
141 | 194 | } |
0 commit comments