static void search_cb(sdp_list_t *recs, int err, gpointer data) { struct avrcp_device *dev = data; sdp_list_t *list; DBG(""); if (err < 0) { error("Unable to get AV_REMOTE_SVCLASS_ID SDP record: %s", strerror(-err)); goto fail; } if (!recs || !recs->data) { error("No AVRCP records found"); goto fail; } for (list = recs; list; list = list->next) { sdp_record_t *rec = list->data; sdp_list_t *l; sdp_profile_desc_t *desc; int features; if (sdp_get_profile_descs(rec, &l) < 0) continue; desc = l->data; dev->version = desc->version; if (sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, &features) == 0) dev->features = features; sdp_list_free(l, free); break; } if (dev->io) { GError *gerr = NULL; if (!bt_io_accept(dev->io, connect_cb, dev, NULL, &gerr)) { error("bt_io_accept: %s", gerr->message); g_error_free(gerr); goto fail; } return; } if (!avrcp_device_connect(dev, connect_cb)) { error("Unable to connect to AVRCP"); goto fail; } return; fail: avrcp_device_remove(dev); }
static const void *bluetooth_getattribute(guint id, int attribute_id) { GSList *l; sdp_data_t *data; for (l = sessions; l; l = l->next) { struct bluetooth_session *session = l->data; if (session->id != id) continue; if (session->sdp_record == NULL) break; /* Read version since UUID is already known */ if (attribute_id == SDP_ATTR_PFILE_DESC_LIST) { sdp_list_t *descs; void *ret = NULL; if (sdp_get_profile_descs(session->sdp_record, &descs) < 0) return NULL; if (descs && descs->data) { sdp_profile_desc_t *desc = descs->data; ret = GINT_TO_POINTER(desc->version); } sdp_list_free(descs, free); return ret; } data = sdp_data_get(session->sdp_record, attribute_id); if (!data) break; return &data->val; } return NULL; }
static int get_remote_profile_version(sdp_record_t *rec) { uuid_t uuid; sdp_list_t *profiles; sdp_profile_desc_t *desc; int ver = 0; sdp_uuid16_create(&uuid, HANDSFREE_PROFILE_ID); sdp_get_profile_descs(rec, &profiles); if (profiles == NULL) goto done; desc = profiles->data; if (sdp_uuid16_cmp(&desc->uuid, &uuid) == 0) ver = desc->version; sdp_list_free(profiles, free); done: return ver; }
/* * 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; }