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