📄 adapter.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2006-2007 Nokia Corporation * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org> * * * 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#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <time.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/l2cap.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <glib.h>#include <dbus/dbus.h>#include "hcid.h"#include "dbus.h"#include "device.h"#include "textfile.h"#include "oui.h"#include "adapter.h"#include "dbus-common.h"#include "dbus-helper.h"#include "dbus-hci.h"#include "dbus-sdp.h"#include "dbus-error.h"#include "error.h"#define NUM_ELEMENTS(table) (sizeof(table)/sizeof(const char *))static const char *service_cls[] = { "positioning", "networking", "rendering", "capturing", "object transfer", "audio", "telephony", "information"};static const char *major_cls[] = { "miscellaneous", "computer", "phone", "access point", "audio/video", "peripheral", "imaging", "wearable", "toy", "uncategorized"};static const char *computer_minor_cls[] = { "uncategorized", "desktop", "server", "laptop", "handheld", "palm", "wearable"};static const char *phone_minor_cls[] = { "uncategorized", "cellular", "cordless", "smart phone", "modem", "isdn"};static const char *access_point_minor_cls[] = { "fully", "1-17 percent", "17-33 percent", "33-50 percent", "50-67 percent", "67-83 percent", "83-99 percent", "not available"};static const char *audio_video_minor_cls[] = { "uncategorized", "headset", "handsfree", "unknown", "microphone", "loudspeaker", "headphones", "portable audio", "car audio", "set-top box", "hifi audio", "vcr", "video camera", "camcorder", "video monitor", "video display and loudspeaker", "video conferencing", "unknown", "gaming/toy"};static const char *peripheral_minor_cls[] = { "uncategorized", "keyboard", "pointing", "combo"};#if 0static const char *peripheral_2_minor_cls[] = { "uncategorized", "joystick", "gamepad", "remote control", "sensing", "digitizer tablet", "card reader"};#endifstatic const char *imaging_minor_cls[] = { "display", "camera", "scanner", "printer"};static const char *wearable_minor_cls[] = { "wrist watch", "pager", "jacket", "helmet", "glasses"};static const char *toy_minor_cls[] = { "robot", "vehicle", "doll", "controller", "game"};int pending_remote_name_cancel(struct adapter *adapter){ struct remote_dev_info *dev, match; GSList *l; int dd, err = 0; /* find the pending remote name request */ memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUESTED; l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); if (!l) /* no pending request */ return 0; dd = hci_open_dev(adapter->dev_id); if (dd < 0) return -ENODEV; dev = l->data; if (hci_read_remote_name_cancel(dd, &dev->bdaddr, 1000) < 0) { error("Remote name cancel failed: %s(%d)", strerror(errno), errno); err = -errno; } /* free discovered devices list */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; hci_close_dev(dd); return err;}static struct bonding_request_info *bonding_request_new(bdaddr_t *peer, DBusConnection *conn, DBusMessage *msg){ struct bonding_request_info *bonding; bonding = g_new0(struct bonding_request_info, 1); bacpy(&bonding->bdaddr, peer); bonding->conn = dbus_connection_ref(conn); bonding->rq = dbus_message_ref(msg); return bonding;}const char *mode2str(uint8_t mode){ switch(mode) { case MODE_OFF: return "off"; case MODE_CONNECTABLE: return "connectable"; case MODE_DISCOVERABLE: return "discoverable"; case MODE_LIMITED: return "limited"; default: return "unknown"; }}static uint8_t on_mode(const char *addr){ char mode[14]; bdaddr_t sba; str2ba(addr, &sba); if (read_on_mode(&sba, mode, sizeof(mode)) < 0) return MODE_CONNECTABLE; return str2mode(addr, mode);}uint8_t str2mode(const char *addr, const char *mode){ if (strcasecmp("off", mode) == 0) return MODE_OFF; else if (strcasecmp("connectable", mode) == 0) return MODE_CONNECTABLE; else if (strcasecmp("discoverable", mode) == 0) return MODE_DISCOVERABLE; else if (strcasecmp("limited", mode) == 0) return MODE_LIMITED; else if (strcasecmp("on", mode) == 0) return on_mode(addr); else return MODE_UNKNOWN;}static DBusHandlerResult adapter_get_info(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; const char *property = adapter->address; DBusMessage *reply; DBusMessageIter iter; DBusMessageIter dict; bdaddr_t ba; char str[249]; uint8_t cls[3]; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); dbus_message_iter_append_dict_entry(&dict, "address", DBUS_TYPE_STRING, &property); memset(str, 0, sizeof(str)); property = str; str2ba(adapter->address, &ba); if (!read_local_name(&ba, str)) dbus_message_iter_append_dict_entry(&dict, "name", DBUS_TYPE_STRING, &property); get_device_version(adapter->dev_id, str, sizeof(str)); dbus_message_iter_append_dict_entry(&dict, "version", DBUS_TYPE_STRING, &property); get_device_revision(adapter->dev_id, str, sizeof(str)); dbus_message_iter_append_dict_entry(&dict, "revision", DBUS_TYPE_STRING, &property); get_device_manufacturer(adapter->dev_id, str, sizeof(str)); dbus_message_iter_append_dict_entry(&dict, "manufacturer", DBUS_TYPE_STRING, &property); get_device_company(adapter->dev_id, str, sizeof(str)); dbus_message_iter_append_dict_entry(&dict, "company", DBUS_TYPE_STRING, &property); property = mode2str(adapter->mode); dbus_message_iter_append_dict_entry(&dict, "mode", DBUS_TYPE_STRING, &property); dbus_message_iter_append_dict_entry(&dict, "discoverable_timeout", DBUS_TYPE_UINT32, &adapter->discov_timeout); if (!read_local_class(&ba, cls)) { uint32_t class; memcpy(&class, cls, 3); dbus_message_iter_append_dict_entry(&dict, "class", DBUS_TYPE_UINT32, &class); property = major_class_str(class); dbus_message_iter_append_dict_entry(&dict, "major_class", DBUS_TYPE_STRING, &property); property = minor_class_str(class); dbus_message_iter_append_dict_entry(&dict, "minor_class", DBUS_TYPE_STRING, &property); } dbus_message_iter_close_container(&iter, &dict); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_address(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; const char *paddr = adapter->address; DBusMessage *reply; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_version(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; char str[20], *str_ptr = str; int err; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); err = get_device_version(adapter->dev_id, str, sizeof(str)); if (err < 0) return error_failed_errno(conn, msg, -err); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_revision(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; char str[64], *str_ptr = str; int err; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); err = get_device_revision(adapter->dev_id, str, sizeof(str)); if (err < 0) return error_failed_errno(conn, msg, -err); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_manufacturer(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; char str[64], *str_ptr = str; int err; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); err = get_device_manufacturer(adapter->dev_id, str, sizeof(str)); if (err < 0) return error_failed_errno(conn, msg, -err); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_company(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; char str[64], *str_ptr = str; int err; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); err = get_device_company(adapter->dev_id, str, sizeof(str)); if (err < 0) return error_failed_errno(conn, msg, -err); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_list_modes(DBusConnection *conn, DBusMessage *msg, void *data){ DBusMessage *reply; DBusMessageIter iter; DBusMessageIter array_iter; const char *mode_ptr[] = { "off", "connectable", "discoverable", "limited" }; int i; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array_iter); for (i = 0; i < 4; i++) dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &mode_ptr[i]); dbus_message_iter_close_container(&iter, &array_iter); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_mode(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; DBusMessage *reply = NULL; const char *mode; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; mode = mode2str(adapter->mode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -