1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #define LOG_TAG "BtGatt.JNI"
19
20 #define LOG_NDEBUG 0
21
22 #define CHECK_CALLBACK_ENV \
23 if (!checkCallbackThread()) { \
24 error("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
25 return; \
26 }
27
28 #include "com_android_bluetooth.h"
29 #include "hardware/bt_gatt.h"
30 #include "utils/Log.h"
31 #include "android_runtime/AndroidRuntime.h"
32
33 #include <string.h>
34
35 #include <cutils/log.h>
36 #define info(fmt, ...) ALOGI ("%s(L%d): " fmt,__FUNCTION__, __LINE__, ## __VA_ARGS__)
37 #define debug(fmt, ...) ALOGD ("%s(L%d): " fmt,__FUNCTION__, __LINE__, ## __VA_ARGS__)
38 #define warn(fmt, ...) ALOGW ("WARNING: %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__)
39 #define error(fmt, ...) ALOGE ("ERROR: %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__)
40 #define asrt(s) if(!(s)) ALOGE ("%s(L%d): ASSERT %s failed! ##",__FUNCTION__, __LINE__, #s)
41
42 #define BD_ADDR_LEN 6
43
44 #define UUID_PARAMS(uuid_ptr) \
45 uuid_lsb(uuid_ptr), uuid_msb(uuid_ptr)
46
47 #define GATT_ID_PARAMS(attr_ptr) \
48 attr_ptr->inst_id, \
49 UUID_PARAMS((&attr_ptr->uuid))
50
51 #define SRVC_ID_PARAMS(srvc_ptr) \
52 (srvc_ptr->is_primary ? \
53 BTGATT_SERVICE_TYPE_PRIMARY : BTGATT_SERVICE_TYPE_SECONDARY), \
54 GATT_ID_PARAMS((&srvc_ptr->id))
55
56
set_uuid(uint8_t * uuid,jlong uuid_msb,jlong uuid_lsb)57 static void set_uuid(uint8_t* uuid, jlong uuid_msb, jlong uuid_lsb)
58 {
59 for (int i = 0; i != 8; ++i)
60 {
61 uuid[i] = (uuid_lsb >> (8 * i)) & 0xFF;
62 uuid[i + 8] = (uuid_msb >> (8 * i)) & 0xFF;
63 }
64 }
65
uuid_lsb(bt_uuid_t * uuid)66 static uint64_t uuid_lsb(bt_uuid_t* uuid)
67 {
68 uint64_t lsb = 0;
69 int i;
70
71 for (i = 7; i >= 0; i--)
72 {
73 lsb <<= 8;
74 lsb |= uuid->uu[i];
75 }
76
77 return lsb;
78 }
79
uuid_msb(bt_uuid_t * uuid)80 static uint64_t uuid_msb(bt_uuid_t* uuid)
81 {
82 uint64_t msb = 0;
83 int i;
84
85 for (i = 15; i >= 8; i--)
86 {
87 msb <<= 8;
88 msb |= uuid->uu[i];
89 }
90
91 return msb;
92 }
93
bd_addr_str_to_addr(const char * str,uint8_t * bd_addr)94 static void bd_addr_str_to_addr(const char* str, uint8_t *bd_addr)
95 {
96 int i;
97 char c;
98
99 c = *str++;
100 for (i = 0; i < BD_ADDR_LEN; i++)
101 {
102 if (c >= '0' && c <= '9')
103 bd_addr[i] = c - '0';
104 else if (c >= 'a' && c <= 'z')
105 bd_addr[i] = c - 'a' + 10;
106 else // (c >= 'A' && c <= 'Z')
107 bd_addr[i] = c - 'A' + 10;
108
109 c = *str++;
110 if (c != ':')
111 {
112 bd_addr[i] <<= 4;
113 if (c >= '0' && c <= '9')
114 bd_addr[i] |= c - '0';
115 else if (c >= 'a' && c <= 'z')
116 bd_addr[i] |= c - 'a' + 10;
117 else // (c >= 'A' && c <= 'Z')
118 bd_addr[i] |= c - 'A' + 10;
119
120 c = *str++;
121 }
122
123 c = *str++;
124 }
125 }
126
jstr2bdaddr(JNIEnv * env,bt_bdaddr_t * bda,jstring address)127 static void jstr2bdaddr(JNIEnv* env, bt_bdaddr_t *bda, jstring address)
128 {
129 const char* c_bda = env->GetStringUTFChars(address, NULL);
130 if (c_bda != NULL && bda != NULL && strlen(c_bda) == 17)
131 {
132 bd_addr_str_to_addr(c_bda, bda->address);
133 env->ReleaseStringUTFChars(address, c_bda);
134 }
135 }
136
137 namespace android {
138
139 /**
140 * Client callback methods
141 */
142
143 static jmethodID method_onClientRegistered;
144 static jmethodID method_onScanResult;
145 static jmethodID method_onConnected;
146 static jmethodID method_onDisconnected;
147 static jmethodID method_onReadCharacteristic;
148 static jmethodID method_onWriteCharacteristic;
149 static jmethodID method_onExecuteCompleted;
150 static jmethodID method_onSearchCompleted;
151 static jmethodID method_onSearchResult;
152 static jmethodID method_onReadDescrExtProp;
153 static jmethodID method_onReadDescriptor;
154 static jmethodID method_onWriteDescriptor;
155 static jmethodID method_onNotify;
156 static jmethodID method_onGetCharacteristic;
157 static jmethodID method_onGetDescriptor;
158 static jmethodID method_onGetIncludedService;
159 static jmethodID method_onRegisterForNotifications;
160 static jmethodID method_onReadRemoteRssi;
161 static jmethodID method_onAdvertiseCallback;
162
163 /**
164 * Server callback methods
165 */
166 static jmethodID method_onServerRegistered;
167 static jmethodID method_onClientConnected;
168 static jmethodID method_onServiceAdded;
169 static jmethodID method_onIncludedServiceAdded;
170 static jmethodID method_onCharacteristicAdded;
171 static jmethodID method_onDescriptorAdded;
172 static jmethodID method_onServiceStarted;
173 static jmethodID method_onServiceStopped;
174 static jmethodID method_onServiceDeleted;
175 static jmethodID method_onResponseSendCompleted;
176 static jmethodID method_onAttributeRead;
177 static jmethodID method_onAttributeWrite;
178 static jmethodID method_onExecuteWrite;
179
180 /**
181 * Static variables
182 */
183
184 static const btgatt_interface_t *sGattIf = NULL;
185 static jobject mCallbacksObj = NULL;
186 static JNIEnv *sCallbackEnv = NULL;
187
checkCallbackThread()188 static bool checkCallbackThread() {
189 sCallbackEnv = getCallbackEnv();
190
191 JNIEnv* env = AndroidRuntime::getJNIEnv();
192 if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
193 return true;
194 }
195
196 /**
197 * BTA client callbacks
198 */
199
btgattc_register_app_cb(int status,int clientIf,bt_uuid_t * app_uuid)200 void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid)
201 {
202 CHECK_CALLBACK_ENV
203 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status,
204 clientIf, UUID_PARAMS(app_uuid));
205 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
206 }
207
btgattc_scan_result_cb(bt_bdaddr_t * bda,int rssi,uint8_t * adv_data)208 void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data)
209 {
210 CHECK_CALLBACK_ENV
211
212 char c_address[32];
213 snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
214 bda->address[0], bda->address[1], bda->address[2],
215 bda->address[3], bda->address[4], bda->address[5]);
216
217 jstring address = sCallbackEnv->NewStringUTF(c_address);
218 jbyteArray jb = sCallbackEnv->NewByteArray(62);
219 sCallbackEnv->SetByteArrayRegion(jb, 0, 62, (jbyte *) adv_data);
220
221 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanResult
222 , address, rssi, jb);
223
224 sCallbackEnv->DeleteLocalRef(address);
225 sCallbackEnv->DeleteLocalRef(jb);
226 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
227 }
228
btgattc_open_cb(int conn_id,int status,int clientIf,bt_bdaddr_t * bda)229 void btgattc_open_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
230 {
231 CHECK_CALLBACK_ENV
232
233 char c_address[32];
234 snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
235 bda->address[0], bda->address[1], bda->address[2],
236 bda->address[3], bda->address[4], bda->address[5]);
237
238 jstring address = sCallbackEnv->NewStringUTF(c_address);
239 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnected,
240 clientIf, conn_id, status, address);
241 sCallbackEnv->DeleteLocalRef(address);
242 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
243 }
244
btgattc_close_cb(int conn_id,int status,int clientIf,bt_bdaddr_t * bda)245 void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
246 {
247 CHECK_CALLBACK_ENV
248 char c_address[32];
249 snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
250 bda->address[0], bda->address[1], bda->address[2],
251 bda->address[3], bda->address[4], bda->address[5]);
252
253 jstring address = sCallbackEnv->NewStringUTF(c_address);
254 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDisconnected,
255 clientIf, conn_id, status, address);
256 sCallbackEnv->DeleteLocalRef(address);
257 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
258 }
259
btgattc_search_complete_cb(int conn_id,int status)260 void btgattc_search_complete_cb(int conn_id, int status)
261 {
262 CHECK_CALLBACK_ENV
263 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchCompleted,
264 conn_id, status);
265 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
266 }
267
btgattc_search_result_cb(int conn_id,btgatt_srvc_id_t * srvc_id)268 void btgattc_search_result_cb(int conn_id, btgatt_srvc_id_t *srvc_id)
269 {
270 CHECK_CALLBACK_ENV
271 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchResult, conn_id,
272 SRVC_ID_PARAMS(srvc_id));
273 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
274 }
275
btgattc_get_characteristic_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_gatt_id_t * char_id,int char_prop)276 void btgattc_get_characteristic_cb(int conn_id, int status,
277 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
278 int char_prop)
279 {
280 CHECK_CALLBACK_ENV
281 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetCharacteristic
282 , conn_id, status, SRVC_ID_PARAMS(srvc_id), GATT_ID_PARAMS(char_id)
283 , char_prop);
284 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
285 }
286
btgattc_get_descriptor_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_gatt_id_t * char_id,btgatt_gatt_id_t * descr_id)287 void btgattc_get_descriptor_cb(int conn_id, int status,
288 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
289 btgatt_gatt_id_t *descr_id)
290 {
291 CHECK_CALLBACK_ENV
292 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetDescriptor
293 , conn_id, status, SRVC_ID_PARAMS(srvc_id), GATT_ID_PARAMS(char_id)
294 , GATT_ID_PARAMS(descr_id));
295 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
296 }
297
btgattc_get_included_service_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_srvc_id_t * incl_srvc_id)298 void btgattc_get_included_service_cb(int conn_id, int status,
299 btgatt_srvc_id_t *srvc_id, btgatt_srvc_id_t *incl_srvc_id)
300 {
301 CHECK_CALLBACK_ENV
302 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetIncludedService
303 , conn_id, status, SRVC_ID_PARAMS(srvc_id), SRVC_ID_PARAMS(incl_srvc_id));
304 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
305 }
306
btgattc_register_for_notification_cb(int conn_id,int registered,int status,btgatt_srvc_id_t * srvc_id,btgatt_gatt_id_t * char_id)307 void btgattc_register_for_notification_cb(int conn_id, int registered, int status,
308 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
309 {
310 CHECK_CALLBACK_ENV
311 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRegisterForNotifications
312 , conn_id, status, registered, SRVC_ID_PARAMS(srvc_id), GATT_ID_PARAMS(char_id));
313 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
314 }
315
btgattc_notify_cb(int conn_id,btgatt_notify_params_t * p_data)316 void btgattc_notify_cb(int conn_id, btgatt_notify_params_t *p_data)
317 {
318 CHECK_CALLBACK_ENV
319
320 char c_address[32];
321 snprintf(c_address, sizeof(c_address), "%02X:%02X:%02X:%02X:%02X:%02X",
322 p_data->bda.address[0], p_data->bda.address[1], p_data->bda.address[2],
323 p_data->bda.address[3], p_data->bda.address[4], p_data->bda.address[5]);
324
325 jstring address = sCallbackEnv->NewStringUTF(c_address);
326 jbyteArray jb = sCallbackEnv->NewByteArray(p_data->len);
327 sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->len, (jbyte *) p_data->value);
328
329 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNotify
330 , conn_id, address, SRVC_ID_PARAMS((&p_data->srvc_id))
331 , GATT_ID_PARAMS((&p_data->char_id)), p_data->is_notify, jb);
332
333 sCallbackEnv->DeleteLocalRef(address);
334 sCallbackEnv->DeleteLocalRef(jb);
335 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
336 }
337
btgattc_read_characteristic_cb(int conn_id,int status,btgatt_read_params_t * p_data)338 void btgattc_read_characteristic_cb(int conn_id, int status, btgatt_read_params_t *p_data)
339 {
340 CHECK_CALLBACK_ENV
341
342 jbyteArray jb;
343 if ( status == 0 ) //successful
344 {
345 jb = sCallbackEnv->NewByteArray(p_data->value.len);
346 sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->value.len,
347 (jbyte *) p_data->value.value);
348 } else {
349 uint8_t value = 0;
350 jb = sCallbackEnv->NewByteArray(1);
351 sCallbackEnv->SetByteArrayRegion(jb, 0, 1, (jbyte *) &value);
352 }
353
354 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadCharacteristic
355 , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
356 , GATT_ID_PARAMS((&p_data->char_id)), p_data->value_type, jb);
357 sCallbackEnv->DeleteLocalRef(jb);
358 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
359 }
360
btgattc_write_characteristic_cb(int conn_id,int status,btgatt_write_params_t * p_data)361 void btgattc_write_characteristic_cb(int conn_id, int status, btgatt_write_params_t *p_data)
362 {
363 CHECK_CALLBACK_ENV
364 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic
365 , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
366 , GATT_ID_PARAMS((&p_data->char_id)));
367 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
368 }
369
btgattc_execute_write_cb(int conn_id,int status)370 void btgattc_execute_write_cb(int conn_id, int status)
371 {
372 CHECK_CALLBACK_ENV
373 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteCompleted
374 , conn_id, status);
375 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
376 }
377
btgattc_read_descriptor_cb(int conn_id,int status,btgatt_read_params_t * p_data)378 void btgattc_read_descriptor_cb(int conn_id, int status, btgatt_read_params_t *p_data)
379 {
380 CHECK_CALLBACK_ENV
381
382 jbyteArray jb;
383 if ( p_data->value.len != 0 )
384 {
385 jb = sCallbackEnv->NewByteArray(p_data->value.len);
386 sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->value.len,
387 (jbyte *) p_data->value.value);
388 } else {
389 jb = sCallbackEnv->NewByteArray(1);
390 }
391
392 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadDescriptor
393 , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
394 , GATT_ID_PARAMS((&p_data->char_id)), GATT_ID_PARAMS((&p_data->descr_id))
395 , p_data->value_type, jb);
396
397 sCallbackEnv->DeleteLocalRef(jb);
398 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
399 }
400
btgattc_write_descriptor_cb(int conn_id,int status,btgatt_write_params_t * p_data)401 void btgattc_write_descriptor_cb(int conn_id, int status, btgatt_write_params_t *p_data)
402 {
403 CHECK_CALLBACK_ENV
404 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor
405 , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
406 , GATT_ID_PARAMS((&p_data->char_id))
407 , GATT_ID_PARAMS((&p_data->descr_id)));
408 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
409 }
410
btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t * bda,int rssi,int status)411 void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status)
412 {
413 CHECK_CALLBACK_ENV
414
415 char c_address[32];
416 snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
417 bda->address[0], bda->address[1], bda->address[2],
418 bda->address[3], bda->address[4], bda->address[5]);
419 jstring address = sCallbackEnv->NewStringUTF(c_address);
420 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadRemoteRssi,
421 client_if, address, rssi, status);
422 sCallbackEnv->DeleteLocalRef(address);
423 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
424 }
425
btgattc_advertise_cb(int status,int client_if)426 void btgattc_advertise_cb(int status, int client_if)
427 {
428 CHECK_CALLBACK_ENV
429 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiseCallback, status, client_if);
430 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
431 }
432
433 static const btgatt_client_callbacks_t sGattClientCallbacks = {
434 btgattc_register_app_cb,
435 btgattc_scan_result_cb,
436 btgattc_open_cb,
437 btgattc_close_cb,
438 btgattc_search_complete_cb,
439 btgattc_search_result_cb,
440 btgattc_get_characteristic_cb,
441 btgattc_get_descriptor_cb,
442 btgattc_get_included_service_cb,
443 btgattc_register_for_notification_cb,
444 btgattc_notify_cb,
445 btgattc_read_characteristic_cb,
446 btgattc_write_characteristic_cb,
447 btgattc_read_descriptor_cb,
448 btgattc_write_descriptor_cb,
449 btgattc_execute_write_cb,
450 btgattc_remote_rssi_cb,
451 btgattc_advertise_cb
452 };
453
454
455 /**
456 * BTA server callbacks
457 */
458
btgatts_register_app_cb(int status,int server_if,bt_uuid_t * uuid)459 void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid)
460 {
461 CHECK_CALLBACK_ENV
462 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerRegistered
463 , status, server_if, UUID_PARAMS(uuid));
464 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
465 }
466
btgatts_connection_cb(int conn_id,int server_if,int connected,bt_bdaddr_t * bda)467 void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda)
468 {
469 CHECK_CALLBACK_ENV
470
471 char c_address[32];
472 sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
473 bda->address[0], bda->address[1], bda->address[2],
474 bda->address[3], bda->address[4], bda->address[5]);
475
476 jstring address = sCallbackEnv->NewStringUTF(c_address);
477 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientConnected,
478 address, connected, conn_id, server_if);
479 sCallbackEnv->DeleteLocalRef(address);
480 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
481 }
482
btgatts_service_added_cb(int status,int server_if,btgatt_srvc_id_t * srvc_id,int srvc_handle)483 void btgatts_service_added_cb(int status, int server_if,
484 btgatt_srvc_id_t *srvc_id, int srvc_handle)
485 {
486 CHECK_CALLBACK_ENV
487 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceAdded, status,
488 server_if, SRVC_ID_PARAMS(srvc_id),
489 srvc_handle);
490 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
491 }
492
btgatts_included_service_added_cb(int status,int server_if,int srvc_handle,int incl_srvc_handle)493 void btgatts_included_service_added_cb(int status, int server_if,
494 int srvc_handle,
495 int incl_srvc_handle)
496 {
497 CHECK_CALLBACK_ENV
498 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onIncludedServiceAdded,
499 status, server_if, srvc_handle, incl_srvc_handle);
500 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
501 }
502
btgatts_characteristic_added_cb(int status,int server_if,bt_uuid_t * char_id,int srvc_handle,int char_handle)503 void btgatts_characteristic_added_cb(int status, int server_if, bt_uuid_t *char_id,
504 int srvc_handle, int char_handle)
505 {
506 CHECK_CALLBACK_ENV
507 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCharacteristicAdded,
508 status, server_if, UUID_PARAMS(char_id),
509 srvc_handle, char_handle);
510 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
511 }
512
btgatts_descriptor_added_cb(int status,int server_if,bt_uuid_t * descr_id,int srvc_handle,int descr_handle)513 void btgatts_descriptor_added_cb(int status, int server_if,
514 bt_uuid_t *descr_id, int srvc_handle,
515 int descr_handle)
516 {
517 CHECK_CALLBACK_ENV
518 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDescriptorAdded,
519 status, server_if, UUID_PARAMS(descr_id),
520 srvc_handle, descr_handle);
521 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
522 }
523
btgatts_service_started_cb(int status,int server_if,int srvc_handle)524 void btgatts_service_started_cb(int status, int server_if, int srvc_handle)
525 {
526 CHECK_CALLBACK_ENV
527 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceStarted, status,
528 server_if, srvc_handle);
529 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
530 }
531
btgatts_service_stopped_cb(int status,int server_if,int srvc_handle)532 void btgatts_service_stopped_cb(int status, int server_if, int srvc_handle)
533 {
534 CHECK_CALLBACK_ENV
535 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceStopped, status,
536 server_if, srvc_handle);
537 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
538 }
539
btgatts_service_deleted_cb(int status,int server_if,int srvc_handle)540 void btgatts_service_deleted_cb(int status, int server_if, int srvc_handle)
541 {
542 CHECK_CALLBACK_ENV
543 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceDeleted, status,
544 server_if, srvc_handle);
545 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
546 }
547
btgatts_request_read_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int attr_handle,int offset,bool is_long)548 void btgatts_request_read_cb(int conn_id, int trans_id, bt_bdaddr_t *bda,
549 int attr_handle, int offset, bool is_long)
550 {
551 CHECK_CALLBACK_ENV
552
553 char c_address[32];
554 sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
555 bda->address[0], bda->address[1], bda->address[2],
556 bda->address[3], bda->address[4], bda->address[5]);
557
558 jstring address = sCallbackEnv->NewStringUTF(c_address);
559 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAttributeRead,
560 address, conn_id, trans_id, attr_handle,
561 offset, is_long);
562 sCallbackEnv->DeleteLocalRef(address);
563 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
564 }
565
btgatts_request_write_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int attr_handle,int offset,int length,bool need_rsp,bool is_prep,uint8_t * value)566 void btgatts_request_write_cb(int conn_id, int trans_id,
567 bt_bdaddr_t *bda, int attr_handle,
568 int offset, int length,
569 bool need_rsp, bool is_prep, uint8_t* value)
570 {
571 CHECK_CALLBACK_ENV
572
573 char c_address[32];
574 sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
575 bda->address[0], bda->address[1], bda->address[2],
576 bda->address[3], bda->address[4], bda->address[5]);
577
578 jstring address = sCallbackEnv->NewStringUTF(c_address);
579
580 jbyteArray val = sCallbackEnv->NewByteArray(length);
581 if (val) sCallbackEnv->SetByteArrayRegion(val, 0, length, (jbyte*)value);
582 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAttributeWrite,
583 address, conn_id, trans_id, attr_handle,
584 offset, length, need_rsp, is_prep, val);
585 sCallbackEnv->DeleteLocalRef(address);
586 sCallbackEnv->DeleteLocalRef(val);
587 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
588 }
589
btgatts_request_exec_write_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int exec_write)590 void btgatts_request_exec_write_cb(int conn_id, int trans_id,
591 bt_bdaddr_t *bda, int exec_write)
592 {
593 CHECK_CALLBACK_ENV
594
595 char c_address[32];
596 sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
597 bda->address[0], bda->address[1], bda->address[2],
598 bda->address[3], bda->address[4], bda->address[5]);
599
600 jstring address = sCallbackEnv->NewStringUTF(c_address);
601 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteWrite,
602 address, conn_id, trans_id, exec_write);
603 sCallbackEnv->DeleteLocalRef(address);
604 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
605 }
606
btgatts_response_confirmation_cb(int status,int handle)607 void btgatts_response_confirmation_cb(int status, int handle)
608 {
609 CHECK_CALLBACK_ENV
610 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onResponseSendCompleted,
611 status, handle);
612 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
613 }
614
615 static const btgatt_server_callbacks_t sGattServerCallbacks = {
616 btgatts_register_app_cb,
617 btgatts_connection_cb,
618 btgatts_service_added_cb,
619 btgatts_included_service_added_cb,
620 btgatts_characteristic_added_cb,
621 btgatts_descriptor_added_cb,
622 btgatts_service_started_cb,
623 btgatts_service_stopped_cb,
624 btgatts_service_deleted_cb,
625 btgatts_request_read_cb,
626 btgatts_request_write_cb,
627 btgatts_request_exec_write_cb,
628 btgatts_response_confirmation_cb
629 };
630
631 /**
632 * GATT callbacks
633 */
634
635 static const btgatt_callbacks_t sGattCallbacks = {
636 sizeof(btgatt_callbacks_t),
637 &sGattClientCallbacks,
638 &sGattServerCallbacks
639 };
640
641 /**
642 * Native function definitions
643 */
644
classInitNative(JNIEnv * env,jclass clazz)645 static void classInitNative(JNIEnv* env, jclass clazz) {
646
647 // Client callbacks
648
649 method_onClientRegistered = env->GetMethodID(clazz, "onClientRegistered", "(IIJJ)V");
650 method_onScanResult = env->GetMethodID(clazz, "onScanResult", "(Ljava/lang/String;I[B)V");
651 method_onConnected = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V");
652 method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V");
653 method_onReadCharacteristic = env->GetMethodID(clazz, "onReadCharacteristic", "(IIIIJJIJJI[B)V");
654 method_onWriteCharacteristic = env->GetMethodID(clazz, "onWriteCharacteristic", "(IIIIJJIJJ)V");
655 method_onExecuteCompleted = env->GetMethodID(clazz, "onExecuteCompleted", "(II)V");
656 method_onSearchCompleted = env->GetMethodID(clazz, "onSearchCompleted", "(II)V");
657 method_onSearchResult = env->GetMethodID(clazz, "onSearchResult", "(IIIJJ)V");
658 method_onReadDescriptor = env->GetMethodID(clazz, "onReadDescriptor", "(IIIIJJIJJIJJI[B)V");
659 method_onWriteDescriptor = env->GetMethodID(clazz, "onWriteDescriptor", "(IIIIJJIJJIJJ)V");
660 method_onNotify = env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IIJJIJJZ[B)V");
661 method_onGetCharacteristic = env->GetMethodID(clazz, "onGetCharacteristic", "(IIIIJJIJJI)V");
662 method_onGetDescriptor = env->GetMethodID(clazz, "onGetDescriptor", "(IIIIJJIJJIJJ)V");
663 method_onGetIncludedService = env->GetMethodID(clazz, "onGetIncludedService", "(IIIIJJIIJJ)V");
664 method_onRegisterForNotifications = env->GetMethodID(clazz, "onRegisterForNotifications", "(IIIIIJJIJJ)V");
665 method_onReadRemoteRssi = env->GetMethodID(clazz, "onReadRemoteRssi", "(ILjava/lang/String;II)V");
666
667 // Server callbacks
668
669 method_onServerRegistered = env->GetMethodID(clazz, "onServerRegistered", "(IIJJ)V");
670 method_onClientConnected = env->GetMethodID(clazz, "onClientConnected", "(Ljava/lang/String;ZII)V");
671 method_onServiceAdded = env->GetMethodID(clazz, "onServiceAdded", "(IIIIJJI)V");
672 method_onIncludedServiceAdded = env->GetMethodID(clazz, "onIncludedServiceAdded", "(IIII)V");
673 method_onCharacteristicAdded = env->GetMethodID(clazz, "onCharacteristicAdded", "(IIJJII)V");
674 method_onDescriptorAdded = env->GetMethodID(clazz, "onDescriptorAdded", "(IIJJII)V");
675 method_onServiceStarted = env->GetMethodID(clazz, "onServiceStarted", "(III)V");
676 method_onServiceStopped = env->GetMethodID(clazz, "onServiceStopped", "(III)V");
677 method_onServiceDeleted = env->GetMethodID(clazz, "onServiceDeleted", "(III)V");
678 method_onResponseSendCompleted = env->GetMethodID(clazz, "onResponseSendCompleted", "(II)V");
679 method_onAttributeRead= env->GetMethodID(clazz, "onAttributeRead", "(Ljava/lang/String;IIIIZ)V");
680 method_onAttributeWrite= env->GetMethodID(clazz, "onAttributeWrite", "(Ljava/lang/String;IIIIIZZ[B)V");
681 method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V");
682 method_onAdvertiseCallback = env->GetMethodID(clazz, "onAdvertiseCallback", "(II)V");
683
684 info("classInitNative: Success!");
685 }
686
687 static const bt_interface_t* btIf;
688
initializeNative(JNIEnv * env,jobject object)689 static void initializeNative(JNIEnv *env, jobject object) {
690 if(btIf)
691 return;
692
693 if ( (btIf = getBluetoothInterface()) == NULL) {
694 error("Bluetooth module is not loaded");
695 return;
696 }
697
698 if (sGattIf != NULL) {
699 ALOGW("Cleaning up Bluetooth GATT Interface before initializing...");
700 sGattIf->cleanup();
701 sGattIf = NULL;
702 }
703
704 if (mCallbacksObj != NULL) {
705 ALOGW("Cleaning up Bluetooth GATT callback object");
706 env->DeleteGlobalRef(mCallbacksObj);
707 mCallbacksObj = NULL;
708 }
709
710 if ( (sGattIf = (btgatt_interface_t *)
711 btIf->get_profile_interface(BT_PROFILE_GATT_ID)) == NULL) {
712 error("Failed to get Bluetooth GATT Interface");
713 return;
714 }
715
716 bt_status_t status;
717 if ( (status = sGattIf->init(&sGattCallbacks)) != BT_STATUS_SUCCESS) {
718 error("Failed to initialize Bluetooth GATT, status: %d", status);
719 sGattIf = NULL;
720 return;
721 }
722
723 mCallbacksObj = env->NewGlobalRef(object);
724 }
725
cleanupNative(JNIEnv * env,jobject object)726 static void cleanupNative(JNIEnv *env, jobject object) {
727 bt_status_t status;
728 if (!btIf) return;
729
730 if (sGattIf != NULL) {
731 sGattIf->cleanup();
732 sGattIf = NULL;
733 }
734
735 if (mCallbacksObj != NULL) {
736 env->DeleteGlobalRef(mCallbacksObj);
737 mCallbacksObj = NULL;
738 }
739 btIf = NULL;
740 }
741
742 /**
743 * Native Client functions
744 */
745
gattClientGetDeviceTypeNative(JNIEnv * env,jobject object,jstring address)746 static int gattClientGetDeviceTypeNative(JNIEnv* env, jobject object, jstring address)
747 {
748 if (!sGattIf) return 0;
749 bt_bdaddr_t bda;
750 jstr2bdaddr(env, &bda, address);
751 return sGattIf->client->get_device_type(&bda);
752 }
753
gattClientRegisterAppNative(JNIEnv * env,jobject object,jlong app_uuid_lsb,jlong app_uuid_msb)754 static void gattClientRegisterAppNative(JNIEnv* env, jobject object,
755 jlong app_uuid_lsb, jlong app_uuid_msb )
756 {
757 bt_uuid_t uuid;
758
759 if (!sGattIf) return;
760 set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
761 sGattIf->client->register_client(&uuid);
762 }
763
gattClientUnregisterAppNative(JNIEnv * env,jobject object,jint clientIf)764 static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clientIf)
765 {
766 if (!sGattIf) return;
767 sGattIf->client->unregister_client(clientIf);
768 }
769
gattClientScanNative(JNIEnv * env,jobject object,jint clientIf,jboolean start)770 static void gattClientScanNative(JNIEnv* env, jobject object, jint clientIf, jboolean start)
771 {
772 if (!sGattIf) return;
773 sGattIf->client->scan(clientIf, start);
774 }
775
gattClientConnectNative(JNIEnv * env,jobject object,jint clientif,jstring address,jboolean isDirect)776 static void gattClientConnectNative(JNIEnv* env, jobject object, jint clientif,
777 jstring address, jboolean isDirect)
778 {
779 if (!sGattIf) return;
780
781 bt_bdaddr_t bda;
782 jstr2bdaddr(env, &bda, address);
783 sGattIf->client->connect(clientif, &bda, isDirect);
784 }
785
gattClientDisconnectNative(JNIEnv * env,jobject object,jint clientIf,jstring address,jint conn_id)786 static void gattClientDisconnectNative(JNIEnv* env, jobject object, jint clientIf,
787 jstring address, jint conn_id)
788 {
789 if (!sGattIf) return;
790 bt_bdaddr_t bda;
791 jstr2bdaddr(env, &bda, address);
792 sGattIf->client->disconnect(clientIf, &bda, conn_id);
793 }
794
gattClientRefreshNative(JNIEnv * env,jobject object,jint clientIf,jstring address)795 static void gattClientRefreshNative(JNIEnv* env, jobject object, jint clientIf,
796 jstring address)
797 {
798 if (!sGattIf) return;
799
800 bt_bdaddr_t bda;
801 jstr2bdaddr(env, &bda, address);
802 sGattIf->client->refresh(clientIf, &bda);
803 }
804
gattClientSearchServiceNative(JNIEnv * env,jobject object,jint conn_id,jboolean search_all,jlong service_uuid_lsb,jlong service_uuid_msb)805 static void gattClientSearchServiceNative(JNIEnv* env, jobject object, jint conn_id,
806 jboolean search_all, jlong service_uuid_lsb, jlong service_uuid_msb)
807 {
808 if (!sGattIf) return;
809
810 bt_uuid_t uuid;
811 set_uuid(uuid.uu, service_uuid_msb, service_uuid_lsb);
812 sGattIf->client->search_service(conn_id, search_all ? 0 : &uuid);
813 }
814
gattClientGetCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb)815 static void gattClientGetCharacteristicNative(JNIEnv* env, jobject object,
816 jint conn_id,
817 jint service_type, jint service_id_inst_id,
818 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
819 jint char_id_inst_id,
820 jlong char_id_uuid_lsb, jlong char_id_uuid_msb)
821 {
822 if (!sGattIf) return;
823
824 btgatt_srvc_id_t srvc_id;
825 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
826 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
827
828 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
829
830 btgatt_gatt_id_t char_id;
831 char_id.inst_id = (uint8_t) char_id_inst_id;
832 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
833
834 if (char_id_uuid_lsb == 0)
835 {
836 sGattIf->client->get_characteristic(conn_id, &srvc_id, 0);
837 } else {
838 sGattIf->client->get_characteristic(conn_id, &srvc_id, &char_id);
839 }
840 }
841
gattClientGetDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint descr_id_inst_id,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb)842 static void gattClientGetDescriptorNative(JNIEnv* env, jobject object,
843 jint conn_id,
844 jint service_type, jint service_id_inst_id,
845 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
846 jint char_id_inst_id,
847 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
848 jint descr_id_inst_id,
849 jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb)
850 {
851 if (!sGattIf) return;
852
853 btgatt_srvc_id_t srvc_id;
854 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
855 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
856 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
857
858 btgatt_gatt_id_t char_id;
859 char_id.inst_id = (uint8_t) char_id_inst_id;
860 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
861
862 btgatt_gatt_id_t descr_id;
863 descr_id.inst_id = (uint8_t) descr_id_inst_id;
864 set_uuid(descr_id.uuid.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
865
866 if (descr_id_uuid_lsb == 0)
867 {
868 sGattIf->client->get_descriptor(conn_id, &srvc_id, &char_id, 0);
869 } else {
870 sGattIf->client->get_descriptor(conn_id, &srvc_id, &char_id, &descr_id);
871 }
872 }
873
gattClientGetIncludedServiceNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint incl_service_id_inst_id,jint incl_service_type,jlong incl_service_id_uuid_lsb,jlong incl_service_id_uuid_msb)874 static void gattClientGetIncludedServiceNative(JNIEnv* env, jobject object,
875 jint conn_id, jint service_type, jint service_id_inst_id,
876 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
877 jint incl_service_id_inst_id, jint incl_service_type,
878 jlong incl_service_id_uuid_lsb, jlong incl_service_id_uuid_msb)
879 {
880 if (!sGattIf) return;
881
882 btgatt_srvc_id_t srvc_id;
883 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
884 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
885 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
886
887 btgatt_srvc_id_t incl_srvc_id;
888 incl_srvc_id.id.inst_id = (uint8_t) incl_service_id_inst_id;
889 incl_srvc_id.is_primary = (incl_service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
890 set_uuid(incl_srvc_id.id.uuid.uu, incl_service_id_uuid_msb, incl_service_id_uuid_lsb);
891
892 if (incl_service_id_uuid_lsb == 0)
893 {
894 sGattIf->client->get_included_service(conn_id, &srvc_id, 0);
895 } else {
896 sGattIf->client->get_included_service(conn_id, &srvc_id, &incl_srvc_id);
897 }
898 }
899
gattClientReadCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint authReq)900 static void gattClientReadCharacteristicNative(JNIEnv* env, jobject object,
901 jint conn_id, jint service_type, jint service_id_inst_id,
902 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
903 jint char_id_inst_id,
904 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
905 jint authReq)
906 {
907 if (!sGattIf) return;
908
909 btgatt_srvc_id_t srvc_id;
910 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
911 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
912 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
913
914 btgatt_gatt_id_t char_id;
915 char_id.inst_id = (uint8_t) char_id_inst_id;
916 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
917
918 sGattIf->client->read_characteristic(conn_id, &srvc_id, &char_id, authReq);
919 }
920
gattClientReadDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint descr_id_inst_id,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb,jint authReq)921 static void gattClientReadDescriptorNative(JNIEnv* env, jobject object,
922 jint conn_id, jint service_type, jint service_id_inst_id,
923 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
924 jint char_id_inst_id,
925 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
926 jint descr_id_inst_id,
927 jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
928 jint authReq)
929 {
930 if (!sGattIf) return;
931
932 btgatt_srvc_id_t srvc_id;
933 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
934 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
935 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
936
937 btgatt_gatt_id_t char_id;
938 char_id.inst_id = (uint8_t) char_id_inst_id;
939 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
940
941 btgatt_gatt_id_t descr_id;
942 descr_id.inst_id = (uint8_t) descr_id_inst_id;
943 set_uuid(descr_id.uuid.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
944
945 sGattIf->client->read_descriptor(conn_id, &srvc_id, &char_id, &descr_id, authReq);
946 }
947
gattClientWriteCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint write_type,jint auth_req,jbyteArray value)948 static void gattClientWriteCharacteristicNative(JNIEnv* env, jobject object,
949 jint conn_id, jint service_type, jint service_id_inst_id,
950 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
951 jint char_id_inst_id,
952 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
953 jint write_type, jint auth_req, jbyteArray value)
954 {
955 if (!sGattIf) return;
956
957 btgatt_srvc_id_t srvc_id;
958 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
959 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
960 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
961
962 btgatt_gatt_id_t char_id;
963 char_id.inst_id = (uint8_t) char_id_inst_id;
964 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
965
966 uint16_t len = (uint16_t) env->GetArrayLength(value);
967 jbyte *p_value = env->GetByteArrayElements(value, NULL);
968 if (p_value == NULL) return;
969
970 sGattIf->client->write_characteristic(conn_id, &srvc_id, &char_id,
971 write_type, len, auth_req, (char*)p_value);
972 env->ReleaseByteArrayElements(value, p_value, 0);
973 }
974
gattClientExecuteWriteNative(JNIEnv * env,jobject object,jint conn_id,jboolean execute)975 static void gattClientExecuteWriteNative(JNIEnv* env, jobject object,
976 jint conn_id, jboolean execute)
977 {
978 if (!sGattIf) return;
979 sGattIf->client->execute_write(conn_id, execute ? 1 : 0);
980 }
981
gattClientWriteDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint descr_id_inst_id,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb,jint write_type,jint auth_req,jbyteArray value)982 static void gattClientWriteDescriptorNative(JNIEnv* env, jobject object,
983 jint conn_id, jint service_type, jint service_id_inst_id,
984 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
985 jint char_id_inst_id,
986 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
987 jint descr_id_inst_id,
988 jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
989 jint write_type, jint auth_req, jbyteArray value)
990 {
991 if (!sGattIf) return;
992
993 if (value == NULL) {
994 warn("gattClientWriteDescriptorNative() ignoring NULL array");
995 return;
996 }
997
998 btgatt_srvc_id_t srvc_id;
999 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
1000 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
1001 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
1002
1003 btgatt_gatt_id_t char_id;
1004 char_id.inst_id = (uint8_t) char_id_inst_id;
1005 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
1006
1007 btgatt_gatt_id_t descr_id;
1008 descr_id.inst_id = (uint8_t) descr_id_inst_id;
1009 set_uuid(descr_id.uuid.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
1010
1011 uint16_t len = (uint16_t) env->GetArrayLength(value);
1012 jbyte *p_value = env->GetByteArrayElements(value, NULL);
1013 if (p_value == NULL) return;
1014
1015 sGattIf->client->write_descriptor(conn_id, &srvc_id, &char_id, &descr_id,
1016 write_type, len, auth_req, (char*)p_value);
1017 env->ReleaseByteArrayElements(value, p_value, 0);
1018 }
1019
gattClientRegisterForNotificationsNative(JNIEnv * env,jobject object,jint clientIf,jstring address,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jboolean enable)1020 static void gattClientRegisterForNotificationsNative(JNIEnv* env, jobject object,
1021 jint clientIf, jstring address,
1022 jint service_type, jint service_id_inst_id,
1023 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
1024 jint char_id_inst_id,
1025 jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
1026 jboolean enable)
1027 {
1028 if (!sGattIf) return;
1029
1030 btgatt_srvc_id_t srvc_id;
1031 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
1032 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
1033 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
1034
1035 btgatt_gatt_id_t char_id;
1036 char_id.inst_id = (uint8_t) char_id_inst_id;
1037 set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
1038
1039 bt_bdaddr_t bd_addr;
1040 const char *c_address = env->GetStringUTFChars(address, NULL);
1041 bd_addr_str_to_addr(c_address, bd_addr.address);
1042
1043 if (enable)
1044 sGattIf->client->register_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
1045 else
1046 sGattIf->client->deregister_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
1047 }
1048
gattClientReadRemoteRssiNative(JNIEnv * env,jobject object,jint clientif,jstring address)1049 static void gattClientReadRemoteRssiNative(JNIEnv* env, jobject object, jint clientif,
1050 jstring address)
1051 {
1052 if (!sGattIf) return;
1053
1054 bt_bdaddr_t bda;
1055 jstr2bdaddr(env, &bda, address);
1056
1057 sGattIf->client->read_remote_rssi(clientif, &bda);
1058 }
1059
gattAdvertiseNative(JNIEnv * env,jobject object,jint client_if,jboolean start)1060 static void gattAdvertiseNative(JNIEnv *env, jobject object,
1061 jint client_if, jboolean start)
1062 {
1063 if (!sGattIf) return;
1064 sGattIf->client->listen(client_if, start);
1065 }
1066
gattSetAdvDataNative(JNIEnv * env,jobject object,jint client_if,jboolean setScanRsp,jboolean inclName,jboolean inclTxPower,jint minInterval,jint maxInterval,jint appearance,jbyteArray manufacturerData,jbyteArray serviceData,jbyteArray serviceUuid)1067 static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if, jboolean setScanRsp,
1068 jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval,
1069 jint appearance, jbyteArray manufacturerData, jbyteArray serviceData,
1070 jbyteArray serviceUuid)
1071 {
1072 if (!sGattIf) return;
1073 jbyte* arr_data = env->GetByteArrayElements(manufacturerData, NULL);
1074 uint16_t arr_len = (uint16_t) env->GetArrayLength(manufacturerData);
1075
1076 jbyte* service_data = env->GetByteArrayElements(serviceData, NULL);
1077 uint16_t service_data_len = (uint16_t) env->GetArrayLength(serviceData);
1078
1079 jbyte* service_uuid = env->GetByteArrayElements(serviceUuid, NULL);
1080 uint16_t service_uuid_len = (uint16_t) env->GetArrayLength(serviceUuid);
1081
1082 sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower,
1083 minInterval, maxInterval, appearance, arr_len, (char*)arr_data,
1084 service_data_len, (char*)service_data, service_uuid_len,
1085 (char*)service_uuid);
1086
1087 env->ReleaseByteArrayElements(manufacturerData, arr_data, JNI_ABORT);
1088 env->ReleaseByteArrayElements(serviceData, service_data, JNI_ABORT);
1089 env->ReleaseByteArrayElements(serviceUuid, service_uuid, JNI_ABORT);
1090 }
1091
1092
1093 /**
1094 * Native server functions
1095 */
gattServerRegisterAppNative(JNIEnv * env,jobject object,jlong app_uuid_lsb,jlong app_uuid_msb)1096 static void gattServerRegisterAppNative(JNIEnv* env, jobject object,
1097 jlong app_uuid_lsb, jlong app_uuid_msb )
1098 {
1099 bt_uuid_t uuid;
1100 if (!sGattIf) return;
1101 set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
1102 sGattIf->server->register_server(&uuid);
1103 }
1104
gattServerUnregisterAppNative(JNIEnv * env,jobject object,jint serverIf)1105 static void gattServerUnregisterAppNative(JNIEnv* env, jobject object, jint serverIf)
1106 {
1107 if (!sGattIf) return;
1108 sGattIf->server->unregister_server(serverIf);
1109 }
1110
gattServerConnectNative(JNIEnv * env,jobject object,jint server_if,jstring address,jboolean is_direct)1111 static void gattServerConnectNative(JNIEnv *env, jobject object,
1112 jint server_if, jstring address, jboolean is_direct)
1113 {
1114 if (!sGattIf) return;
1115
1116 bt_bdaddr_t bd_addr;
1117 const char *c_address = env->GetStringUTFChars(address, NULL);
1118 bd_addr_str_to_addr(c_address, bd_addr.address);
1119
1120 sGattIf->server->connect(server_if, &bd_addr, is_direct);
1121 }
1122
gattServerDisconnectNative(JNIEnv * env,jobject object,jint serverIf,jstring address,jint conn_id)1123 static void gattServerDisconnectNative(JNIEnv* env, jobject object, jint serverIf,
1124 jstring address, jint conn_id)
1125 {
1126 if (!sGattIf) return;
1127 bt_bdaddr_t bda;
1128 jstr2bdaddr(env, &bda, address);
1129 sGattIf->server->disconnect(serverIf, &bda, conn_id);
1130 }
1131
gattServerAddServiceNative(JNIEnv * env,jobject object,jint server_if,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint num_handles)1132 static void gattServerAddServiceNative (JNIEnv *env, jobject object,
1133 jint server_if, jint service_type, jint service_id_inst_id,
1134 jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
1135 jint num_handles)
1136 {
1137 if (!sGattIf) return;
1138
1139 btgatt_srvc_id_t srvc_id;
1140 srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
1141 srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
1142 set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
1143
1144 sGattIf->server->add_service(server_if, &srvc_id, num_handles);
1145 }
1146
gattServerAddIncludedServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jint included_svc_handle)1147 static void gattServerAddIncludedServiceNative (JNIEnv *env, jobject object,
1148 jint server_if, jint svc_handle, jint included_svc_handle)
1149 {
1150 if (!sGattIf) return;
1151 sGattIf->server->add_included_service(server_if, svc_handle,
1152 included_svc_handle);
1153 }
1154
gattServerAddCharacteristicNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jlong char_uuid_lsb,jlong char_uuid_msb,jint properties,jint permissions)1155 static void gattServerAddCharacteristicNative (JNIEnv *env, jobject object,
1156 jint server_if, jint svc_handle,
1157 jlong char_uuid_lsb, jlong char_uuid_msb,
1158 jint properties, jint permissions)
1159 {
1160 if (!sGattIf) return;
1161
1162 bt_uuid_t uuid;
1163 set_uuid(uuid.uu, char_uuid_msb, char_uuid_lsb);
1164
1165 sGattIf->server->add_characteristic(server_if, svc_handle,
1166 &uuid, properties, permissions);
1167 }
1168
gattServerAddDescriptorNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jlong desc_uuid_lsb,jlong desc_uuid_msb,jint permissions)1169 static void gattServerAddDescriptorNative (JNIEnv *env, jobject object,
1170 jint server_if, jint svc_handle,
1171 jlong desc_uuid_lsb, jlong desc_uuid_msb,
1172 jint permissions)
1173 {
1174 if (!sGattIf) return;
1175
1176 bt_uuid_t uuid;
1177 set_uuid(uuid.uu, desc_uuid_msb, desc_uuid_lsb);
1178
1179 sGattIf->server->add_descriptor(server_if, svc_handle, &uuid, permissions);
1180 }
1181
gattServerStartServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jint transport)1182 static void gattServerStartServiceNative (JNIEnv *env, jobject object,
1183 jint server_if, jint svc_handle, jint transport )
1184 {
1185 if (!sGattIf) return;
1186 sGattIf->server->start_service(server_if, svc_handle, transport);
1187 }
1188
gattServerStopServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle)1189 static void gattServerStopServiceNative (JNIEnv *env, jobject object,
1190 jint server_if, jint svc_handle)
1191 {
1192 if (!sGattIf) return;
1193 sGattIf->server->stop_service(server_if, svc_handle);
1194 }
1195
gattServerDeleteServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle)1196 static void gattServerDeleteServiceNative (JNIEnv *env, jobject object,
1197 jint server_if, jint svc_handle)
1198 {
1199 if (!sGattIf) return;
1200 sGattIf->server->delete_service(server_if, svc_handle);
1201 }
1202
gattServerSendIndicationNative(JNIEnv * env,jobject object,jint server_if,jint attr_handle,jint conn_id,jbyteArray val)1203 static void gattServerSendIndicationNative (JNIEnv *env, jobject object,
1204 jint server_if, jint attr_handle, jint conn_id, jbyteArray val)
1205 {
1206 if (!sGattIf) return;
1207
1208 jbyte* array = env->GetByteArrayElements(val, 0);
1209 int val_len = env->GetArrayLength(val);
1210
1211 sGattIf->server->send_indication(server_if, attr_handle, conn_id, val_len,
1212 /*confirm*/ 1, (char*)array);
1213 env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1214 }
1215
gattServerSendNotificationNative(JNIEnv * env,jobject object,jint server_if,jint attr_handle,jint conn_id,jbyteArray val)1216 static void gattServerSendNotificationNative (JNIEnv *env, jobject object,
1217 jint server_if, jint attr_handle, jint conn_id, jbyteArray val)
1218 {
1219 if (!sGattIf) return;
1220
1221 jbyte* array = env->GetByteArrayElements(val, 0);
1222 int val_len = env->GetArrayLength(val);
1223
1224 sGattIf->server->send_indication(server_if, attr_handle, conn_id, val_len,
1225 /*confirm*/ 0, (char*)array);
1226 env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1227 }
1228
gattServerSendResponseNative(JNIEnv * env,jobject object,jint server_if,jint conn_id,jint trans_id,jint status,jint handle,jint offset,jbyteArray val,jint auth_req)1229 static void gattServerSendResponseNative (JNIEnv *env, jobject object,
1230 jint server_if, jint conn_id, jint trans_id, jint status,
1231 jint handle, jint offset, jbyteArray val, jint auth_req)
1232 {
1233 if (!sGattIf) return;
1234
1235 btgatt_response_t response;
1236
1237 response.attr_value.handle = handle;
1238 response.attr_value.auth_req = auth_req;
1239 response.attr_value.offset = offset;
1240 response.attr_value.len = 0;
1241
1242 if (val != NULL)
1243 {
1244 response.attr_value.len = (uint16_t) env->GetArrayLength(val);
1245 jbyte* array = env->GetByteArrayElements(val, 0);
1246
1247 for (int i = 0; i != response.attr_value.len; ++i)
1248 response.attr_value.value[i] = (uint8_t) array[i];
1249 env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1250 }
1251
1252 sGattIf->server->send_response(conn_id, trans_id, status, &response);
1253 }
1254
gattTestNative(JNIEnv * env,jobject object,jint command,jlong uuid1_lsb,jlong uuid1_msb,jstring bda1,jint p1,jint p2,jint p3,jint p4,jint p5)1255 static void gattTestNative(JNIEnv *env, jobject object, jint command,
1256 jlong uuid1_lsb, jlong uuid1_msb, jstring bda1,
1257 jint p1, jint p2, jint p3, jint p4, jint p5 )
1258 {
1259 if (!sGattIf) return;
1260
1261 bt_bdaddr_t bt_bda1;
1262 jstr2bdaddr(env, &bt_bda1, bda1);
1263
1264 bt_uuid_t uuid1;
1265 set_uuid(uuid1.uu, uuid1_msb, uuid1_lsb);
1266
1267 btgatt_test_params_t params;
1268 params.bda1 = &bt_bda1;
1269 params.uuid1 = &uuid1;
1270 params.u1 = p1;
1271 params.u2 = p2;
1272 params.u3 = p3;
1273 params.u4 = p4;
1274 params.u5 = p5;
1275 sGattIf->client->test_command(command, ¶ms);
1276 }
1277
1278 /**
1279 * JNI function definitinos
1280 */
1281
1282 static JNINativeMethod sMethods[] = {
1283 {"classInitNative", "()V", (void *) classInitNative},
1284 {"initializeNative", "()V", (void *) initializeNative},
1285 {"cleanupNative", "()V", (void *) cleanupNative},
1286
1287 {"gattClientGetDeviceTypeNative", "(Ljava/lang/String;)I", (void *) gattClientGetDeviceTypeNative},
1288 {"gattClientRegisterAppNative", "(JJ)V", (void *) gattClientRegisterAppNative},
1289 {"gattClientUnregisterAppNative", "(I)V", (void *) gattClientUnregisterAppNative},
1290 {"gattClientScanNative", "(IZ)V", (void *) gattClientScanNative},
1291 {"gattClientConnectNative", "(ILjava/lang/String;Z)V", (void *) gattClientConnectNative},
1292 {"gattClientDisconnectNative", "(ILjava/lang/String;I)V", (void *) gattClientDisconnectNative},
1293 {"gattClientRefreshNative", "(ILjava/lang/String;)V", (void *) gattClientRefreshNative},
1294 {"gattClientSearchServiceNative", "(IZJJ)V", (void *) gattClientSearchServiceNative},
1295 {"gattClientGetCharacteristicNative", "(IIIJJIJJ)V", (void *) gattClientGetCharacteristicNative},
1296 {"gattClientGetDescriptorNative", "(IIIJJIJJIJJ)V", (void *) gattClientGetDescriptorNative},
1297 {"gattClientGetIncludedServiceNative", "(IIIJJIIJJ)V", (void *) gattClientGetIncludedServiceNative},
1298 {"gattClientReadCharacteristicNative", "(IIIJJIJJI)V", (void *) gattClientReadCharacteristicNative},
1299 {"gattClientReadDescriptorNative", "(IIIJJIJJIJJI)V", (void *) gattClientReadDescriptorNative},
1300 {"gattClientWriteCharacteristicNative", "(IIIJJIJJII[B)V", (void *) gattClientWriteCharacteristicNative},
1301 {"gattClientWriteDescriptorNative", "(IIIJJIJJIJJII[B)V", (void *) gattClientWriteDescriptorNative},
1302 {"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative},
1303 {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative},
1304 {"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative},
1305 {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative},
1306
1307 {"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative},
1308 {"gattServerUnregisterAppNative", "(I)V", (void *) gattServerUnregisterAppNative},
1309 {"gattServerConnectNative", "(ILjava/lang/String;Z)V", (void *) gattServerConnectNative},
1310 {"gattServerDisconnectNative", "(ILjava/lang/String;I)V", (void *) gattServerDisconnectNative},
1311 {"gattServerAddServiceNative", "(IIIJJI)V", (void *) gattServerAddServiceNative},
1312 {"gattServerAddIncludedServiceNative", "(III)V", (void *) gattServerAddIncludedServiceNative},
1313 {"gattServerAddCharacteristicNative", "(IIJJII)V", (void *) gattServerAddCharacteristicNative},
1314 {"gattServerAddDescriptorNative", "(IIJJI)V", (void *) gattServerAddDescriptorNative},
1315 {"gattServerStartServiceNative", "(III)V", (void *) gattServerStartServiceNative},
1316 {"gattServerStopServiceNative", "(II)V", (void *) gattServerStopServiceNative},
1317 {"gattServerDeleteServiceNative", "(II)V", (void *) gattServerDeleteServiceNative},
1318 {"gattServerSendIndicationNative", "(III[B)V", (void *) gattServerSendIndicationNative},
1319 {"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative},
1320 {"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative},
1321
1322 {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative},
1323 {"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative},
1324 };
1325
register_com_android_bluetooth_gatt(JNIEnv * env)1326 int register_com_android_bluetooth_gatt(JNIEnv* env)
1327 {
1328 return jniRegisterNativeMethods(env, "com/android/bluetooth/gatt/GattService",
1329 sMethods, NELEM(sMethods));
1330 }
1331
1332 }
1333