void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) { app_gap_cb_t *p_dev = &m_dev_info; char bda_str[18]; char uuid_str[37]; switch (event) { case ESP_BT_GAP_DISC_RES_EVT: { update_device_info(param); break; } case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: { if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) { ESP_LOGI(GAP_TAG, "Device discovery stopped."); if ( (p_dev->state == APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE || p_dev->state == APP_GAP_STATE_DEVICE_DISCOVERING) && p_dev->dev_found) { p_dev->state = APP_GAP_STATE_SERVICE_DISCOVERING; ESP_LOGI(GAP_TAG, "Discover services ..."); esp_bt_gap_get_remote_services(p_dev->bda); } } else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) { ESP_LOGI(GAP_TAG, "Discovery started."); } break; } case ESP_BT_GAP_RMT_SRVCS_EVT: { if (memcmp(param->rmt_srvcs.bda, p_dev->bda, ESP_BD_ADDR_LEN) == 0 && p_dev->state == APP_GAP_STATE_SERVICE_DISCOVERING) { p_dev->state = APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE; if (param->rmt_srvcs.stat == ESP_BT_STATUS_SUCCESS) { ESP_LOGI(GAP_TAG, "Services for device %s found", bda2str(p_dev->bda, bda_str, 18)); for (int i = 0; i < param->rmt_srvcs.num_uuids; i++) { esp_bt_uuid_t *u = param->rmt_srvcs.uuid_list + i; ESP_LOGI(GAP_TAG, "--%s", uuid2str(u, uuid_str, 37)); // ESP_LOGI(GAP_TAG, "--%d", u->len); } } else { ESP_LOGI(GAP_TAG, "Services for device %s not found", bda2str(p_dev->bda, bda_str, 18)); } } break; } case ESP_BT_GAP_RMT_SRVC_REC_EVT: default: { ESP_LOGI(GAP_TAG, "event: %d", event); break; } } return; }
void btdev_cache_print(int state) { btdev_struct *entry; char buf[256], *name; int i; char ch; for (i = 0; (entry = s_list_nth_data(devcache.head, i)); i++) { if (!(entry->state & state)) continue; parse_cod(buf, entry->cod); if (entry->name[0] != '\0') name = entry->name; else name = "(none)"; switch (entry->state) { case DEVSTATE_RANGE: ch = '+'; break; case DEVSTATE_GONE: ch = '-'; break; case DEVSTATE_UNKNOWN: default: ch = ' '; } printf("%c%d: Address: %s, Class: 0x%06X, Key: \"%s\"", ch, i+1, bda2str(&entry->bda), entry->cod, (entry->flags & BTDEV_KEY)?"yes":"no"); printf(", Name: \"%s\"\n", name); printf(" %s\n", buf); } }
int __sdp_connect(char *target) { int status; struct sockaddr_affix sa; status = sdp_init(0); if (status < 0) return status; sa.family = PF_AFFIX; sa.devnum = hci_devnum(btdev);//HCIDEV_ANY; if (strcmp(target, "local") == 0) { printf("Opening local connection\n"); srvHandle = sdp_connect_local(); } else { status = btdev_get_bda(&sa.bda, target); if (status) { printf("Incorrect address given\n"); return -1; } printf("Connecting to host %s ...\n", bda2str(&sa.bda)); srvHandle = sdp_connect(&sa); } if (srvHandle < 0) return -1; return 0; }
int btdev_cache_save(void) { btdev_struct *entry; FILE *cfd; int i, k; if (devcache.lock == -1 && btdev_cache_lock() < 0) return -1; cfd = fopen(devcache.file, "w"); if (!cfd) { fprintf(stderr, "Unable to fopen cache file: %s\n", devcache.file); btdev_cache_unlock(); return -1; } fprintf(cfd, "<device-listing>\n"); for (i = 0; (entry = s_list_nth_data(devcache.head, i)); i++) { fprintf(cfd, "<device bda=\"%s\"", bda2str(&entry->bda)); if (entry->cod) fprintf(cfd, " class=\"%x\"", entry->cod); if (entry->name[0] != '\0') fprintf(cfd, " name=\"%s\"", entry->name); if (entry->flags & BTDEV_KEY) { fprintf(cfd, " key=\""); for (k = 0; k < 16; k++) fprintf(cfd, "%02x", entry->link_key[k]); fprintf(cfd, "\""); } fprintf(cfd, "/>\n"); } fprintf(cfd, "</device-listing>\n"); fclose(cfd); btdev_cache_unlock(); return 0; }
int cmd_pan_connect(struct command *cmd) { int err, role = AFFIX_PAN_NAP; BD_ADDR bda; struct sockaddr_affix saddr; __argv = &__argv[optind]; if (!*__argv) { printf("Address missing\n"); print_usage(cmd); return 1; } err = btdev_get_bda(&bda, *__argv); if (err) { printf("Incorrect address given\n"); return 1; } if (*(++__argv)) { /* role */ role = str2role(*__argv); if (!role) { fprintf(stderr, "invalid role: %s\n", *__argv); return 1; } } saddr.family = PF_AFFIX; saddr.bda = bda; saddr.devnum = HCIDEV_ANY; #if defined(CONFIG_AFFIX_SDP) if (sdpmode) { uint16_t ServiceID; uint16_t count; slist_t *searchList = NULL; slist_t *attrList = NULL; slist_t *svcList = NULL; sdpsvc_t *svcRec; if (role == AFFIX_PAN_NAP) ServiceID = SDP_UUID_NAP; else if (role == AFFIX_PAN_GN) ServiceID = SDP_UUID_GN; else ServiceID = SDP_UUID_PANU; printf("Connecting to host %s ...\n", bda2str(&bda)); /* search for service ServiceID */ s_list_append_uuid16(&searchList, ServiceID); /* set attributes to find */ s_list_append_uint(&attrList, SDP_ATTR_SERVICE_RECORD_HANDLE); s_list_append_uint(&attrList, SDP_ATTR_PROTO_DESC_LIST); err = __sdp_search_attr_req(&saddr, searchList, IndividualAttributes, attrList, 0xffff, &svcList, &count); s_list_destroy(&searchList); s_list_free(&attrList); if (err) { fprintf(stderr, "%s\n", sdp_error(err)); return -1; } if (count == 0) { printf("services [%s] not found\n", val2str(sdp_service_map, ServiceID)); return -1; } printf("Service found\n"); svcRec = s_list_dequeue(&svcList); sdp_free_svc(svcRec); sdp_free_svclist(&svcList); } #endif saddr.devnum = hci_devnum(btdev); err = affix_pan_connect(&saddr, role); if (err) { if (errno == EINVAL) fprintf(stderr, "Connection not allowed in this role.\n"); else fprintf(stderr, "failed.\n"); } else fprintf(stderr, "connected.\n"); return 0; }
int cmd_pan_discovery(struct command *cmd) { int role = AFFIX_PAN_NAP; int fd, i, found = 0; __u32 length = 8; int err; INQUIRY_ITEM devs[20]; char *devnames[20]; char name[248]; __u8 num; uint16_t ServiceID; uint16_t count; slist_t *searchList = NULL; slist_t *attrList = NULL; slist_t *svcList = NULL; sdpsvc_t *svcRec; struct sockaddr_affix saddr; __argv = &__argv[optind]; if (*__argv) { role = str2role(*__argv); if (!role) { fprintf(stderr, "invalid role: %s\n", *__argv); return 1; } if (*(++__argv)) sscanf(*__argv, "%x", &length); } fd = hci_open(btdev); if (fd < 0) { printf("Unable to open device %s: %s\n", btdev, strerror(errno)); return -1; } printf("Searching %d sec ...\n", length); err = HCI_Inquiry(fd, length, 20, devs, &num); if (err) { fprintf(stderr, "%s\n", hci_error(err)); exit(1); } if (num == 0) { printf("done.\nNo devices found.\n"); } else { printf("Searching done. Checking for service %s ...\n", role2str(role)); btdev_cache_reload(); btdev_cache_retire(); for (i = 0; i < num; i++) { if (!(devs[i].Class_of_Device & HCI_COD_NETWORKING)) continue; saddr.family = PF_AFFIX; saddr.bda = devs[i].bda; saddr.devnum = HCIDEV_ANY; printf("% 2d: %s ", ++found, bda2str(&saddr.bda)); devs[i].Clock_Offset |= 0x8000; err = HCI_RemoteNameRequest(fd, &devs[i], name); if (!err) devnames[i] = strdup(name); else devnames[i] = NULL; printf("(%s)... ", name); #if defined(CONFIG_AFFIX_SDP) if (role == AFFIX_PAN_NAP) ServiceID = SDP_UUID_NAP; else if (role == AFFIX_PAN_GN) ServiceID = SDP_UUID_GN; else ServiceID = SDP_UUID_PANU; /* search for service ServiceID */ s_list_append_uuid16(&searchList, ServiceID); /* set attributes to find */ s_list_append_uint(&attrList, SDP_ATTR_SERVICE_RECORD_HANDLE); s_list_append_uint(&attrList, SDP_ATTR_PROTO_DESC_LIST); err = __sdp_search_attr_req(&saddr, searchList, IndividualAttributes, attrList, 0xffff, &svcList, &count); s_list_destroy(&searchList); s_list_free(&attrList); hci_disconnect(&saddr); if (err) { //fprintf(stderr, "%s\n", sdp_error(err)); printf("no\n"); continue; } if (count == 0) { printf("no\n"); continue; } printf("yes\n"); svcRec = s_list_dequeue(&svcList); sdp_free_svc(svcRec); sdp_free_svclist(&svcList); //hci_get_conn(); #else fprintf(stderr, "Affix SDP support disabled at compile time!\n"); break; #endif __btdev_cache_add(devs[i].bda, devs[i].Class_of_Device, devnames[i]); if (devnames[i]) free(devnames[i]); } btdev_cache_save(); } close(fd); return 0; }
static void update_device_info(esp_bt_gap_cb_param_t *param) { char bda_str[18]; uint32_t cod = 0; int32_t rssi = -129; /* invalid value */ esp_bt_gap_dev_prop_t *p; ESP_LOGI(GAP_TAG, "Device found: %s", bda2str(param->disc_res.bda, bda_str, 18)); for (int i = 0; i < param->disc_res.num_prop; i++) { p = param->disc_res.prop + i; switch (p->type) { case ESP_BT_GAP_DEV_PROP_COD: cod = *(uint32_t *)(p->val); ESP_LOGI(GAP_TAG, "--Class of Device: 0x%x", cod); break; case ESP_BT_GAP_DEV_PROP_RSSI: rssi = *(int8_t *)(p->val); ESP_LOGI(GAP_TAG, "--RSSI: %d", rssi); break; case ESP_BT_GAP_DEV_PROP_BDNAME: default: break; } } /* search for device with MAJOR service class as "rendering" in COD */ app_gap_cb_t *p_dev = &m_dev_info; if (p_dev->dev_found && 0 != memcmp(param->disc_res.bda, p_dev->bda, ESP_BD_ADDR_LEN)) { return; } if (!esp_bt_gap_is_valid_cod(cod) || !(esp_bt_gap_get_cod_major_dev(cod) == ESP_BT_COD_MAJOR_DEV_PHONE)) { return; } memcpy(p_dev->bda, param->disc_res.bda, ESP_BD_ADDR_LEN); p_dev->dev_found = true; for (int i = 0; i < param->disc_res.num_prop; i++) { p = param->disc_res.prop + i; switch (p->type) { case ESP_BT_GAP_DEV_PROP_COD: p_dev->cod = *(uint32_t *)(p->val); break; case ESP_BT_GAP_DEV_PROP_RSSI: p_dev->rssi = *(int8_t *)(p->val); break; case ESP_BT_GAP_DEV_PROP_BDNAME: { uint8_t len = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN : (uint8_t)p->len; memcpy(p_dev->bdname, (uint8_t *)(p->val), len); p_dev->bdname[len] = '\0'; p_dev->bdname_len = len; break; } case ESP_BT_GAP_DEV_PROP_EIR: { memcpy(p_dev->eir, (uint8_t *)(p->val), p->len); p_dev->eir_len = p->len; break; } default: break; } } if (p_dev->eir && p_dev->bdname_len == 0) { get_name_from_eir(p_dev->eir, p_dev->bdname, &p_dev->bdname_len); ESP_LOGI(GAP_TAG, "Found a target device, address %s, name %s", bda_str, p_dev->bdname); p_dev->state = APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE; ESP_LOGI(GAP_TAG, "Cancel device discovery ..."); esp_bt_gap_cancel_discovery(); } }