📄 adapter.c
字号:
dbus_message_append_args(reply, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_set_mode(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; const char *mode; uint8_t scan_enable; uint8_t new_mode, current_scan = adapter->scan_enable; bdaddr_t local; gboolean limited; int err, dd; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (!mode) return error_invalid_arguments(conn, msg, NULL); new_mode = str2mode(adapter->address, mode); switch(new_mode) { case MODE_OFF: scan_enable = SCAN_DISABLED; break; case MODE_CONNECTABLE: scan_enable = SCAN_PAGE; break; case MODE_DISCOVERABLE: case MODE_LIMITED: scan_enable = (SCAN_PAGE | SCAN_INQUIRY); break; default: return error_invalid_arguments(conn, msg, NULL); } /* Do reverse resolution in case of "on" mode */ mode = mode2str(new_mode); dd = hci_open_dev(adapter->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); if (!adapter->up && (hcid.offmode == HCID_OFFMODE_NOSCAN || (hcid.offmode == HCID_OFFMODE_DEVDOWN && scan_enable != SCAN_DISABLED))) { /* Start HCI device */ if (ioctl(dd, HCIDEVUP, adapter->dev_id) == 0) goto done; /* on success */ if (errno != EALREADY) { err = errno; error("Can't init device hci%d: %s (%d)\n", adapter->dev_id, strerror(errno), errno); hci_close_dev(dd); return error_failed_errno(conn, msg, err); } } if (adapter->up && scan_enable == SCAN_DISABLED && hcid.offmode == HCID_OFFMODE_DEVDOWN) { if (ioctl(dd, HCIDEVDOWN, adapter->dev_id) < 0) { hci_close_dev(dd); return error_failed_errno(conn, msg, errno); } goto done; } limited = (new_mode == MODE_LIMITED ? TRUE : FALSE); err = set_limited_discoverable(dd, adapter->class, limited); if (err < 0) { hci_close_dev(dd); return error_failed_errno(conn, msg, -err); } if (current_scan != scan_enable) { struct hci_request rq; uint8_t status = 0; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_SCAN_ENABLE; rq.cparam = &scan_enable; rq.clen = sizeof(scan_enable); rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, 1000) < 0) { err = errno; error("Sending write scan enable command failed: %s (%d)", strerror(errno), errno); hci_close_dev(dd); return error_failed_errno(conn, msg, err); } if (status) { error("Setting scan enable failed with status 0x%02x", status); hci_close_dev(dd); return error_failed_errno(conn, msg, bt_error(status)); } } else { /* discoverable or limited */ if ((scan_enable & SCAN_INQUIRY) && (new_mode != adapter->mode)) { dbus_connection_emit_signal(conn, dbus_message_get_path(msg), ADAPTER_INTERFACE, "ModeChanged", DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if (adapter->timeout_id) g_source_remove(adapter->timeout_id); if (adapter->discov_timeout != 0) adapter->timeout_id = g_timeout_add(adapter->discov_timeout * 1000, discov_timeout_handler, adapter); } }done: str2ba(adapter->address, &local); write_device_mode(&local, mode); hci_close_dev(dd); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; adapter->mode = new_mode; return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_discoverable_to(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; 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_UINT32, &adapter->discov_timeout, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_set_discoverable_to(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; uint32_t timeout; bdaddr_t bdaddr; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &timeout, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; if (adapter->timeout_id) { g_source_remove(adapter->timeout_id); adapter->timeout_id = 0; } if ((timeout != 0) && (adapter->scan_enable & SCAN_INQUIRY)) adapter->timeout_id = g_timeout_add(timeout * 1000, discov_timeout_handler, adapter); adapter->discov_timeout = timeout; str2ba(adapter->address, &bdaddr); write_discoverable_timeout(&bdaddr, timeout); dbus_connection_emit_signal(conn, dbus_message_get_path(msg), ADAPTER_INTERFACE, "DiscoverableTimeoutChanged", DBUS_TYPE_UINT32, &timeout, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_is_connectable(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; DBusMessage *reply; const uint8_t scan_enable = adapter->scan_enable; dbus_bool_t connectable = FALSE; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); if (scan_enable & SCAN_PAGE) connectable = TRUE; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connectable, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_is_discoverable(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; DBusMessage *reply; const uint8_t scan_enable = adapter->scan_enable; dbus_bool_t discoverable = FALSE; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); if (scan_enable & SCAN_INQUIRY) discoverable = TRUE; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &discoverable, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_is_connected(DBusConnection *conn, DBusMessage *msg, void *data){ DBusMessage *reply; dbus_bool_t connected = FALSE; struct adapter *adapter = data; GSList *l = adapter->active_conn; const char *peer_addr; bdaddr_t peer_bdaddr; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg, NULL); str2ba(peer_addr, &peer_bdaddr); l = g_slist_find_custom(l, &peer_bdaddr, active_conn_find_by_bdaddr); if (l) connected = TRUE; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_list_connections(DBusConnection *conn, DBusMessage *msg, void *data){ DBusMessage *reply; DBusMessageIter iter; DBusMessageIter array_iter; struct adapter *adapter = data; GSList *l = adapter->active_conn; 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); while (l) { char peer_addr[18]; const char *paddr = peer_addr; struct active_conn_info *dev = l->data; ba2str(&dev->bdaddr, peer_addr); dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &paddr); l = l->next; } dbus_message_iter_close_container(&iter, &array_iter); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_major_class(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; DBusMessage *reply; const char *str_ptr = "computer"; 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; /* FIXME: Currently, only computer major class is supported */ if ((adapter->class[1] & 0x1f) != 1) return error_unsupported_major_class(conn, msg); dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_list_minor_classes(DBusConnection *conn, DBusMessage *msg, void *data){ const struct adapter *adapter = data; DBusMessage *reply = NULL; DBusMessageIter iter; DBusMessageIter array_iter; const char **minor_ptr; uint8_t major_class; int size, i; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); major_class = adapter->class[1] & 0x1F; switch (major_class) { case 1: /* computer */ minor_ptr = computer_minor_cls; size = sizeof(computer_minor_cls) / sizeof(*computer_minor_cls); break; case 2: /* phone */ minor_ptr = phone_minor_cls; size = sizeof(phone_minor_cls) / sizeof(*phone_minor_cls); break; default: return error_unsupported_major_class(conn, msg); } 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 < size; i++) dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &minor_ptr[i]); dbus_message_iter_close_container(&iter, &array_iter); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_minor_class(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; const char *str_ptr = ""; uint8_t minor_class; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); /* FIXME: Currently, only computer major class is supported */ if ((adapter->class[1] & 0x1f) != 1) return error_unsupported_major_class(conn, msg); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; minor_class = adapter->class[0] >> 2; /* Validate computer minor class */ if (minor_class > (sizeof(computer_minor_cls) / sizeof(*computer_minor_cls))) goto failed; str_ptr = computer_minor_cls[minor_class];failed: dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_set_minor_class(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; const char *minor; uint32_t dev_class = 0xFFFFFFFF; int i, dd; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &minor, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (!minor) return error_invalid_arguments(conn, msg, NULL); dd = hci_open_dev(adapter->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); /* Currently, only computer major class is supported */ if ((adapter->class[1] & 0x1f) != 1) { hci_close_dev(dd); return error_unsupported_major_class(conn, msg); } for (i = 0; i < sizeof(computer_minor_cls) / sizeof(*computer_minor_cls); i++) if (!strcasecmp(minor, computer_minor_cls[i])) { /* Remove the format type */ dev_class = i << 2; break; } /* Check if it's a valid minor class */ if (dev_class == 0xFFFFFFFF) { hci_close_dev(dd); return error_invalid_arguments(conn, msg, NULL); } /* set the service class and major class */ dev_class |= (adapter->class[2] << 16) | (adapter->class[1] << 8); if (hci_write_class_of_dev(dd, dev_class, 2000) < 0) { int err = errno; error("Can't write class of device on hci%d: %s(%d)", adapter->dev_id, strerror(errno), errno); hci_close_dev(dd); return error_failed_errno(conn, msg, err); } dbus_connection_emit_signal(conn, dbus_message_get_path(msg), ADAPTER_INTERFACE, "MinorClassChanged", DBUS_TYPE_STRING, &minor, DBUS_TYPE_INVALID); reply = dbus_message_new_method_return(msg); hci_close_dev(dd); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_service_classes(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; DBusMessageIter iter; DBusMessageIter array_iter; const char *str_ptr; int i; if (!adapter->up) return error_not_ready(conn, msg); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -