aboutsummaryrefslogtreecommitdiffstats
path: root/ble.c
diff options
context:
space:
mode:
Diffstat (limited to 'ble.c')
-rw-r--r--ble.c416
1 files changed, 319 insertions, 97 deletions
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;
+}