static void cmd_status(int argcp, char **argvp) { resp_begin(rsp_STATUS); switch(conn_state) { case STATE_CONNECTING: send_sym(tag_CONNSTATE, st_CONNECTING); send_str(tag_DEVICE, opt_dst); break; case STATE_CONNECTED: send_sym(tag_CONNSTATE, st_CONNECTED); send_str(tag_DEVICE, opt_dst); break; case STATE_SCANNING: send_sym(tag_CONNSTATE, st_SCANNING); send_str(tag_DEVICE, opt_dst); break; case STATE_ADVERTISING: send_sym(tag_CONNSTATE, st_ADVERTISING); send_str(tag_DEVICE, opt_dst); break; default: send_sym(tag_CONNSTATE, st_DISCONNECTED); break; } send_uint(tag_MTU, opt_mtu); send_str(tag_SEC_LEVEL, opt_sec_level); resp_end(); }
static void resp_mgmt_with_data(unsigned int data) { resp_begin(rsp_MGMT); send_sym(tag_ERRCODE, err_SUCCESS); send_uint(tag_DATA, data); resp_end(); }
static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) { uint8_t *opdu; uint8_t evt; uint16_t handle, i, olen; size_t plen; evt = pdu[0]; if ( evt != ATT_OP_HANDLE_NOTIFY && evt != ATT_OP_HANDLE_IND ) { printf("#Invalid opcode %02X in event handler??\n", evt); return; } assert( len >= 3 ); handle = att_get_u16(&pdu[1]); resp_begin( evt==ATT_OP_HANDLE_NOTIFY ? rsp_NOTIFY : rsp_IND ); send_uint( tag_HANDLE, handle ); send_data( pdu+3, len-3 ); resp_end(); if (evt == ATT_OP_HANDLE_NOTIFY) return; opdu = g_attrib_get_buffer(attrib, &plen); olen = enc_confirmation(opdu, plen); if (olen > 0) g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL); }
static void primary_by_uuid_cb(uint8_t status, GSList *ranges, void *user_data) { GSList *l; if (status) { resp_error_comm(status); return; } resp_begin(rsp_DISCOVERY); for (l = ranges; l; l = l->next) { struct att_range *range = l->data; send_uint(tag_RANGE_START, range->start); send_uint(tag_RANGE_END, range->end); } resp_end(); }
static void resp_error_comm(unsigned int bt_err) { resp_begin(rsp_ERROR); send_sym(tag_ERRCODE, err_COMM_ERR); // BT error code (BT spec Vol2 PartD) or 0 if NA send_uint(tag_BT_ERR, bt_err); resp_end(); }
static void primary_by_uuid_cb(GSList *ranges, guint8 status, gpointer user_data) { GSList *l; if (status) { resp_error(err_COMM_ERR); // Todo: status return; } resp_begin(rsp_DISCOVERY); for (l = ranges; l; l = l->next) { struct att_range *range = l->data; send_uint(tag_RANGE_START, range->start); send_uint(tag_RANGE_END, range->end); } resp_end(); }
static void included_cb(uint8_t status, GSList *includes, void *user_data) { GSList *l; if (status) { resp_error_comm(status); return; } resp_begin(rsp_DISCOVERY); for (l = includes; l; l = l->next) { struct gatt_included *incl = l->data; send_uint(tag_HANDLE, incl->handle); send_uint(tag_RANGE_START, incl->range.start); send_uint(tag_RANGE_END, incl->range.end); send_str(tag_UUID, incl->uuid); } resp_end(); }
static void primary_all_cb(uint8_t status, GSList *services, void *user_data) { GSList *l; if (status) { resp_error_comm(status); return; } resp_begin(rsp_DISCOVERY); for (l = services; l; l = l->next) { struct gatt_primary *prim = l->data; send_uint(tag_RANGE_START, prim->range.start); send_uint(tag_RANGE_END, prim->range.end); send_str(tag_UUID, prim->uuid); } resp_end(); }
static void char_cb(uint8_t status, GSList *characteristics, void *user_data) { GSList *l; if (status) { resp_error_comm(status); return; } resp_begin(rsp_DISCOVERY); for (l = characteristics; l; l = l->next) { struct gatt_char *chars = l->data; send_uint(tag_HANDLE, chars->handle); send_uint(tag_PROPERTIES, chars->properties); send_uint(tag_VALUE_HANDLE, chars->value_handle); send_str(tag_UUID, chars->uuid); } resp_end(); }
static void mgmt_device_found(uint16_t index, uint16_t length, const void *param, void *user_data) { const struct mgmt_ev_device_found *ev = param; assert(length == sizeof(*ev) + ev->eir_len); assert(index == opt_src_idx); // Result sometimes sent too early if (conn_state != STATE_SCANNING) return; resp_begin(rsp_SCAN); send_addr(&ev->addr); send_uint(tag_RSSI, -ev->rssi); send_uint(tag_FLAG, -ev->flags); if (ev->eir_len) send_data(ev->eir, ev->eir_len); resp_end(); }
static void char_cb(GSList *characteristics, guint8 status, gpointer user_data) { GSList *l; if (status) { resp_error(err_COMM_ERR); // Todo: status return; } resp_begin(rsp_DISCOVERY); for (l = characteristics; l; l = l->next) { struct gatt_char *chars = l->data; send_uint(tag_HANDLE, chars->handle); send_uint(tag_PROPERTIES, chars->properties); send_uint(tag_VALUE_HANDLE, chars->value_handle); send_str(tag_UUID, chars->uuid); } resp_end(); }
static void included_cb(GSList *includes, guint8 status, gpointer user_data) { GSList *l; if (status) { resp_error(err_COMM_ERR); // Todo: status return; } resp_begin(rsp_DISCOVERY); for (l = includes; l; l = l->next) { struct gatt_included *incl = l->data; send_uint(tag_HANDLE, incl->handle); send_uint(tag_RANGE_START, incl->range.start); send_uint(tag_RANGE_END, incl->range.end); send_str(tag_UUID, incl->uuid); } resp_end(); }
static void primary_all_cb(GSList *services, guint8 status, gpointer user_data) { GSList *l; if (status) { resp_error(err_COMM_ERR); // Todo: status return; } resp_begin(rsp_DISCOVERY); for (l = services; l; l = l->next) { struct gatt_primary *prim = l->data; send_uint(tag_RANGE_START, prim->range.start); send_uint(tag_RANGE_END, prim->range.end); send_str(tag_UUID, prim->uuid); } resp_end(); }
static void send_addr(const struct mgmt_addr_info *addr) { const uint8_t *val = addr->bdaddr.b; printf(" %s=b", tag_ADDR); int len = 6; /* Human-readable byte order is reverse of bdaddr.b */ while ( len-- > 0 ) printf("%02X", val[len]); send_uint(tag_TYPE, addr->type); }
static void char_desc_cb(uint8_t status, GSList *descriptors, void *user_data) { GSList *l; if (status != 0) { resp_error_comm(status); return; } resp_begin(rsp_DESCRIPTORS); for (l = descriptors; l != NULL; l = l->next) { struct gatt_desc *desc = (struct gatt_desc *)l->data; send_uint(tag_HANDLE, desc->handle); send_str (tag_UUID, desc->uuid); } resp_end(); }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; uint16_t handle = 0xffff; int i; if (status != 0) { resp_error(err_COMM_ERR); // Todo: status return; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) { resp_error(err_NOT_FOUND); // Todo: what does this mean? return; } resp_begin(rsp_DESCRIPTORS); for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = att_get_u16(value); if (format == 0x01) uuid = att_get_uuid16(&value[2]); else uuid = att_get_uuid128(&value[2]); bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); send_uint(tag_HANDLE, handle); send_str (tag_UUID, uuidstr); } resp_end(); att_data_list_free(list); if (handle != 0xffff && handle < end) gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb, NULL); }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct characteristic_data *char_data = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND && char_data->start != char_data->orig_start) { printf("# TODO case in char_read_by_uuid_cb\n"); goto done; } if (status != 0) { resp_error(err_COMM_ERR); // Todo: status goto done; } list = dec_read_by_type_resp(pdu, plen); resp_begin(rsp_READ); if (list == NULL) goto nolist; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; char_data->start = att_get_u16(value) + 1; send_uint(tag_HANDLE, att_get_u16(value)); send_data(value+2, list->len-2); // All the same length?? } att_data_list_free(list); nolist: resp_end(); done: g_free(char_data); }