📄 service.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2007 Marcel Holtmann <marcel@holtmann.org> * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <netinet/in.h>#include "sdpd.h"#include "logging.h"static sdp_record_t *server = NULL;static uint8_t service_classes = 0x00;static service_classes_callback_t service_classes_callback = NULL;static uint16_t did_vendor = 0x0000;static uint16_t did_product = 0x0000;static uint16_t did_version = 0x0000;/* * List of version numbers supported by the SDP server. * Add to this list when newer versions are supported. */static sdp_version_t sdpVnumArray[1] = { { 1, 0 }};static const int sdpServerVnumEntries = 1;/* * The service database state is an attribute of the service record * of the SDP server itself. This attribute is guaranteed to * change if any of the contents of the service repository * changes. This function updates the timestamp of value of * the svcDBState attribute * Set the SDP server DB. Simply a timestamp which is the marker * when the DB was modified. */static void update_db_timestamp(void){ uint32_t dbts = sdp_get_time(); sdp_data_t *d = sdp_data_alloc(SDP_UINT32, &dbts); sdp_attr_replace(server, SDP_ATTR_SVCDB_STATE, d);}static void update_svclass_list(void){ sdp_list_t *list = sdp_get_record_list(); uint8_t val = 0; for (; list; list = list->next) { sdp_record_t *rec = (sdp_record_t *) list->data; if (rec->svclass.type != SDP_UUID16) continue; switch (rec->svclass.value.uuid16) { case DIALUP_NET_SVCLASS_ID: case CIP_SVCLASS_ID: val |= 0x42; /* Telephony & Networking */ break; case IRMC_SYNC_SVCLASS_ID: case OBEX_OBJPUSH_SVCLASS_ID: case OBEX_FILETRANS_SVCLASS_ID: case IRMC_SYNC_CMD_SVCLASS_ID: case PBAP_PSE_SVCLASS_ID: val |= 0x10; /* Object Transfer */ break; case HEADSET_SVCLASS_ID: case HANDSFREE_SVCLASS_ID: val |= 0x20; /* Audio */ break; case CORDLESS_TELEPHONY_SVCLASS_ID: case INTERCOM_SVCLASS_ID: case FAX_SVCLASS_ID: case SAP_SVCLASS_ID: val |= 0x40; /* Telephony */ break; case AUDIO_SOURCE_SVCLASS_ID: case VIDEO_SOURCE_SVCLASS_ID: val |= 0x08; /* Capturing */ break; case AUDIO_SINK_SVCLASS_ID: case VIDEO_SINK_SVCLASS_ID: val |= 0x04; /* Rendering */ break; case PANU_SVCLASS_ID: case NAP_SVCLASS_ID: case GN_SVCLASS_ID: val |= 0x02; /* Networking */ break; } } debug("Service classes 0x%02x", val); service_classes = val; if (service_classes_callback) service_classes_callback(BDADDR_ANY, val);}uint8_t get_service_classes(const bdaddr_t *bdaddr){ return service_classes;}void set_service_classes_callback(service_classes_callback_t callback){ service_classes_callback = callback;}void create_ext_inquiry_response(const char *name, uint8_t *data){ sdp_list_t *list = sdp_get_record_list(); uint8_t *ptr = data; uint16_t uuid[24]; int i, index = 0; if (name) { int len = strlen(name); if (len > 48) { len = 48; ptr[1] = 0x08; } else ptr[1] = 0x09; ptr[0] = len + 1; memcpy(ptr + 2, name, len); ptr += len + 2; } if (did_vendor != 0x0000) { uint16_t source = 0x0002; *ptr++ = 9; *ptr++ = 11; *ptr++ = (source & 0x00ff); *ptr++ = (source & 0xff00) >> 8; *ptr++ = (did_vendor & 0x00ff); *ptr++ = (did_vendor & 0xff00) >> 8; *ptr++ = (did_product & 0x00ff); *ptr++ = (did_product & 0xff00) >> 8; *ptr++ = (did_version & 0x00ff); *ptr++ = (did_version & 0xff00) >> 8; } ptr[1] = 0x03; for (; list; list = list->next) { sdp_record_t *rec = (sdp_record_t *) list->data; if (rec->svclass.type != SDP_UUID16) continue; if (rec->svclass.value.uuid16 < 0x1100) continue; if (index > 23) { ptr[1] = 0x02; break; } for (i = 0; i < index; i++) if (uuid[i] == rec->svclass.value.uuid16) break; if (i == index - 1) continue; uuid[index++] = rec->svclass.value.uuid16; } if (index > 0) { ptr[0] = (index * 2) + 1; ptr += 2; for (i = 0; i < index; i++) { *ptr++ = (uuid[i] & 0x00ff); *ptr++ = (uuid[i] & 0xff00) >> 8; } }}void register_public_browse_group(void){ sdp_list_t *browselist; uuid_t bgscid, pbgid; sdp_data_t *sdpdata; sdp_record_t *browse = sdp_record_alloc(); browse->handle = SDP_SERVER_RECORD_HANDLE + 1; sdp_record_add(BDADDR_ANY, browse); sdpdata = sdp_data_alloc(SDP_UINT32, &browse->handle); sdp_attr_add(browse, SDP_ATTR_RECORD_HANDLE, sdpdata); sdp_uuid16_create(&bgscid, BROWSE_GRP_DESC_SVCLASS_ID); browselist = sdp_list_append(0, &bgscid); sdp_set_service_classes(browse, browselist); sdp_list_free(browselist, 0); sdp_uuid16_create(&pbgid, PUBLIC_BROWSE_GROUP); sdp_attr_add_new(browse, SDP_ATTR_GROUP_ID, SDP_UUID16, &pbgid.value.uuid16);}/* * The SDP server must present its own service record to * the service repository. This can be accessed by service * discovery clients. This method constructs a service record * and stores it in the repository */void register_server_service(void){ sdp_list_t *classIDList; uuid_t classID; void **versions, **versionDTDs; uint8_t dtd; sdp_data_t *pData; int i; server = sdp_record_alloc(); server->pattern = NULL; /* Force the record to be SDP_SERVER_RECORD_HANDLE */ server->handle = SDP_SERVER_RECORD_HANDLE; sdp_record_add(BDADDR_ANY, server); sdp_attr_add(server, SDP_ATTR_RECORD_HANDLE, sdp_data_alloc(SDP_UINT32, &server->handle)); sdp_uuid16_create(&classID, SDP_SERVER_SVCLASS_ID); classIDList = sdp_list_append(0, &classID); sdp_set_service_classes(server, classIDList); sdp_list_free(classIDList, 0); /* * Set the version numbers supported, these are passed as arguments * to the server on command line. Now defaults to 1.0 * Build the version number sequence first */ versions = (void **)malloc(sdpServerVnumEntries * sizeof(void *)); versionDTDs = (void **)malloc(sdpServerVnumEntries * sizeof(void *)); dtd = SDP_UINT16; for (i = 0; i < sdpServerVnumEntries; i++) { uint16_t *version = malloc(sizeof(uint16_t)); *version = sdpVnumArray[i].major; *version = (*version << 8); *version |= sdpVnumArray[i].minor; versions[i] = version; versionDTDs[i] = &dtd; } pData = sdp_seq_alloc(versionDTDs, versions, sdpServerVnumEntries); for (i = 0; i < sdpServerVnumEntries; i++) free(versions[i]); free(versions); free(versionDTDs); sdp_attr_add(server, SDP_ATTR_VERSION_NUM_LIST, pData); update_db_timestamp(); update_svclass_list();}void register_device_id(const uint16_t vendor, const uint16_t product, const uint16_t version){ const uint16_t spec = 0x0102, source = 0x0002; const uint8_t primary = 1; sdp_list_t *class_list, *group_list, *profile_list; uuid_t class_uuid, group_uuid; sdp_data_t *sdp_data, *primary_data, *source_data; sdp_data_t *spec_data, *vendor_data, *product_data, *version_data; sdp_profile_desc_t profile; sdp_record_t *record = sdp_record_alloc(); info("Adding device id record for %04x:%04x", vendor, product); did_vendor = vendor; did_product = product; did_version = version; record->handle = sdp_next_handle();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -