From 68041c4710fc044c13f4107a74ae26badf611fd8 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 1 Sep 2015 11:42:26 +0100 Subject: works --- ble.c | 416 ++++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 319 insertions(+), 97 deletions(-) (limited to 'ble.c') diff --git a/ble.c b/ble.c index 6e16adf..8e8c6c8 100644 --- a/ble.c +++ b/ble.c @@ -1,13 +1,61 @@ #include "project.h" +#include "dfu.h" #include "bluez/gatt-client.h" #include "bluez/mainloop.h" -static int verbose = 1; +static int verbose = 0; #define ATT_CID 4 -static bt_uuid_t fota_uuid,cp_uuid,data_uuid,cccd_uuid; +static bt_uuid_t fota_uuid, cp_uuid, data_uuid, cccd_uuid; + + +static const char * +ecode_to_string (uint8_t ecode) +{ + switch (ecode) + { + case BT_ATT_ERROR_INVALID_HANDLE: + return "Invalid Handle"; + case BT_ATT_ERROR_READ_NOT_PERMITTED: + return "Read Not Permitted"; + case BT_ATT_ERROR_WRITE_NOT_PERMITTED: + return "Write Not Permitted"; + case BT_ATT_ERROR_INVALID_PDU: + return "Invalid PDU"; + case BT_ATT_ERROR_AUTHENTICATION: + return "Authentication Required"; + case BT_ATT_ERROR_REQUEST_NOT_SUPPORTED: + return "Request Not Supported"; + case BT_ATT_ERROR_INVALID_OFFSET: + return "Invalid Offset"; + case BT_ATT_ERROR_AUTHORIZATION: + return "Authorization Required"; + case BT_ATT_ERROR_PREPARE_QUEUE_FULL: + return "Prepare Write Queue Full"; + case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND: + return "Attribute Not Found"; + case BT_ATT_ERROR_ATTRIBUTE_NOT_LONG: + return "Attribute Not Long"; + case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE: + return "Insuficient Encryption Key Size"; + case BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN: + return "Invalid Attribute value len"; + case BT_ATT_ERROR_UNLIKELY: + return "Unlikely Error"; + case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION: + return "Insufficient Encryption"; + case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE: + return "Group type Not Supported"; + case BT_ATT_ERROR_INSUFFICIENT_RESOURCES: + return "Insufficient Resources"; + default: + return "Unknown error type"; + } +} + + @@ -133,20 +181,21 @@ l2cap_le_att_connect (bdaddr_t * src, bdaddr_t * dst, uint8_t dst_type, void -ble_close (BLE *ble) +ble_close (BLE * ble) { if (!ble) return; + mainloop_finish (); if (ble->notify_id) - bt_gatt_client_unregister_notify(ble->gatt, ble->notify_id); + bt_gatt_client_unregister_notify (ble->gatt, ble->notify_id); if (ble->gatt) - bt_gatt_client_unref(ble->gatt); + bt_gatt_client_unref (ble->gatt); - if (ble->db) - gatt_db_unref(ble->db); + if (ble->db) + gatt_db_unref (ble->db); if (ble->att) bt_att_unref (ble->att); @@ -155,6 +204,7 @@ ble_close (BLE *ble) free (ble); + } @@ -166,81 +216,84 @@ att_disconnect_cb (int err, void *user_data) mainloop_exit_failure (); } -static void print_uuid(const bt_uuid_t *uuid) +static void +print_uuid (const bt_uuid_t * uuid) { - char uuid_str[MAX_LEN_UUID_STR]; - bt_uuid_t uuid128; + char uuid_str[MAX_LEN_UUID_STR]; + bt_uuid_t uuid128; - bt_uuid_to_uuid128(uuid, &uuid128); - bt_uuid_to_string(&uuid128, uuid_str, sizeof(uuid_str)); + bt_uuid_to_uuid128 (uuid, &uuid128); + bt_uuid_to_string (&uuid128, uuid_str, sizeof (uuid_str)); - printf("%s\n", uuid_str); + printf ("%s\n", uuid_str); } -static void scan_desc(struct gatt_db_attribute *attr, void *user_data) +static void +scan_desc (struct gatt_db_attribute *attr, void *user_data) { -BLE *ble=user_data; -uint16_t handle=gatt_db_attribute_get_handle(attr); -const bt_uuid_t *uuid=gatt_db_attribute_get_type(attr); + BLE *ble = user_data; + uint16_t handle = gatt_db_attribute_get_handle (attr); + const bt_uuid_t *uuid = gatt_db_attribute_get_type (attr); - printf("\t\tdesc - handle: 0x%04x, uuid: ",handle); - print_uuid(uuid); + printf ("\t\tdesc - handle: 0x%04x, uuid: ", handle); + print_uuid (uuid); - if (!bt_uuid_cmp(uuid,&cccd_uuid)) - ble->cccd_handle=handle; + if (!bt_uuid_cmp (uuid, &cccd_uuid)) + ble->cccd_handle = handle; } -static void scan_chrc(struct gatt_db_attribute *attr, void *user_data) +static void +scan_chrc (struct gatt_db_attribute *attr, void *user_data) { - BLE *ble=user_data; - uint16_t handle, value_handle; - uint8_t properties; - bt_uuid_t uuid; + BLE *ble = user_data; + uint16_t handle, value_handle; + uint8_t properties; + bt_uuid_t uuid; - if (!gatt_db_attribute_get_char_data(attr, &handle, - &value_handle, - &properties, - &uuid)) - return; + if (!gatt_db_attribute_get_char_data (attr, &handle, + &value_handle, &properties, &uuid)) + return; - printf("\tchar - start: 0x%04x, value: 0x%04x, props: 0x%02x, uuid: ", - handle, value_handle, properties); + printf ("\tchar - start: 0x%04x, value: 0x%04x, props: 0x%02x, uuid: ", + handle, value_handle, properties); - print_uuid(&uuid); + print_uuid (&uuid); - if (!bt_uuid_cmp(&uuid,&data_uuid)) - ble->data_handle=value_handle; + if (!bt_uuid_cmp (&uuid, &data_uuid)) + ble->data_handle = value_handle; - if (!bt_uuid_cmp(&uuid,&cp_uuid)) { - ble->cp_handle=value_handle; - gatt_db_service_foreach_desc(attr, scan_desc, ble); - } + if (!bt_uuid_cmp (&uuid, &cp_uuid)) + { + ble->cp_handle = value_handle; + gatt_db_service_foreach_desc (attr, scan_desc, ble); + } } -static void scan_service(struct gatt_db_attribute *attr, void *user_data) +static void +scan_service (struct gatt_db_attribute *attr, void *user_data) { - BLE *ble = user_data; - uint16_t start, end; - bool primary; - bt_uuid_t uuid; + BLE *ble = user_data; + uint16_t start, end; + bool primary; + bt_uuid_t uuid; - if (!gatt_db_attribute_get_service_data(attr, &start, &end, &primary, - &uuid)) - return; + if (!gatt_db_attribute_get_service_data (attr, &start, &end, &primary, + &uuid)) + return; - gatt_db_service_foreach_char(attr, scan_chrc, ble); + gatt_db_service_foreach_char (attr, scan_chrc, ble); - printf("\n"); + printf ("\n"); } @@ -261,27 +314,29 @@ ready_cb (bool success, uint8_t att_ecode, void *user_data) printf ("GATT discovery procedures complete\n"); - gatt_db_foreach_service(ble->db, &fota_uuid, scan_service, ble); + gatt_db_foreach_service (ble->db, &fota_uuid, scan_service, ble); + + printf ("Handles:\n\tdata: 0x%04x\n\tcp : 0x%04x\n\tcccd: 0x%04x\n", + ble->data_handle, ble->cp_handle, ble->cccd_handle); - printf("Handles:\n\tdata: 0x%04x\n\tcp : 0x%04x\n\tcccd: 0x%04x\n", - ble->data_handle,ble->cp_handle,ble->cccd_handle); + if (ble->cccd_handle && ble->cp_handle && ble->data_handle) + { + mainloop_exit_success (); + return; + } - if (ble->cccd_handle && ble->cp_handle && ble->data_handle) { - mainloop_exit_success (); - return; - } - - mainloop_exit_failure(); + mainloop_exit_failure (); } -void ble_init(void) +void +ble_init (void) { - bt_string_to_uuid(&fota_uuid, "00001530-1212-efde-1523-785feabcd123"); - bt_string_to_uuid(&cp_uuid, "00001531-1212-efde-1523-785feabcd123"); - bt_string_to_uuid(&data_uuid, "00001532-1212-efde-1523-785feabcd123"); - bt_string_to_uuid(&cccd_uuid, "00002902-0000-1000-8000-00805f9b34fb"); + bt_string_to_uuid (&fota_uuid, "00001530-1212-efde-1523-785feabcd123"); + bt_string_to_uuid (&cp_uuid, "00001531-1212-efde-1523-785feabcd123"); + bt_string_to_uuid (&data_uuid, "00001532-1212-efde-1523-785feabcd123"); + bt_string_to_uuid (&cccd_uuid, "00002902-0000-1000-8000-00805f9b34fb"); mainloop_init (); } @@ -294,6 +349,9 @@ ble_open (const char *bdaddr) ble = xmalloc (sizeof (*ble)); memset (ble, 0, sizeof (*ble)); + ble->notify_waiting_for_op = -1; + ble->notify_code = -1; + ble->sec = BT_SECURITY_LOW; ble->dst_type = BDADDR_LE_RANDOM; bacpy (&ble->src_addr, BDADDR_ANY); @@ -364,59 +422,223 @@ ble_open (const char *bdaddr) return NULL; } -static void notify_cb(uint16_t value_handle, const uint8_t *value, - uint16_t length, void *user_data) +static void +notify_cb (uint16_t value_handle, const uint8_t * value, + uint16_t length, void *user_data) { - int i; + int i; + BLE *ble = user_data; - printf("Handle Value Not/Ind: 0x%04x - ", value_handle); + printf ("Handle Value Not/Ind: 0x%04x - ", value_handle); - if (length == 0) { - printf("(0 bytes)\n"); - return; - } + if (length == 0) + { + printf ("(0 bytes)\n"); + return; + } + + printf ("(%u bytes): ", length); + + for (i = 0; i < length; i++) + printf ("%02x ", value[i]); + + printf ("\n"); + + if (value_handle != ble->cp_handle) + return; + if (length != 3) + return; + + if (value[0] != OP_CODE_RESPONSE) + return; + + if (value[1] != ble->notify_waiting_for_op) + return; - printf("(%u bytes): ", length); + ble->notify_code = value[2]; - for (i = 0; i < length; i++) - printf("%02x ", value[i]); + printf ("Got response => 0x%02x\n", value[2]); + mainloop_quit (); - printf("\n"); } -static void register_notify_cb(uint16_t att_ecode, void *user_data) +static void +register_notify_cb (uint16_t att_ecode, void *user_data) { - if (att_ecode) { - printf("Failed to register notify handler " - "- error code: 0x%02x\n", att_ecode); - mainloop_exit_failure(); - return; - } + if (att_ecode) + { + printf ("Failed to register notify handler " + "- error code: 0x%02x\n", att_ecode); + mainloop_exit_failure (); + return; + } + + printf ("Registered notify handler!\n"); + mainloop_exit_success (); +} + + +int +ble_register_notify (BLE * ble) +{ + + + + if (!bt_gatt_client_is_ready (ble->gatt)) + { + printf ("GATT client not initialized\n"); + return EXIT_FAILURE; + } + + ble->notify_id = bt_gatt_client_register_notify (ble->gatt, ble->cp_handle, + register_notify_cb, + notify_cb, ble, NULL); + if (!ble->notify_id) + { + printf ("Failed to register notify handler\n"); + return EXIT_FAILURE; + } + + printf ("requesting notify\n"); + + return mainloop_run (); +} + +static void +write_cb (bool success, uint8_t att_ecode, void *user_data) +{ +//BLE *ble=user_data; + + if (success) + { + mainloop_exit_success (); + } + else + { + printf ("Write failed: %s (0x%02x)\n", + ecode_to_string (att_ecode), att_ecode); + mainloop_exit_failure (); + } +} + + +int +ble_send_cp (BLE * ble, uint8_t * buf, size_t len) +{ + printf ("Sending control:\n"); + hexdump (buf, len); - printf("Registered notify handler!\n"); - mainloop_exit_success(); + if (!bt_gatt_client_write_value (ble->gatt, ble->cp_handle, buf, len, + write_cb, ble, NULL)) + { + printf ("Failed to initiate write procedure\n"); + return EXIT_FAILURE; + } + + return mainloop_run (); } -int ble_register_notify(BLE *ble) { +#if 0 +int +ble_send_data (BLE * ble, uint8_t * buf, size_t len) +{ + size_t mtu = 16, tx; + + printf ("Sending data:\n"); + + + hexdump (buf, (len < 64) ? len : 64); + + while (len) + { + + printf ("%u bytes left\n", (unsigned) len); + tx = (len > mtu) ? mtu : len; - if (!bt_gatt_client_is_ready(ble->gatt)) { - printf("GATT client not initialized\n"); - return EXIT_FAILURE; + if (!bt_gatt_client_write_value (ble->gatt, ble->data_handle, buf, tx, + write_cb, ble, NULL)) + { + printf ("Failed to initiate write procedure\n"); + return EXIT_FAILURE; } - ble->notify_id = bt_gatt_client_register_notify(ble->gatt, ble->cp_handle, - register_notify_cb, - notify_cb, NULL, NULL); - if (!ble->notify_id) { - printf("Failed to register notify handler\n"); - return EXIT_FAILURE; + if (mainloop_run () == EXIT_FAILURE) + return EXIT_FAILURE; + + len -= tx; + buf += tx; + } + + return EXIT_SUCCESS; +} +#else +int +ble_send_data (BLE * ble, uint8_t * buf, size_t len) +{ + if (!bt_gatt_client_write_value (ble->gatt, ble->data_handle, buf, len, + write_cb, ble, NULL)) + { + printf ("Failed to initiate write procedure\n"); + return EXIT_FAILURE; + } + + return mainloop_run (); +} +#endif + + +int +ble_send_data_noresp (BLE * ble, uint8_t * buf, size_t len) +{ + size_t mtu = 16, tx; + + printf ("Sending data:\n"); + + + hexdump (buf, (len < 64) ? len : 64); + + + while (len) + { + + printf ("%u bytes left\n", (unsigned) len); + + tx = (len > mtu) ? mtu : len; + + if (!bt_gatt_client_write_without_response + (ble->gatt, ble->data_handle, false, buf, tx)) + { + printf ("Failed to initiate write procedure\n"); + return EXIT_FAILURE; } - printf("requesting notify\n"); + len -= tx; + buf += tx; + } - return mainloop_run(); + return EXIT_SUCCESS; } + +void +ble_wait_setup (BLE * ble, uint8_t op) +{ + ble->notify_waiting_for_op = op; + ble->notify_code = -1; +} + + +int +ble_wait_run (BLE * ble) +{ + mainloop_run (); + + ble->notify_waiting_for_op = -1; + + printf ("Returning response 0x%02x\n", ble->notify_code); + + return ble->notify_code; +} -- cgit v1.2.3