void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { char buf[BLE_UUID_STR_LEN]; switch (ctxt->op) { case BLE_GATT_REGISTER_OP_SVC: BLEPRPH_LOG(DEBUG, "registered service %s with handle=%d\n", ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), ctxt->svc.handle); break; case BLE_GATT_REGISTER_OP_CHR: BLEPRPH_LOG(DEBUG, "registering characteristic %s with " "def_handle=%d val_handle=%d\n", ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), ctxt->chr.def_handle, ctxt->chr.val_handle); break; case BLE_GATT_REGISTER_OP_DSC: BLEPRPH_LOG(DEBUG, "registering descriptor %s with handle=%d\n", ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), ctxt->dsc.handle); break; default: assert(0); break; } }
/** * Enables advertising with the following parameters: * o General discoverable mode. * o Undirected connectable mode. */ static void sensor_oic_advertise(void) { struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; const char *name; int rc; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset(&fields, 0, sizeof fields); /* Advertise two flags: * o Discoverability in forthcoming advertisement (general) * o BLE-only (BR/EDR unsupported). */ fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; /* Indicate that the TX power level field should be included; have the * stack fill this value automatically. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields.tx_pwr_lvl_is_present = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; name = ble_svc_gap_device_name(); fields.name = (uint8_t *)name; fields.name_len = strlen(name); fields.name_is_complete = 1; fields.uuids128 = (ble_uuid128_t []) { BLE_UUID128_INIT(OC_GATT_UNSEC_SVC_UUID) }; fields.num_uuids128 = 1; fields.uuids128_is_complete = 1; rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { BLEPRPH_LOG(ERROR, "error setting advertisement data; rc=%d\n", rc); return; } /* Begin advertising. */ memset(&adv_params, 0, sizeof adv_params); adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, sensor_oic_gap_event, NULL); if (rc != 0) { BLEPRPH_LOG(ERROR, "error enabling advertisement; rc=%d\n", rc); return; } }
/** * Logs information about a connection to the console. */ static void bleprph_print_conn_desc(struct ble_gap_conn_desc *desc) { BLEPRPH_LOG(INFO, "handle=%d peer_addr_type=%d peer_addr=", desc->conn_handle, desc->peer_addr_type); bleprph_print_bytes(desc->peer_addr, 6); BLEPRPH_LOG(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d " "encrypted=%d authenticated=%d", desc->conn_itvl, desc->conn_latency, desc->supervision_timeout, desc->sec_state.enc_enabled, desc->sec_state.authenticated); }
/** * Utility function to log an array of bytes. */ static void bleprph_print_bytes(uint8_t *bytes, int len) { int i; for (i = 0; i < len; i++) { BLEPRPH_LOG(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); } }
/** * Enables advertising with the following parameters: * o General discoverable mode. * o Undirected connectable mode. */ static void bleprph_advertise(void) { struct ble_hs_adv_fields fields; int rc; /** * Set the advertisement data included in our advertisements: * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset(&fields, 0, sizeof fields); fields.tx_pwr_lvl_is_present = 1; fields.name = (uint8_t *)bleprph_device_name; fields.name_len = strlen(bleprph_device_name); fields.name_is_complete = 1; fields.uuids16 = (uint16_t[]){ GATT_SVR_SVC_ALERT_UUID }; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { BLEPRPH_LOG(ERROR, "error setting advertisement data; rc=%d\n", rc); return; } /* Begin advertising. */ rc = ble_gap_adv_start(BLE_GAP_DISC_MODE_GEN, BLE_GAP_CONN_MODE_UND, NULL, 0, NULL, bleprph_gap_event, NULL); if (rc != 0) { BLEPRPH_LOG(ERROR, "error enabling advertisement; rc=%d\n", rc); return; } }
/** * Logs information about a connection to the console. */ static void sensor_oic_print_conn_desc(struct ble_gap_conn_desc *desc) { BLEPRPH_LOG(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=", desc->conn_handle, desc->our_ota_addr.type); print_addr(desc->our_ota_addr.val); BLEPRPH_LOG(INFO, " our_id_addr_type=%d our_id_addr=", desc->our_id_addr.type); print_addr(desc->our_id_addr.val); BLEPRPH_LOG(INFO, " peer_ota_addr_type=%d peer_ota_addr=", desc->peer_ota_addr.type); print_addr(desc->peer_ota_addr.val); BLEPRPH_LOG(INFO, " peer_id_addr_type=%d peer_id_addr=", desc->peer_id_addr.type); print_addr(desc->peer_id_addr.val); BLEPRPH_LOG(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d " "encrypted=%d authenticated=%d bonded=%d\n", desc->conn_itvl, desc->conn_latency, desc->supervision_timeout, desc->sec_state.encrypted, desc->sec_state.authenticated, desc->sec_state.bonded); }
/** * The nimble host executes this callback when a GAP event occurs. The * application associates a GAP event callback with each connection that forms. * bleprph uses the same callback for all connections. * * @param event The type of event being signalled. * @param status The error code associated with the event * (0 = success). * @param ctxt Various information pertaining to the event. * @param arg Application-specified argument; unuesd by * bleprph. * * @return 0 if the application successfully handled the * event; nonzero on failure. The semantics * of the return code is specific to the * particular GAP event being signalled. */ static int bleprph_gap_event(int event, int status, struct ble_gap_conn_ctxt *ctxt, void *arg) { int authenticated; int rc; switch (event) { case BLE_GAP_EVENT_CONN: /* A new connection has been established or an existing one has been * terminated. */ BLEPRPH_LOG(INFO, "connection %s; status=%d ", status == 0 ? "up" : "down", status); bleprph_print_conn_desc(ctxt->desc); BLEPRPH_LOG(INFO, "\n"); if (status != 0) { /* Connection terminated; resume advertising. */ bleprph_advertise(); } return 0; case BLE_GAP_EVENT_CONN_UPDATED: /* The central has updated the connection parameters. */ BLEPRPH_LOG(INFO, "connection updated; status=%d ", status); bleprph_print_conn_desc(ctxt->desc); BLEPRPH_LOG(INFO, "\n"); return 0; case BLE_GAP_EVENT_LTK_REQUEST: /* An encryption procedure (bonding) is being attempted. The nimble * stack is asking us to look in our key database for a long-term key * corresponding to the specified ediv and random number. */ BLEPRPH_LOG(INFO, "looking up ltk with ediv=0x%02x rand=0x%llx\n", ctxt->ltk_params->ediv, ctxt->ltk_params->rand_num); /* Perform a key lookup and populate the context object with the * result. The nimble stack will use this key if this function returns * success. */ rc = keystore_lookup(ctxt->ltk_params->ediv, ctxt->ltk_params->rand_num, ctxt->ltk_params->ltk, &authenticated); if (rc == 0) { ctxt->ltk_params->authenticated = authenticated; BLEPRPH_LOG(INFO, "ltk="); bleprph_print_bytes(ctxt->ltk_params->ltk, sizeof ctxt->ltk_params->ltk); BLEPRPH_LOG(INFO, " authenticated=%d\n", authenticated); } else { BLEPRPH_LOG(INFO, "no matching ltk\n"); } /* Indicate whether we were able to find an appropriate key. */ return rc; case BLE_GAP_EVENT_KEY_EXCHANGE: /* The central is sending us key information or vice-versa. If the * central is doing the sending, save the long-term key in the in-RAM * database. This permits bonding to occur on subsequent connections * with this peer (as long as bleprph isn't restarted!). */ if (ctxt->key_params->is_ours && ctxt->key_params->ltk_valid && ctxt->key_params->ediv_rand_valid) { rc = keystore_add(ctxt->key_params->ediv, ctxt->key_params->rand_val, ctxt->key_params->ltk, ctxt->desc->sec_state.authenticated); if (rc != 0) { BLEPRPH_LOG(INFO, "error persisting LTK; status=%d\n", rc); } } return 0; case BLE_GAP_EVENT_SECURITY: /* Encryption has been enabled or disabled for this connection. */ BLEPRPH_LOG(INFO, "security event; status=%d ", status); bleprph_print_conn_desc(ctxt->desc); BLEPRPH_LOG(INFO, "\n"); return 0; } return 0; }
/** * The nimble host executes this callback when a GAP event occurs. The * application associates a GAP event callback with each connection that forms. * sensor_oic uses the same callback for all connections. * * @param event The type of event being signalled. * @param ctxt Various information pertaining to the event. * @param arg Application-specified argument; unuesd by * sensor_oic. * * @return 0 if the application successfully handled the * event; nonzero on failure. The semantics * of the return code is specific to the * particular GAP event being signalled. */ static int sensor_oic_gap_event(struct ble_gap_event *event, void *arg) { struct ble_gap_conn_desc desc; int rc; switch (event->type) { case BLE_GAP_EVENT_CONNECT: /* A new connection was established or a connection attempt failed. */ BLEPRPH_LOG(INFO, "connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed", event->connect.status); if (event->connect.status == 0) { rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); sensor_oic_print_conn_desc(&desc); } BLEPRPH_LOG(INFO, "\n"); if (event->connect.status != 0) { /* Connection failed; resume advertising. */ sensor_oic_advertise(); } else { oc_ble_coap_conn_new(event->connect.conn_handle); } return 0; case BLE_GAP_EVENT_DISCONNECT: BLEPRPH_LOG(INFO, "disconnect; reason=%d ", event->disconnect.reason); sensor_oic_print_conn_desc(&event->disconnect.conn); BLEPRPH_LOG(INFO, "\n"); oc_ble_coap_conn_del(event->disconnect.conn.conn_handle); /* Connection terminated; resume advertising. */ sensor_oic_advertise(); return 0; case BLE_GAP_EVENT_CONN_UPDATE: /* The central has updated the connection parameters. */ BLEPRPH_LOG(INFO, "connection updated; status=%d ", event->conn_update.status); rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); sensor_oic_print_conn_desc(&desc); BLEPRPH_LOG(INFO, "\n"); return 0; case BLE_GAP_EVENT_DISC_COMPLETE: BLEPRPH_LOG(INFO, "discovery complete; reason=%d\n", event->disc_complete.reason); return 0; case BLE_GAP_EVENT_ADV_COMPLETE: BLEPRPH_LOG(INFO, "advertise complete; reason=%d\n", event->adv_complete.reason); sensor_oic_advertise(); return 0; case BLE_GAP_EVENT_ENC_CHANGE: /* Encryption has been enabled or disabled for this connection. */ BLEPRPH_LOG(INFO, "encryption change event; status=%d ", event->enc_change.status); rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); sensor_oic_print_conn_desc(&desc); BLEPRPH_LOG(INFO, "\n"); return 0; case BLE_GAP_EVENT_SUBSCRIBE: BLEPRPH_LOG(INFO, "subscribe event; conn_handle=%d attr_handle=%d " "reason=%d prevn=%d curn=%d previ=%d curi=%d\n", event->subscribe.conn_handle, event->subscribe.attr_handle, event->subscribe.reason, event->subscribe.prev_notify, event->subscribe.cur_notify, event->subscribe.prev_indicate, event->subscribe.cur_indicate); return 0; case BLE_GAP_EVENT_MTU: BLEPRPH_LOG(INFO, "mtu update event; conn_handle=%d cid=%d mtu=%d\n", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); return 0; } return 0; }
static void sensor_oic_on_reset(int reason) { BLEPRPH_LOG(ERROR, "Resetting state; reason=%d\n", reason); }