static int serial_probe(struct btd_device *device, const char *uuid) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); sdp_list_t *protos; int ch; bdaddr_t src, dst; const sdp_record_t *rec; DBG("path %s: %s", path, uuid); rec = btd_device_get_record(device, uuid); if (!rec) return -EINVAL; if (sdp_get_access_protos(rec, &protos) < 0) return -EINVAL; ch = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); if (ch < 1 || ch > 30) { error("Channel out of range: %d", ch); return -EINVAL; } adapter_get_address(adapter, &src); device_get_address(device, &dst); return port_register(connection, path, &src, &dst, uuid, ch); }
gboolean gatt_parse_record(const sdp_record_t *rec, uuid_t *prim_uuid, uint16_t *psm, uint16_t *start, uint16_t *end) { sdp_list_t *list; uuid_t uuid; gboolean ret; if (sdp_get_service_classes(rec, &list) < 0) return FALSE; memcpy(&uuid, list->data, sizeof(uuid)); sdp_list_free(list, free); if (sdp_get_access_protos(rec, &list) < 0) return FALSE; ret = parse_proto_params(list, psm, start, end); sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(list, NULL); /* FIXME: replace by bt_uuid_t after uuid_t/sdp code cleanup */ if (ret && prim_uuid) memcpy(prim_uuid, &uuid, sizeof(uuid_t)); return ret; }
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data) { struct serial_port *port = user_data; struct serial_device *device = port->device; sdp_record_t *record = NULL; sdp_list_t *protos; DBusMessage *reply; GError *gerr = NULL; if (!port->listener_id) { reply = NULL; goto failed; } if (err < 0) { error("Unable to get service record: %s (%d)", strerror(-err), -err); reply = failed(port->msg, strerror(-err)); goto failed; } if (!recs || !recs->data) { error("No record found"); reply = failed(port->msg, "No record found"); goto failed; } record = recs->data; if (sdp_get_access_protos(record, &protos) < 0) { error("Unable to get access protos from port record"); reply = failed(port->msg, "Invalid channel"); goto failed; } port->channel = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &device->src, BT_IO_OPT_DEST_BDADDR, &device->dst, BT_IO_OPT_CHANNEL, port->channel, BT_IO_OPT_INVALID); if (!port->io) { error("%s", gerr->message); reply = failed(port->msg, gerr->message); g_error_free(gerr); goto failed; } return; failed: g_dbus_remove_watch(device->conn, port->listener_id); port->listener_id = 0; g_dbus_send_message(device->conn, reply); }
int dun_sdp_search(bdaddr_t *src, bdaddr_t *dst, int *channel, int type) { sdp_session_t *s; sdp_list_t *srch, *attrs, *rsp; uuid_t svclass; uint16_t attr; int err; s = sdp_connect(src, dst, 0); if (!s) { syslog(LOG_ERR, "Failed to connect to the SDP server. %s(%d)", strerror(errno), errno); return -1; } switch (type) { case MROUTER: sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID); break; case ACTIVESYNC: sdp_uuid128_create(&svclass, (void *) async_uuid); break; case DIALUP: sdp_uuid16_create(&svclass, DIALUP_NET_SVCLASS_ID); break; default: sdp_uuid16_create(&svclass, LAN_ACCESS_SVCLASS_ID); break; } srch = sdp_list_append(NULL, &svclass); attr = SDP_ATTR_PROTO_DESC_LIST; attrs = sdp_list_append(NULL, &attr); err = sdp_service_search_attr_req(s, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp); sdp_close(s); if (err) return 0; for(; rsp; rsp = rsp->next) { sdp_record_t *rec = (sdp_record_t *) rsp->data; sdp_list_t *protos; if (!sdp_get_access_protos(rec, &protos)) { int ch = sdp_get_proto_port(protos, RFCOMM_UUID); if (ch > 0) { *channel = ch; return 1; } } } return 0; }
int main(int argc, char const *argv[]) { uint32_t svc_uuid_int[] = {0, 0, 0, 0xABCD}; int status; bdaddr_t target, source; uuid_t svc_uuid; sdp_list_t *response_list, *search_list, *attrid_list; sdp_session_t *session = 0; uint32_t range = 0x0000ffff; uint8_t port = 0; //connect to the SDP server running on the remote machine str2ba(dest, &target); str2ba(src, &source); session = sdp_connect(&source, &target, 0); if (session == NULL) { perror("sdp_connect"); exit(1); } sdp_uuid128_create(&svc_uuid, &svc_uuid_int); search_list = sdp_list_append(0, &svc_uuid); attrid_list = sdp_list_append(0, &range); //get a list of service records that have UUID 0xabcd response_list = NULL; status = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list); if (status == 0) { sdp_list_t *proto_list = NULL; sdp_list_t *r = response_list; //go through each of the service records for (; r; r = r->next) { sdp_record_t *rec = (sdp_record_t *)r->data; //get a list of the protocol sequences if (sdp_get_access_protos(rec, &proto_list) == 0) { // get the RFCOMM port number port = sdp_get_proto_port(proto_list, RFCOMM_UUID); sdp_list_free(proto_list, 0); } sdp_record_free(rec); } } sdp_list_free(response_list, 0); sdp_list_free(search_list, 0); sdp_list_free(attrid_list, 0); sdp_close(session); if (port != 0) { printf("found service running on RFCOMM Port %d\n", port); } return 0; }
/* * Taken from gnome-phone-manager */ static int get_rfcomm_channel(sdp_record_t *rec, int only_gnapplet) { int channel = -1; sdp_list_t *protos = NULL; sdp_data_t *data; char name[64]; if (sdp_get_access_protos(rec, &protos) != 0) goto end; data = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); if (data) snprintf(name, sizeof(name), "%.*s", data->unitSize, data->val.str); if (name == NULL) goto end; /* * If we're only supposed to check for gnapplet, do it here * We ignore it if we're not supposed to check for it. */ if (only_gnapplet != 0) { if (strcmp(name, "gnapplet") == 0) channel = sdp_get_proto_port(protos, RFCOMM_UUID); goto end; } /* * We can't seem to connect to the PC Suite channel. */ if (strstr(name, "Nokia PC Suite") != NULL) goto end; /* * And that type of channel on Nokia Symbian phones doesn't * work either. */ if (strstr(name, "Bluetooth Serial Port") != NULL) goto end; /* * Avoid the m-Router channel, same as the PC Suite on Sony Ericsson * phones. */ if (strstr(name, "m-Router Connectivity") != NULL) goto end; channel = sdp_get_proto_port(protos, RFCOMM_UUID); end: sdp_list_foreach(protos, (sdp_list_func_t)sdp_list_free, 0); sdp_list_free(protos, 0); return channel; }
static int detect_channel(bdaddr_t * bdaddr) { uuid_t group; bdaddr_t interface; sdp_list_t *attrid, *search, *seq, *next; uint32_t range = 0x0000ffff; sdp_session_t *sess; int channel = 2; int searchresult; bacpy(&interface, BDADDR_ANY); sdp_uuid16_create(&group, 0x1108); sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); if (!sess) { fprintf(stderr, "Failed to connect to SDP server: %s\nAssuming channel %d\n", strerror(errno), channel); return channel; } attrid = sdp_list_append(0, &range); search = sdp_list_append(0, &group); searchresult = sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq); sdp_list_free(attrid, 0); sdp_list_free(search, 0); if (searchresult) { fprintf(stderr, "Service Search failed: %s\nAssuming channel %d\n", strerror(errno), channel); sdp_close(sess); return channel; } for (; seq; seq = next) { sdp_record_t *rec = (sdp_record_t *) seq->data; sdp_list_t *list = 0; if (sdp_get_access_protos(rec, &list) == 0) { channel = sdp_get_proto_port(list, RFCOMM_UUID); } next = seq->next; free(seq); sdp_record_free(rec); } sdp_close(sess); return channel; }
static uint8_t get_channel(const char *svr, uint16_t uuid) { sdp_session_t *sdp; sdp_list_t *srch, *attrs, *rsp; uuid_t svclass; uint16_t attr; bdaddr_t dst; uint8_t channel = 0; int err; str2ba(svr, &dst); sdp = sdp_connect(&bdaddr, &dst, SDP_RETRY_IF_BUSY); if (!sdp) return 0; sdp_uuid16_create(&svclass, uuid); srch = sdp_list_append(NULL, &svclass); attr = SDP_ATTR_PROTO_DESC_LIST; attrs = sdp_list_append(NULL, &attr); err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp); if (err) goto done; for (; rsp; rsp = rsp->next) { sdp_record_t *rec = (sdp_record_t *) rsp->data; sdp_list_t *protos; if (!sdp_get_access_protos(rec, &protos)) { channel = sdp_get_proto_port(protos, RFCOMM_UUID); if (channel > 0) break; } } done: sdp_close(sdp); return channel; }
static int headset_probe(struct btd_device *device, GSList *uuids) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); const sdp_record_t *record; sdp_list_t *protos; int ch; bdaddr_t src, dst; DBG("path %s", path); if (!g_slist_find_custom(uuids, HSP_HS_UUID, (GCompareFunc) strcasecmp)) return -EINVAL; record = btd_device_get_record(device, uuids->data); if (!record || sdp_get_access_protos(record, &protos) < 0) { error("Invalid record"); return -EINVAL; } ch = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); if (ch <= 0) { error("Invalid RFCOMM channel"); return -EINVAL; } adapter_get_address(adapter, &src); device_get_address(device, &dst); return fake_input_register(connection, device, path, &src, &dst, HSP_HS_UUID, ch); }
int main(void) { int i, j, err, sock, dev_id = -1; struct hci_dev_info dev_info; inquiry_info *info = NULL; bdaddr_t target; char addr[19] = { 0 }; char name[248] = { 0 }; uuid_t uuid = { 0 }; //Change this to your apps UUID char *uuid_str="4e5d48e0-75df-11e3-981f-0800200c9a66"; uint32_t range = 0x0000ffff; sdp_list_t *response_list = NULL, *search_list, *attrid_list; int s, loco_channel = -1, status; struct sockaddr_rc loc_addr = { 0 }; pthread_t blueThread; FILE *fp_Setting; char message_Buffer[64]; char mode[30], language[16], topic[16], topicLen[16]; size_t len = 16; (void) signal(SIGINT, SIG_DFL); changeTopic_flag = 1; ///////////////////////////MRAA///////////////////////////// //Initialize MRAA mraa_init(); //Initialize MRAA Pin 8 == IO8 == GP49 mraa_gpio_context BearButton = mraa_gpio_init(8); //Check for successful initialization or else return if (BearButton == NULL){ printf("Error initializing Push to Talk Pin, IO2\n"); return -1; } //Set pin to an input mraa_gpio_dir(BearButton, MRAA_GPIO_IN); printf("Set Pin to an input\n"); int curr_pin = mraa_gpio_get_pin(BearButton); printf("The current pin number is %d\n", curr_pin); int curr_raw = mraa_gpio_get_pin_raw(BearButton); printf("The raw pin number is %d\n", curr_raw); printf("Going to start reading the button via polling\n"); //////////////////////AWS/////////////////////////////////// aws_flag = 0; IoT_Error_t rc = NONE_ERROR; char HostAddress[255] = AWS_IOT_MQTT_HOST; char certDirectory[PATH_MAX + 1] = "/AWS/SDK/certs/"; uint32_t port = AWS_IOT_MQTT_PORT; MQTTMessageParams Msg = MQTTMessageParamsDefault; Msg.qos = QOS_0; char cPayload[100]; Msg.pPayload = (void *) cPayload; char rootCA[PATH_MAX + 1]; char clientCRT[PATH_MAX + 1]; char clientKey[PATH_MAX + 1]; char cafileName[] = AWS_IOT_ROOT_CA_FILENAME; char clientCRTName[] = AWS_IOT_CERTIFICATE_FILENAME; char clientKeyName[] = AWS_IOT_PRIVATE_KEY_FILENAME; sprintf(rootCA, "/%s/%s", certDirectory, cafileName); sprintf(clientCRT, "/%s/%s", certDirectory, clientCRTName); sprintf(clientKey, "/%s/%s", certDirectory, clientKeyName); MQTTConnectParams connectParams = MQTTConnectParamsDefault; connectParams.KeepAliveInterval_sec = 14000; connectParams.isCleansession = true; connectParams.MQTTVersion = MQTT_3_1_1; connectParams.pClientID = "TED"; connectParams.pHostURL = HostAddress; connectParams.port = port; connectParams.isWillMsgPresent = false; connectParams.pRootCALocation = rootCA; connectParams.pDeviceCertLocation = clientCRT; connectParams.pDevicePrivateKeyLocation = clientKey; connectParams.mqttCommandTimeout_ms = 2000; connectParams.tlsHandshakeTimeout_ms = 5000; connectParams.isSSLHostnameVerify = true;// ensure this is set to true for production connectParams.disconnectHandler = disconnectCallbackHandler; MQTTPublishParams CurriculumParams = MQTTPublishParamsDefault; CurriculumParams.pTopic = "Bear/Curriculum/Request"; MQTTPublishParams MetricsParams = MQTTPublishParamsDefault; MetricsParams.pTopic = "Bear/Curriculum/Metrics"; /////////////////////////////////////////////////////////////////////////////////////// dev_id = hci_get_route(NULL); if (dev_id < 0) { perror("No Bluetooth Adapter Available"); exit(1); } if (hci_devinfo(dev_id, &dev_info) < 0) { perror("Can't get device info"); exit(1); } sock = hci_open_dev( dev_id ); if (sock < 0) { perror("HCI device open failed"); free(info); exit(1); } if( !str2uuid( uuid_str, &uuid ) ) { perror("Invalid UUID"); free(info); exit(1); } do { printf("Scanning ...\n"); sdp_session_t *session; int retries; int foundit, responses; str2ba(TABLET_ADDRESS,&target); memset(name, 0, sizeof(name)); if (hci_read_remote_name(sock, &target, sizeof(name), name, 0) < 0){ strcpy(name, "[unknown]"); } printf("Found %s %s, searching for the the desired service on it now\n", addr, name); // connect to the SDP server running on the remote machine sdpconnect: session = 0; retries = 0; while(!session) { session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY ); if(session) break; if(errno == EALREADY && retries < 5) { perror("Retrying"); retries++; sleep(1); continue; } break; } if ( session == NULL ) { perror("Can't open session with the device"); continue; } search_list = sdp_list_append( 0, &uuid ); attrid_list = sdp_list_append( 0, &range ); err = 0; err = sdp_service_search_attr_req( session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list); sdp_list_t *r = response_list; sdp_record_t *rec; // go through each of the service records foundit = 0; responses = 0; for (; r; r = r->next ) { responses++; rec = (sdp_record_t*) r->data; sdp_list_t *proto_list; // get a list of the protocol sequences if( sdp_get_access_protos( rec, &proto_list ) == 0 ) { sdp_list_t *p = proto_list; // go through each protocol sequence for( ; p ; p = p->next ) { sdp_list_t *pds = (sdp_list_t*)p->data; // go through each protocol list of the protocol sequence for( ; pds ; pds = pds->next ) { // check the protocol attributes sdp_data_t *d = (sdp_data_t*)pds->data; int proto = 0; for( ; d; d = d->next ) { switch( d->dtd ) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: proto = sdp_uuid_to_proto( &d->val.uuid ); break; case SDP_UINT8: if( proto == RFCOMM_UUID ) { printf("rfcomm channel: %d\n",d->val.int8); loco_channel = d->val.int8; foundit = 1; } break; } } } sdp_list_free( (sdp_list_t*)p->data, 0 ); } sdp_list_free( proto_list, 0 ); } if (loco_channel > 0) break; } printf("No of Responses %d\n", responses); if ( loco_channel > 0 && foundit == 1 ) { printf("Found service on this device, now gonna blast it with dummy data\n"); s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); loc_addr.rc_family = AF_BLUETOOTH; loc_addr.rc_channel = loco_channel; loc_addr.rc_bdaddr = *(&target); status = connect(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr)); if( status < 0 ) { perror("uh oh"); } rc = pthread_create(&blueThread, NULL, threadListen, (void *)s); if (rc){ printf("ERROR: %d\n", rc); exit(1); } MQTTSubscribeParams subParams = MQTTSubscribeParamsDefault; //Loop through trying to subscribe to AWS incase the first attempt fails, so will keep trying until the app sends the edison proper network info. do{ INFO("Connecting..."); rc = aws_iot_mqtt_connect(&connectParams); if (NONE_ERROR != rc) { ERROR("Error(%d) connecting to %s:%d", rc, connectParams.pHostURL, connectParams.port); } subParams.mHandler = MQTTcallbackHandler; subParams.pTopic = "Bear/Curriculum/Response"; subParams.qos = QOS_0; if (NONE_ERROR == rc) { INFO("Subscribing..."); rc = aws_iot_mqtt_subscribe(&subParams); if (NONE_ERROR != rc) { ERROR("Error subscribing"); } } sleep(1); }while(NONE_ERROR != rc); aws_flag = 1; //////////////////////////Start of teaching stuff////////////////////////////////////////// do { if(changeTopic_flag){ sprintf(cPayload, "{\"BearID\":\"%s\"}",BEARID); Msg.PayloadLen = strlen(cPayload) + 1; CurriculumParams.MessageParams = Msg; rc = aws_iot_mqtt_publish(&CurriculumParams); while(rc == NONE_ERROR && changeTopic_flag){ rc = aws_iot_mqtt_yield(100); INFO("-->sleep"); sleep(1); } changeTopic_flag = 0; } fp_Setting = fopen("/Curriculum/BearSettings.txt", "r"); fgets(language, sizeof(language), fp_Setting); fgets(mode, sizeof(mode), fp_Setting); fgets(topic, sizeof(topic), fp_Setting); fgets(topicLen, sizeof(topicLen), fp_Setting); language[strlen(language)-1] = 0; mode[strlen(mode)-1] = 0; topic[strlen(topic)-1] = 0; topicLen[strlen(topicLen)-1] = 0; fclose(fp_Setting); //Wait for the tablet to tell the edison to start the lesson while(strcmp(threadMessage, "learning")){ printf("Waiting for learning, got: %s\n", threadMessage); if(!strcmp(threadMessage, "crash")){ memset(threadMessage, 0, sizeof(threadMessage)); goto CRASHED; } memset(threadMessage, 0, sizeof(threadMessage)); sleep(1); } printf("Current Mode: %s\n", mode); printf("Current Language: %s\n", language); printf("Current topic: %s\n", topic); //Call a different function depending on what teaching mode it is, also write to the tablet based on the topic info and lesson if(!strcmp(mode, "Repeat After Me")){ sprintf(message_Buffer,"%s,1,%s",language, topicLen); status = write(s,message_Buffer,sizeof(message_Buffer)); if(!strcmp(language, "English")){ status = repeat_after_me_english(s, topic, MetricsParams, BearButton); } else{ status = repeat_after_me_foreign(s, language, topic, MetricsParams, BearButton); } } else if(!strcmp(mode, "English to Foreign")){ sprintf(message_Buffer,"%s,3,%s",language, topicLen); status = write(s,message_Buffer,sizeof(message_Buffer)); status = english_to_foreign(s, language, topic, MetricsParams, BearButton); } else if(!strcmp(mode, "Foreign to English")){ sprintf(message_Buffer,"%s,2,%s",language, topicLen); status = write(s,message_Buffer,sizeof(message_Buffer)); status = foreign_to_english(s, language, topic, MetricsParams, BearButton); } changeTopic_flag = 1; printf("Changing Topic"); sleep(5); } while (status > 0); CRASHED: printf("\nBluetooth Disconnected\n"); close(s); sdp_record_free( rec ); } sdp_close(session); if (loco_channel > 0) { goto sdpconnect; //break; } sleep(1); } while (1); printf("Exiting...\n"); }
/* * utility function to perform an SDP search on a connected session. Builds * and returns a python list of dictionaries. Each dictionary represents a * service record match */ static PyObject * do_search( sdp_session_t *sess, uuid_t *uuid ) { sdp_list_t *response_list = NULL, *attrid_list, *search_list, *r; uint32_t range = 0x0000ffff; char buf[1024] = { 0 }; int err = 0; PyObject *result = 0; PyObject *rtn_list = PyList_New(0); if( ! rtn_list ) return 0; search_list = sdp_list_append( 0, uuid ); attrid_list = sdp_list_append( 0, &range ); // perform the search Py_BEGIN_ALLOW_THREADS err = sdp_service_search_attr_req( sess, search_list, \ SDP_ATTR_REQ_RANGE, attrid_list, &response_list); Py_END_ALLOW_THREADS if( err ) { PyErr_SetFromErrno( bluetooth_error ); result = 0; goto cleanup; } // parse the results (ewww....) // go through each of the service records for (r = response_list; r; r = r->next ) { PyObject *dict = PyDict_New(); sdp_record_t *rec = (sdp_record_t*) r->data; sdp_list_t *proto_list = NULL, *svc_class_list = NULL, *profile_list = NULL; PyObject *py_class_list = NULL, *py_profile_list = NULL; uuid_t service_id = { 0 }; if( ! dict ) return 0; // initialize service class list py_class_list = PyList_New(0); if( ! py_class_list ) return 0; dict_set_str_pyobj( dict, "service-classes", py_class_list ); Py_DECREF( py_class_list ); // initialize profile list py_profile_list = PyList_New(0); if( ! py_profile_list ) return 0; dict_set_str_pyobj( dict, "profiles", py_profile_list ); Py_DECREF( py_profile_list ); // set service name if( ! sdp_get_service_name( rec, buf, sizeof(buf) ) ) { dict_set_strings( dict, "name", buf ); memset(buf, 0, sizeof( buf ) ); } else { dict_set_str_pyobj( dict, "name", Py_None ); } // set service description if( ! sdp_get_service_desc( rec, buf, sizeof(buf) ) ) { dict_set_strings( dict, "description", buf ); memset(buf, 0, sizeof( buf ) ); } else { dict_set_str_pyobj( dict, "description", Py_None ); } // set service provider name if( ! sdp_get_provider_name( rec, buf, sizeof(buf) ) ) { dict_set_strings( dict, "provider", buf ); memset(buf, 0, sizeof( buf ) ); } else { dict_set_str_pyobj( dict, "provider", Py_None ); } // set service id if( ! sdp_get_service_id( rec, &service_id ) ) { uuid2str( &service_id, buf ); dict_set_strings( dict, "service-id", buf ); memset(buf, 0, sizeof( buf ) ); } else { dict_set_str_pyobj( dict, "service-id", Py_None ); } // get a list of the protocol sequences if( sdp_get_access_protos( rec, &proto_list ) == 0 ) { sdp_list_t *p = proto_list; int port; if( ( port = sdp_get_proto_port( p, RFCOMM_UUID ) ) != 0 ) { dict_set_strings( dict, "protocol", "RFCOMM" ); dict_set_str_long( dict, "port", port ); } else if ( (port = sdp_get_proto_port( p, L2CAP_UUID ) ) != 0 ) { dict_set_strings( dict, "protocol", "L2CAP" ); dict_set_str_long( dict, "port", port ); } else { dict_set_strings( dict, "protocol", "UNKNOWN" ); dict_set_str_pyobj( dict, "port", Py_None ); } // sdp_get_access_protos allocates data on the heap for the // protocol list, so we need to free the results... for( ; p ; p = p->next ) { sdp_list_free( (sdp_list_t*)p->data, 0 ); } sdp_list_free( proto_list, 0 ); } else { dict_set_str_pyobj( dict, "protocol", Py_None ); dict_set_str_pyobj( dict, "port", Py_None ); } // get a list of the service classes if( sdp_get_service_classes( rec, &svc_class_list ) == 0 ) { sdp_list_t *iter; for( iter = svc_class_list; iter != NULL; iter = iter->next ) { PyObject *pystr; char uuid_str[40] = { 0 }; uuid2str( (uuid_t*)iter->data, uuid_str ); pystr = PyString_FromString( uuid_str ); PyList_Append( py_class_list, pystr ); Py_DECREF( pystr ); } sdp_list_free( svc_class_list, free ); } // get a list of the profiles if( sdp_get_profile_descs( rec, &profile_list ) == 0 ) { sdp_list_t *iter; for( iter = profile_list; iter != NULL; iter = iter->next ) { PyObject *tuple, *py_uuid, *py_version; sdp_profile_desc_t *desc = (sdp_profile_desc_t*)iter->data; char uuid_str[40] = { 0 }; uuid2str( &desc->uuid, uuid_str ); py_uuid = PyString_FromString( uuid_str ); py_version = PyInt_FromLong( desc->version ); tuple = PyTuple_New( 2 ); PyList_Append( py_profile_list, tuple ); Py_DECREF( tuple ); PyTuple_SetItem( tuple, 0, py_uuid ); PyTuple_SetItem( tuple, 1, py_version ); // Py_DECREF( py_uuid ); // Py_DECREF( py_version ); } sdp_list_free( profile_list, free ); } PyList_Append( rtn_list, dict ); Py_DECREF( dict ); sdp_record_free( rec ); } result = rtn_list; cleanup: sdp_list_free( response_list, 0 ); sdp_list_free( search_list, 0 ); sdp_list_free( attrid_list, 0 ); return result; }
int main(int argc, char **argv) { /* on Samsung Galaxy S3 Service Name: LIVIO_CONNECT Service RecHandle: 0x1000a Service Class ID List: UUID 128: fbe4be12-374a-486b-a473-24e39408a24d Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) */ uint8_t svc_uuid_int[] = { 0xfb, 0xe4, 0xbe, 0x12, 0x37, 0x4a, 0x48, 0x6b, 0xa4, 0x73, 0x24, 0xe3, 0x94, 0x08, 0xa2, 0x4d}; uuid_t svc_uuid; int err; bdaddr_t target; sdp_list_t *response_list = NULL, *search_list, *attrid_list; sdp_session_t *session = 0; if(argc < 2) { printf("usage: %s <bt-addr> \n",argv[0]); exit(1); } str2ba( argv[1], &target ); // connect to the SDP server running on the remote machine session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY ); // specify the UUID of the application we're searching for sdp_uuid128_create( &svc_uuid, &svc_uuid_int ); search_list = sdp_list_append( NULL, &svc_uuid ); // specify that we want a list of all the matching applications' attributes uint32_t range = 0x0000ffff; attrid_list = sdp_list_append( NULL, &range ); printf("starting search...\n"); // get a list of service records that have UUID 0xabcd err = sdp_service_search_attr_req( session, search_list, \ SDP_ATTR_REQ_RANGE, attrid_list, &response_list); sdp_list_t *r = response_list; printf("search completed\n"); // go through each of the service records for (; r; r = r->next ) { sdp_record_t *rec = (sdp_record_t*) r->data; sdp_list_t *proto_list; // get a list of the protocol sequences if( sdp_get_access_protos( rec, &proto_list ) == 0 ) { sdp_list_t *p = proto_list; // go through each protocol sequence for( ; p ; p = p->next ) { sdp_list_t *pds = (sdp_list_t*)p->data; // go through each protocol list of the protocol sequence for( ; pds ; pds = pds->next ) { // check the protocol attributes sdp_data_t *d = (sdp_data_t*)pds->data; int proto = 0; for( ; d; d = d->next ) { switch( d->dtd ) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: proto = sdp_uuid_to_proto( &d->val.uuid ); printf("\tproto: 0x%x\n", proto); break; case SDP_UINT8: if( proto == RFCOMM_UUID ) { printf("rfcomm channel: %d\n",d->val.int8); } break; } } } sdp_list_free( (sdp_list_t*)p->data, 0 ); } sdp_list_free( proto_list, 0 ); } printf("found service record 0x%x\n", rec->handle); sdp_record_free( rec ); } sdp_close(session); }
void *main_bluetooth(void *arg) { int i, err, sock, dev_id = -1; int num_rsp = 0, max_rsp = 5, flags = 0, length = 4; /* [1.28 *<length>]seconds [1.28*4 = 5.12] seconds */ char addr[19] = {0}; char cmd[100], cmd1[50]; char name[248] = {0}, bt_mac[19] = "00:00:00:00:00:00"; uuid_t uuid = {0}; int application_id = (int) *(int *) arg; char uuid_str[50]; FILE *fd = NULL; if (application_id == 2) { printf("\nOpen application: Android Locomate Messaging\n"); strcpy(uuid_str, "66841278-c3d1-11df-ab31-001de000a901"); } else if (application_id == 3) { printf("\nOpen application: Spat Andriod Application\n"); strcpy(uuid_str, "66841278-c3d1-11df-ab31-001de000a903"); } else if (application_id == 4) { printf("\nOpen application: Bluetooth CAN application\n"); strcpy(uuid_str, "00001101-0000-1000-8000-00805F9B34FB"); fd = popen("cat /var/can.conf | grep BTCAN_MAC= | cut -d '=' -f 2", "r"); if (fd != NULL) { fscanf(fd, "%s", bt_mac); pclose(fd); printf("Mac from conf file: %s\n", bt_mac); } } else { printf("\nOpen application: Locomate Safety Application\n"); strcpy(uuid_str, "66841278-c3d1-11df-ab31-001de000a902"); } uint32_t range = 0x0000ffff; sdp_list_t *response_list = NULL, *search_list, *attrid_list; int status; int responses; int retries = 0; struct sockaddr_rc loc_addr = {0}; signal(SIGINT, (void *) sig_int); /* find the bluetooth device is available or not */ sprintf(cmd, "/usr/local/bin/hciconfig hci0 up"); system(cmd); for (retries = 0; retries < 5; retries++) { dev_id = hci_get_route(NULL); if (dev_id < 0) { perror("No Bluetooth Adapter Available\n"); sprintf(cmd, "/usr/local/bin/hciconfig hci0 down"); system(cmd); sprintf(cmd1, "/usr/local/bin/hciconfig hci0 up"); system(cmd1); printf("\nretry getting adapter : %d\n", retries); } else break; } if (retries == 5) { Btooth_forward = -1; return NULL; } for (retries = 0; retries < 5; retries++) { //check for the socket sock = hci_open_dev(dev_id); if (sock < 0) { perror("HCI device open failed"); retries++; printf("\nretries sock : %d\n", retries); } else break; } if (retries == 5) { Btooth_forward = -2; return NULL; } for (retries = 0; retries < 5; retries++) { //check uuid is correct or not if (!str2uuid(uuid_str, &uuid)) { perror("Invalid UUID"); retries++; printf("\nretries str2 uuid : %d\n", retries); } else break; } if (retries == 5) { Btooth_forward = -3; return NULL; } //printf("\nBluetooth Adapter Found \n"); info = (inquiry_info *) malloc(MAX_RSP * sizeof(inquiry_info)); while (1) { // loop to check and establish connection with other device while (connection_established == FALSE) { bzero(info, (MAX_RSP * sizeof(inquiry_info))); num_rsp = hci_inquiry(dev_id, length, max_rsp, NULL, &info, flags); // inquire for how many devices are available if (num_rsp < 0) { perror("Inquiry failed"); sched_yield(); sleep(1); continue; } printf("Inquiry devices found : %d\n", num_rsp); loco_channel = -1; for (i = 0; i < num_rsp; i++) { sdp_session_t *session; ba2str(&(info + i)->bdaddr, addr); printf("\nFound Mac: %s ", addr); if (application_id == 4 && strcmp("00:00:00:00:00:00", bt_mac)) // check for appid and mac_id if (strcasecmp(addr, bt_mac)) continue; memset(name, 0, sizeof(name)); if (hci_read_remote_name(sock, &(info + i)->bdaddr, sizeof(name), name, 8000) < 0) //get devices by name strcpy(name, "[unknown]"); printf("Found : %s name : [[ %s ]]\n", addr, name); // connect to the SDP server running on the remote machine session = NULL; retries = 0; while (!session) { session = sdp_connect(BDADDR_ANY, &(info + i)->bdaddr, 0); if (session) break; if (errno != 0) { fprintf(stderr, "sdp_connect failed error no %d : %s \n", errno, strerror(errno)); } if ((retries < 2) && ((errno == EALREADY))) { retries++; fprintf(stderr, "Retry sdp_connect %d\t", retries); sched_yield(); usleep(300000);//300 ms continue; //continue till 3 times } break; } /* while(!session) */ if (session == NULL) { if (i < (num_rsp - 1)) printf("Trying next device -> %d\n", i + 2); continue; } search_list = NULL; attrid_list = NULL; response_list = NULL; search_list = sdp_list_append(NULL, &uuid); //append list of uuids attrid_list = sdp_list_append(NULL, &range); // append list of attributes err = 0; err = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list); //search for attributes from list sdp_list_t *r = response_list; responses = 0; // go through each of the service records for (; r; r = r->next) { responses++; sdp_record_t *rec = (sdp_record_t *) r->data; sdp_list_t *proto_list; // get a list of the protocol sequences if (sdp_get_access_protos(rec, &proto_list) == 0) { sdp_list_t *p = proto_list; // go through each protocol sequence for (; p; p = p->next) { sdp_list_t *pds = (sdp_list_t *) p->data; // go through each protocol list of the protocol sequence for (; pds; pds = pds->next) { // check the protocol attributes sdp_data_t *d = (sdp_data_t *) pds->data; int proto = 0; for (; d; d = d->next) { switch (d->dtd) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: proto = sdp_uuid_to_proto(&d->val.uuid); break; case SDP_UINT8: if (proto == RFCOMM_UUID) { printf("rfcomm channel: %d\n", d->val.int8); loco_channel = d->val.int8; } break; } /* switch(t->dtd) */ } /* for( ; d; d = d->next) */ } /* for( ; pds ; pds = pds->next) */ sdp_list_free((sdp_list_t *) p->data, 0); } /* for( ; p; p = p->next) */ sdp_list_free(proto_list, 0); } /* if(sdp_get_access_protos(rec, &proto_list)) */ sdp_record_free(rec); if (loco_channel > 0) { break; } } /* for (; r; r = r->next) */ sdp_list_free(response_list, 0); sdp_list_free(search_list, 0); sdp_list_free(attrid_list, 0); printf("No of services= %d on device %d \n", responses, i + 1); if (loco_channel > 0) { // printf("Found Locomate Safety Application on device: name [%s], sending message now\n",name); btooth_socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); loc_addr.rc_family = AF_BLUETOOTH; loc_addr.rc_channel = loco_channel; loc_addr.rc_bdaddr = (info + i)->bdaddr; status = connect(btooth_socket, (struct sockaddr *) &loc_addr, sizeof(loc_addr)); if (status < 0) { perror("\nuh oh: Btooth socket not created\n"); Btooth_forward = -5; } else { sdp_close(session); Btooth_forward = 1; connection_established = TRUE; break; } } sdp_close(session); } /* for (i = 0; i < num_rsp; i++) */ if (connection_established == FALSE) { printf("Scanning again\n"); //sprintf(cmd, "/usr/local/bin/hciconfig hci0 down"); //system(cmd); sprintf(cmd1, "/usr/local/bin/hciconfig hci0 up"); system(cmd1); sched_yield(); sleep(1); } else { printf("***Connection established***\n"); } } /* while(connection_established == ...) */ sched_yield(); sleep(3); // wait for 3seconds, before next check } }
static void search_callback(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data) { struct bluetooth_session *session = user_data; unsigned int scanned, bytesleft = size; int seqlen = 0; uint8_t dataType; uint16_t port = 0; GError *gerr = NULL; if (status || type != SDP_SVC_SEARCH_ATTR_RSP) goto failed; scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen); if (!scanned || !seqlen) goto failed; rsp += scanned; bytesleft -= scanned; do { sdp_record_t *rec; sdp_list_t *protos; sdp_data_t *data; int recsize, ch = -1; recsize = 0; rec = sdp_extract_pdu(rsp, bytesleft, &recsize); if (!rec) break; if (!recsize) { sdp_record_free(rec); break; } if (!sdp_get_access_protos(rec, &protos)) { ch = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); protos = NULL; } data = sdp_data_get(rec, 0x0200); /* PSM must be odd and lsb of upper byte must be 0 */ if (data != NULL && (data->val.uint16 & 0x0101) == 0x0001) ch = data->val.uint16; sdp_record_free(rec); if (ch > 0) { port = ch; break; } scanned += recsize; rsp += recsize; bytesleft -= recsize; } while (scanned < size && bytesleft > 0); if (port == 0) goto failed; session->port = port; g_io_channel_set_close_on_unref(session->io, FALSE); g_io_channel_unref(session->io); session->io = transport_connect(&session->src, &session->dst, port, transport_callback, session); if (session->io != NULL) { sdp_close(session->sdp); session->sdp = NULL; return; } failed: if (session->io != NULL) { g_io_channel_shutdown(session->io, TRUE, NULL); g_io_channel_unref(session->io); session->io = NULL; } g_set_error(&gerr, OBC_BT_ERROR, -EIO, "Unable to find service record"); if (session->func) session->func(session->io, gerr, session->user_data); g_clear_error(&gerr); session_destroy(session); }
int discover_sdp(char* remote) { int channel = 0; // returns rfcomm channel uuid_t svc_uuid; int err; bdaddr_t target; sdp_list_t *response_list = NULL, *search_list, *attrid_list; sdp_session_t *session = 0; str2ba( remote , &target ); // connect to the SDP server running on the remote machine if (D) printf("connecting..\n"); session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY ); // specify the UUID of the application we're searching for if (D) printf("uuid\n"); sdp_uuid128_create( &svc_uuid, &service_uuid_int ); search_list = sdp_list_append( NULL, &svc_uuid ); // specify that we want a list of all the matching applications' attributes uint32_t range = 0x0000ffff; attrid_list = sdp_list_append( NULL, &range ); // get a list of service records that have UUID 0xabcd err = sdp_service_search_attr_req( session, search_list, \ SDP_ATTR_REQ_RANGE, attrid_list, &response_list); sdp_list_t *r = response_list; // go through each of the service records for (; r; r = r->next ) { sdp_record_t *rec = (sdp_record_t*) r->data; sdp_list_t *proto_list; // get a list of the protocol sequences if( sdp_get_access_protos( rec, &proto_list ) == 0 ) { sdp_list_t *p = proto_list; // go through each protocol sequence for( ; p ; p = p->next ) { sdp_list_t *pds = (sdp_list_t*)p->data; // go through each protocol list of the protocol sequence for( ; pds ; pds = pds->next ) { // check the protocol attributes sdp_data_t *d = (sdp_data_t*)pds->data; int proto = 0; for( ; d; d = d->next ) { switch( d->dtd ) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: proto = sdp_uuid_to_proto( &d->val.uuid ); break; case SDP_UINT8: if( proto == RFCOMM_UUID ) { printf("rfcomm channel: %d\n",d->val.int8); channel = (int)d->val.int8; } break; } } } sdp_list_free( (sdp_list_t*)p->data, 0 ); } sdp_list_free( proto_list, 0 ); } printf("found service record 0x%x\n", rec->handle); sdp_record_free( rec ); } sdp_close(session); return channel; }
static void search_callback(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data) { struct callback_data *callback = user_data; unsigned int scanned, bytesleft = size; int seqlen = 0; uint8_t dataType, channel = 0; GError *gerr = NULL; if (status || type != SDP_SVC_SEARCH_ATTR_RSP) goto failed; scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen); if (!scanned || !seqlen) goto failed; rsp += scanned; bytesleft -= scanned; do { sdp_record_t *rec; sdp_list_t *protos; int recsize, ch = -1; recsize = 0; rec = sdp_extract_pdu(rsp, bytesleft, &recsize); if (!rec) break; if (!recsize) { sdp_record_free(rec); break; } if (!sdp_get_access_protos(rec, &protos)) { ch = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); protos = NULL; } sdp_record_free(rec); if (ch > 0) { channel = ch; break; } scanned += recsize; rsp += recsize; bytesleft -= recsize; } while (scanned < size && bytesleft > 0); if (channel == 0) goto failed; callback->session->channel = channel; callback->session->io = rfcomm_connect(&callback->session->src, &callback->session->dst, channel, rfcomm_callback, callback); if (callback->session->io != NULL) { sdp_close(callback->sdp); return; } failed: sdp_close(callback->sdp); g_set_error(&gerr, OBEX_IO_ERROR, -EIO, "Unable to find service record"); callback->func(callback->session, gerr, callback->data); g_clear_error(&gerr); session_unref(callback->session); g_free(callback); }
uint8_t sdp_lookup_uuid_rfcomm_channel(bdaddr_t *addr, uint16_t wanted_uuid) { uuid_t uuid; sdp_list_t *sdp_res, *sdp_search, *sdp_wanted_attr; sdp_session_t *sdp_session; uint32_t wanted_attr_range = 0xFFFF; bdaddr_t bdaddr = *addr; uint8_t rfcomm_channel = 0; int err; sdp_session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY); if (NULL != sdp_session) printf("Connected to target SDP server\n"); sdp_uuid16_create(&uuid, wanted_uuid); sdp_search = sdp_list_append( NULL, &uuid ); sdp_wanted_attr = sdp_list_append( NULL, &wanted_attr_range ); // get a list of service records that have UUID 0xabcd err = sdp_service_search_attr_req(sdp_session, sdp_search, SDP_ATTR_REQ_RANGE, sdp_wanted_attr, &sdp_res); printf("SDP service search result: %p\n", sdp_res); sdp_list_t *r = sdp_res; // go through each of the service records for (; r; r = r->next ) { sdp_record_t *rec = (sdp_record_t*) r->data; sdp_list_t *proto_list; // get a list of the protocol sequences if( sdp_get_access_protos( rec, &proto_list ) == 0 ) { sdp_list_t *p = proto_list; // go through each protocol sequence for( ; p ; p = p->next ) { sdp_list_t *pds = (sdp_list_t*)p->data; // go through each protocol list of the protocol sequence for( ; pds ; pds = pds->next ) { // check the protocol attributes sdp_data_t *d = (sdp_data_t*)pds->data; int proto = 0; for( ; d; d = d->next ) { switch( d->dtd ) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: proto = sdp_uuid_to_proto( &d->val.uuid ); printf("Proto: %d\n", proto); break; case SDP_UINT8: if( proto == RFCOMM_UUID ) { rfcomm_channel = d->val.int8; printf("Found RFCOMM channel: %d\n",d->val.int8); } break; } } } sdp_list_free( (sdp_list_t*)p->data, 0 ); } sdp_list_free( proto_list, 0 ); } sdp_record_free( rec ); } sdp_close(sdp_session); return rfcomm_channel; }
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data) { struct audio_device *dev = user_data; struct gateway *gw = dev->gateway; int ch; sdp_list_t *protos, *classes; uuid_t uuid; GIOChannel *io; GError *gerr = NULL; if (err < 0) { error("Unable to get service record: %s (%d)", strerror(-err), -err); goto fail; } if (!recs || !recs->data) { error("No records found"); err = -EIO; goto fail; } if (sdp_get_service_classes(recs->data, &classes) < 0) { error("Unable to get service classes from record"); err = -EINVAL; goto fail; } if (sdp_get_access_protos(recs->data, &protos) < 0) { error("Unable to get access protocols from record"); err = -ENODATA; goto fail; } gw->version = get_remote_profile_version(recs->data); if (gw->version == 0) { error("Unable to get profile version from record"); err = -EINVAL; goto fail; } memcpy(&uuid, classes->data, sizeof(uuid)); sdp_list_free(classes, free); if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 || uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) { sdp_list_free(protos, NULL); error("Invalid service record or not HFP"); err = -EIO; goto fail; } ch = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); if (ch <= 0) { error("Unable to extract RFCOMM channel from service record"); err = -EIO; goto fail; } io = bt_io_connect(rfcomm_connect_cb, dev, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &dev->src, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_CHANNEL, ch, BT_IO_OPT_INVALID); if (!io) { error("Unable to connect: %s", gerr->message); goto fail; } g_io_channel_unref(io); return; fail: if (gw->msg) { DBusMessage *reply = btd_error_failed(gw->msg, gerr ? gerr->message : strerror(-err)); g_dbus_send_message(btd_get_dbus_connection(), reply); } gateway_close(dev); if (gerr) g_error_free(gerr); }