From 277e0363f2839a05b80c1bc4263cfeaf9909be8c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 23 May 2007 18:32:16 +0000 Subject: Added device class tracking --- hcid/dbus-adapter.c | 112 ++++++++-------------------------------------------- hcid/dbus-adapter.h | 1 + hcid/dbus-api.txt | 13 ++---- hcid/dbus-hci.c | 49 ++++++++++++++++++++++- hcid/dbus-hci.h | 1 + hcid/device.c | 27 +++++++++++-- hcid/hcid.h | 1 + hcid/security.c | 3 ++ 8 files changed, 98 insertions(+), 109 deletions(-) diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 27f7b1c8..ba8d1d90 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -768,8 +768,6 @@ static DBusHandlerResult adapter_get_major_class(DBusConnection *conn, const struct adapter *adapter = data; DBusMessage *reply; const char *str_ptr = "computer"; - uint8_t cls[3]; - int dd; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg); @@ -778,22 +776,8 @@ static DBusHandlerResult adapter_get_major_class(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dd = hci_open_dev(adapter->dev_id); - if (dd < 0) - return error_no_such_adapter(conn, msg); - - if (hci_read_class_of_dev(dd, cls, 1000) < 0) { - int err = errno; - error("Can't read class of device on hci%d: %s(%d)", - adapter->dev_id, strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, err); - } - - hci_close_dev(dd); - /* FIXME: Currently, only computer major class is supported */ - if ((cls[1] & 0x1f) != 1) + if ((adapter->class[1] & 0x1f) != 1) return error_unsupported_major_class(conn, msg); dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, @@ -810,31 +794,13 @@ static DBusHandlerResult adapter_list_minor_classes(DBusConnection *conn, DBusMessageIter iter; DBusMessageIter array_iter; const char **minor_ptr; - uint8_t cls[3]; uint8_t major_class; - int dd, size, i; - - if (!adapter->up) - return error_not_ready(conn, msg); + int size, i; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg); - dd = hci_open_dev(adapter->dev_id); - if (dd < 0) - return error_no_such_adapter(conn, msg); - - if (hci_read_class_of_dev(dd, cls, 1000) < 0) { - int err = errno; - error("Can't read class of device on hci%d: %s(%d)", - adapter->dev_id, strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, err); - } - - hci_close_dev(dd); - - major_class = cls[1] & 0x1F; + major_class = adapter->class[1] & 0x1F; switch (major_class) { case 1: /* computer */ @@ -871,39 +837,20 @@ static DBusHandlerResult adapter_get_minor_class(DBusConnection *conn, struct adapter *adapter = data; DBusMessage *reply; const char *str_ptr = ""; - uint8_t cls[3]; uint8_t minor_class; - int dd; - - 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); - dd = hci_open_dev(adapter->dev_id); - if (dd < 0) - return error_no_such_adapter(conn, msg); - - if (hci_read_class_of_dev(dd, cls, 1000) < 0) { - int err = errno; - error("Can't read class of device on hci%d: %s(%d)", - adapter->dev_id, strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, err); - } - - hci_close_dev(dd); - /* FIXME: Currently, only computer major class is supported */ - if ((cls[1] & 0x1f) != 1) + 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 = cls[0] >> 2; + minor_class = adapter->class[0] >> 2; /* Validate computer minor class */ if (minor_class > (sizeof(computer_minor_cls) / sizeof(*computer_minor_cls))) @@ -923,9 +870,7 @@ static DBusHandlerResult adapter_set_minor_class(DBusConnection *conn, { struct adapter *adapter = data; DBusMessage *reply; - bdaddr_t bdaddr; const char *minor; - uint8_t cls[3]; uint32_t dev_class = 0xFFFFFFFF; int i, dd; @@ -944,18 +889,11 @@ static DBusHandlerResult adapter_set_minor_class(DBusConnection *conn, if (dd < 0) return error_no_such_adapter(conn, msg); - if (hci_read_class_of_dev(dd, cls, 1000) < 0) { - int err = errno; - error("Can't read class of device on hci%d: %s(%d)", - adapter->dev_id, strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, err); - } - /* Currently, only computer major class is supported */ - if ((cls[1] & 0x1f) != 1) + 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 */ @@ -964,18 +902,13 @@ static DBusHandlerResult adapter_set_minor_class(DBusConnection *conn, } /* Check if it's a valid minor class */ - if (dev_class == 0xFFFFFFFF) + if (dev_class == 0xFFFFFFFF) { + hci_close_dev(dd); return error_invalid_arguments(conn, msg); - - /* update the minor class before store */ - cls[0] = (dev_class & 0xff); + } /* set the service class and major class */ - dev_class |= (cls[2] << 16) | (cls[1] << 8); - - hci_devba(adapter->dev_id, &bdaddr); - - write_local_class(&bdaddr, cls); + dev_class |= (adapter->class[2] << 16) | (adapter->class[1] << 8); if (hci_write_class_of_dev(dd, dev_class, 2000) < 0) { int err = errno; @@ -1006,8 +939,7 @@ static DBusHandlerResult adapter_get_service_classes(DBusConnection *conn, DBusMessageIter iter; DBusMessageIter array_iter; const char *str_ptr; - uint8_t cls[3]; - int dd, i; + int i; if (!adapter->up) return error_not_ready(conn, msg); @@ -1015,19 +947,9 @@ static DBusHandlerResult adapter_get_service_classes(DBusConnection *conn, if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg); - dd = hci_open_dev(adapter->dev_id); - if (dd < 0) - return error_no_such_adapter(conn, msg); - - if (hci_read_class_of_dev(dd, cls, 1000) < 0) { - int err = errno; - error("Can't read class of device on hci%d: %s(%d)", - adapter->dev_id, strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, err); - } - reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_iter_init_append(reply, &iter); @@ -1035,7 +957,7 @@ static DBusHandlerResult adapter_get_service_classes(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING, &array_iter); for (i = 0; i < (sizeof(service_cls) / sizeof(*service_cls)); i++) { - if (cls[2] & (1 << i)) { + if (adapter->class[2] & (1 << i)) { str_ptr = service_cls[i]; dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &str_ptr); @@ -1044,8 +966,6 @@ static DBusHandlerResult adapter_get_service_classes(DBusConnection *conn, dbus_message_iter_close_container(&iter, &array_iter); - hci_close_dev(dd); - return send_message_and_unref(conn, reply); } diff --git a/hcid/dbus-adapter.h b/hcid/dbus-adapter.h index 6086787c..2c75c5dc 100644 --- a/hcid/dbus-adapter.h +++ b/hcid/dbus-adapter.h @@ -91,6 +91,7 @@ struct adapter { guint timeout_id; /* discoverable timeout id */ uint32_t discov_timeout; /* discoverable time(msec) */ uint8_t mode; /* scan mode */ + uint8_t class[3]; /* device class */ int discov_active; /* standard discovery active: includes name resolution step */ int pdiscov_active; /* periodic discovery active */ int pinq_idle; /* tracks the idle time for periodic inquiry */ diff --git a/hcid/dbus-api.txt b/hcid/dbus-api.txt index 7f1ed3b6..9fc19578 100644 --- a/hcid/dbus-api.txt +++ b/hcid/dbus-api.txt @@ -434,9 +434,8 @@ Methods dict GetInfo() For the other values, unsupported major class error is returned. - Possible errors: org.bluez.Error.NoSuchAdapter + Possible errors: org.bluez.Error.InvalidArguments org.bluez.Error.UnsupportedMajorClass - org.bluez.Error.Failed array{string} ListAvailableMinorClasses() @@ -448,9 +447,7 @@ Methods dict GetInfo() If the major class is not "computer" an error should be returned. - Possible errors: org.bluez.Error.NotReady - org.bluez.Error.NoSuchAdapter - org.bluez.Error.Failed + Possible errors: org.bluez.Error.InvalidArguments org.bluez.Error.UnsupportedMajorClass string GetMinorClass() @@ -466,10 +463,8 @@ Methods dict GetInfo() The default value is "uncategorized". - Possible errors: org.bluez.Error.NotReady - org.bluez.Error.NoSuchAdapter - org.bluez.Error.Failed - org.bluez.Error.UnsupportedMajorClass + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.UnsupportedMajorClass void SetMinorClass(string minor) diff --git a/hcid/dbus-hci.c b/hcid/dbus-hci.c index c0e3b5f3..242d8e3d 100644 --- a/hcid/dbus-hci.c +++ b/hcid/dbus-hci.c @@ -586,8 +586,11 @@ int hcid_dbus_start_device(uint16_t id) if (err < 0) goto failed; - adapter_mode_changed(adapter, path, mode); + err = get_device_class(adapter->dev_id, adapter->class); + if (err < 0) + goto failed; + adapter_mode_changed(adapter, path, mode); /* * retrieve the active connections: address the scenario where * the are active connections before the daemon've started @@ -1838,6 +1841,50 @@ failed: bt_free(local_addr); } +void hcid_dbus_write_class_complete(bdaddr_t *local) +{ + struct adapter *adapter; + char path[MAX_PATH_LENGTH]; + char *local_addr; + bdaddr_t tmp; + int id, dd = -1; + uint8_t cls[3]; + + baswap(&tmp, local); local_addr = batostr(&tmp); + id = hci_devid(local_addr); + if (id < 0) { + error("No matching device id for %s", local_addr); + goto failed; + } + + snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); + if (!dbus_connection_get_object_user_data(connection, path, + (void *) &adapter)) { + error("Getting %s path data failed!", path); + goto failed; + } + + dd = hci_open_dev(id); + if (dd < 0) { + error("HCI device open failed: hci%d", id); + goto failed; + } + + if (hci_read_class_of_dev(dd, cls, 1000) < 0) { + error("Can't read class of device on hci%d: %s(%d)", + id, strerror(errno), errno); + goto failed; + } + + write_local_class(local, cls); + memcpy(adapter->class, cls, 3); +failed: + if (dd >= 0) + hci_close_dev(dd); + + bt_free(local_addr); +} + void hcid_dbus_pin_code_reply(bdaddr_t *local, void *ptr) { diff --git a/hcid/dbus-hci.h b/hcid/dbus-hci.h index 5a7f9628..eb81415f 100644 --- a/hcid/dbus-hci.h +++ b/hcid/dbus-hci.h @@ -49,6 +49,7 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t status); void hcid_dbus_setname_complete(bdaddr_t *local); void hcid_dbus_setscan_enable_complete(bdaddr_t *local); +void hcid_dbus_write_class_complete(bdaddr_t *local); void hcid_dbus_pin_code_reply(bdaddr_t *local, void *ptr); int unregister_adapter_path(const char *path); diff --git a/hcid/device.c b/hcid/device.c index 4d2239ec..920a4dad 100644 --- a/hcid/device.c +++ b/hcid/device.c @@ -81,6 +81,7 @@ struct hci_dev { uint16_t manufacturer; uint8_t name[248]; + uint8_t class[3]; struct hci_peer *peers; struct hci_conn *conns; @@ -203,7 +204,7 @@ int start_device(uint16_t dev_id) struct hci_dev *dev; struct hci_version ver; uint8_t features[8], inqmode; - int dd; + int dd, err; ASSERT_DEV_ID; @@ -233,15 +234,23 @@ int start_device(uint16_t dev_id) dev->manufacturer = ver.manufacturer; if (hci_read_local_features(dd, features, 1000) < 0) { - int err = errno; + err = errno; error("Can't read features for hci%d: %s (%d)", - dev_id, strerror(errno), errno); + dev_id, strerror(err), err); hci_close_dev(dd); return -err; } memcpy(dev->features, features, 8); + if (hci_read_class_of_dev(dd, dev->class, 1000) < 0) { + err = errno; + error("Can't read class of device on hci%d: %s(%d)", + dev_id, strerror(err), err); + hci_close_dev(dd); + return -err; + } + inqmode = get_inquiry_mode(dev); if (inqmode < 1) goto done; @@ -285,6 +294,18 @@ int get_device_address(uint16_t dev_id, char *address, size_t size) return ba2str(&dev->bdaddr, address); } +int get_device_class(uint16_t dev_id, uint8_t *cls) +{ + struct hci_dev *dev; + + ASSERT_DEV_ID; + + dev = &devices[dev_id]; + memcpy(cls, dev->class, 3); + + return 0; +} + int get_device_version(uint16_t dev_id, char *version, size_t size) { struct hci_dev *dev; diff --git a/hcid/hcid.h b/hcid/hcid.h index 86b21639..50451a6b 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -157,6 +157,7 @@ int start_device(uint16_t dev_id); int stop_device(uint16_t dev_id); int get_device_address(uint16_t dev_id, char *address, size_t size); +int get_device_class(uint16_t dev_id, uint8_t *class); int get_device_version(uint16_t dev_id, char *version, size_t size); int get_device_revision(uint16_t dev_id, char *revision, size_t size); int get_device_manufacturer(uint16_t dev_id, char *manufacturer, size_t size); diff --git a/hcid/security.c b/hcid/security.c index 77062dbd..3f72f5cd 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -436,6 +436,9 @@ static inline void cmd_complete(int dev, bdaddr_t *sba, void *ptr) case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): hcid_dbus_setscan_enable_complete(sba); break; + case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV): + hcid_dbus_write_class_complete(sba); + break; case cmd_opcode_pack(OGF_LINK_CTL, OCF_PIN_CODE_REPLY): case cmd_opcode_pack(OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY): hcid_dbus_pin_code_reply(sba, ptr); -- cgit