// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_CHROMEOS_BLUETOOTH_BLUETOOTH_DEVICE_H_ #define CHROME_BROWSER_CHROMEOS_BLUETOOTH_BLUETOOTH_DEVICE_H_ #pragma once #include #include #include "base/basictypes.h" #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/string16.h" #include "chromeos/dbus/bluetooth_agent_service_provider.h" #include "chromeos/dbus/bluetooth_device_client.h" #include "chromeos/dbus/bluetooth_out_of_band_client.h" #include "dbus/object_path.h" namespace chromeos { class BluetoothAdapter; class BluetoothServiceRecord; class BluetoothSocket; // The BluetoothDevice class represents a remote Bluetooth device, both // its properties and capabilities as discovered by a local adapter and // actions that may be performed on the remove device such as pairing, // connection and disconnection. // // The class is instantiated and managed by the BluetoothAdapter class // and pointers should only be obtained from that class and not cached, // instead use the address() method as a unique key for a device. // // Since the lifecycle of BluetoothDevice instances is managed by // BluetoothAdapter, that class rather than this provides observer methods // for devices coming and going, as well as properties being updated. class BluetoothDevice : private BluetoothDeviceClient::Observer, private BluetoothAgentServiceProvider::Delegate { public: // Possible values that may be returned by GetDeviceType(), representing // different types of bluetooth device that we support or are aware of // decoded from the bluetooth class information. enum DeviceType { DEVICE_UNKNOWN, DEVICE_COMPUTER, DEVICE_PHONE, DEVICE_MODEM, DEVICE_PERIPHERAL, DEVICE_JOYSTICK, DEVICE_GAMEPAD, DEVICE_KEYBOARD, DEVICE_MOUSE, DEVICE_TABLET, DEVICE_KEYBOARD_MOUSE_COMBO }; // Interface for observing changes from bluetooth devices. class Observer { public: virtual ~Observer() {} // TODO(keybuk): add observers for pairing and connection. }; // Interface for negotiating pairing of bluetooth devices. class PairingDelegate { public: virtual ~PairingDelegate() {} // This method will be called when the Bluetooth daemon requires a // PIN Code for authentication of the device |device|, the delegate should // obtain the code from the user and call SetPinCode() on the device to // provide it, or RejectPairing() or CancelPairing() to reject or cancel // the request. // // PIN Codes are generally required for Bluetooth 2.0 and earlier devices // for which there is no automatic pairing or special handling. virtual void RequestPinCode(BluetoothDevice* device) = 0; // This method will be called when the Bluetooth daemon requires a // Passkey for authentication of the device |device|, the delegate should // obtain the passkey from the user (a numeric in the range 0-999999) and // call SetPasskey() on the device to provide it, or RejectPairing() or // CancelPairing() to reject or cancel the request. // // Passkeys are generally required for Bluetooth 2.1 and later devices // which cannot provide input or display on their own, and don't accept // passkey-less pairing. virtual void RequestPasskey(BluetoothDevice* device) = 0; // This method will be called when the Bluetooth daemon requires that the // user enter the PIN code |pincode| into the device |device| so that it // may be authenticated. The DismissDisplayOrConfirm() method // will be called to dismiss the display once pairing is complete or // cancelled. // // This is used for Bluetooth 2.0 and earlier keyboard devices, the // |pincode| will always be a six-digit numeric in the range 000000-999999 // for compatibilty with later specifications. virtual void DisplayPinCode(BluetoothDevice* device, const std::string& pincode) = 0; // This method will be called when the Bluetooth daemon requires that the // user enter the Passkey |passkey| into the device |device| so that it // may be authenticated. The DismissDisplayOrConfirm() method will be // called to dismiss the display once pairing is complete or cancelled. // // This is used for Bluetooth 2.1 and later devices that support input // but not display, such as keyboards. The Passkey is a numeric in the // range 0-999999 and should be always presented zero-padded to six // digits. virtual void DisplayPasskey(BluetoothDevice* device, uint32 passkey) = 0; // This method will be called when the Bluetooth daemon requires that the // user confirm that the Passkey |passkey| is displayed on the screen // of the device |device| so that it may be authenticated. The delegate // should display to the user and ask for confirmation, then call // ConfirmPairing() on the device to confirm, RejectPairing() on the device // to reject or CancelPairing() on the device to cancel authentication // for any other reason. // // This is used for Bluetooth 2.1 and later devices that support display, // such as other computers or phones. The Passkey is a numeric in the // range 0-999999 and should be always present zero-padded to six // digits. virtual void ConfirmPasskey(BluetoothDevice* device, uint32 passkey) = 0; // This method will be called when any previous DisplayPinCode(), // DisplayPasskey() or ConfirmPasskey() request should be concluded // and removed from the user. virtual void DismissDisplayOrConfirm() = 0; }; virtual ~BluetoothDevice(); // Returns the Bluetooth of address the device. This should be used as // a unique key to identify the device and copied where needed. virtual const std::string& address() const; // Returns the name of the device suitable for displaying, this may // be a synthesied string containing the address and localized type name // if the device has no obtained name. virtual string16 GetName() const; // Returns the type of the device, limited to those we support or are // aware of, by decoding the bluetooth class information. The returned // values are unique, and do not overlap, so DEVICE_KEYBOARD is not also // DEVICE_PERIPHERAL. DeviceType GetDeviceType() const; // Returns a localized string containing the device's bluetooth address and // a device type for display when |name_| is empty. string16 GetAddressWithLocalizedDeviceTypeName() const; // Indicates whether the class of this device is supported by Chrome OS. bool IsSupported() const; // Indicates whether the device is paired to the adapter, whether or not // that pairing is permanent or temporary. virtual bool IsPaired() const; // Indicates whether the device is bonded to the adapter, bonding is // formed by pairing and exchanging high-security link keys so that // connections may be encrypted. virtual bool IsBonded() const; // Indicates whether the device is currently connected to the adapter // and at least one service available for use. virtual bool IsConnected() const; // Returns the services (as UUID strings) that this device provides. typedef std::vector ServiceList; const ServiceList& GetServices() const { return service_uuids_; } // The ErrorCallback is used for methods that can fail in which case it // is called, in the success case the callback is simply not called. typedef base::Callback ErrorCallback; // Returns the services (as BluetoothServiceRecord objects) that this device // provides. typedef ScopedVector ServiceRecordList; typedef base::Callback ServiceRecordsCallback; void GetServiceRecords(const ServiceRecordsCallback& callback, const ErrorCallback& error_callback); // Indicates whether this device provides the given service. virtual bool ProvidesServiceWithUUID(const std::string& uuid) const; // The ProvidesServiceCallback is used by ProvidesServiceWithName to indicate // whether or not a matching service was found. typedef base::Callback ProvidesServiceCallback; // Indicates whether this device provides the given service. void ProvidesServiceWithName(const std::string& name, const ProvidesServiceCallback& callback); // Indicates whether the device is currently pairing and expecting a // PIN Code to be returned. bool ExpectingPinCode() const { return !pincode_callback_.is_null(); } // Indicates whether the device is currently pairing and expecting a // Passkey to be returned. bool ExpectingPasskey() const { return !passkey_callback_.is_null(); } // Indicates whether the device is currently pairing and expecting // confirmation of a displayed passkey. bool ExpectingConfirmation() const { return !confirmation_callback_.is_null(); } // The VoidResultCallback is used for methods that do not return any data, to // indicate that the action requested is complete. typedef base::Callback VoidResultCallback; // Initiates a connection to the device, pairing first if necessary. // // Method calls will be made on the supplied object |pairing_delegate| // to indicate what display, and in response should make method calls // back to the device object. Not all devices require user responses // during pairing, so it is normal for |pairing_delegate| to receive no // calls. To explicitly force a low-security connection without bonding, // pass NULL, though this is ignored if the device is already paired. // // If the request fails, |error_callback| will be called; otherwise, // |callback| is called when the request is complete. void Connect(PairingDelegate* pairing_delegate, const base::Closure& callback, const ErrorCallback& error_callback); // Sends the PIN code |pincode| to the remote device during pairing. // // PIN Codes are generally required for Bluetooth 2.0 and earlier devices // for which there is no automatic pairing or special handling. void SetPinCode(const std::string& pincode); // Sends the Passkey |passkey| to the remote device during pairing. // // Passkeys are generally required for Bluetooth 2.1 and later devices // which cannot provide input or display on their own, and don't accept // passkey-less pairing, and are a numeric in the range 0-999999. void SetPasskey(uint32 passkey); // Confirms to the remote device during pairing that a passkey provided by // the ConfirmPasskey() delegate call is displayed on both devices. void ConfirmPairing(); // Rejects a pairing or connection request from a remote device. void RejectPairing(); // Cancels a pairing or connection attempt to a remote device. void CancelPairing(); // Disconnects the device, terminating the low-level ACL connection // and any application connections using it. Link keys and other pairing // information are not discarded, and the device object is not deleted. // If the request fails, |error_callback| will be called; otherwise, // |callback| is called when the request is complete. void Disconnect(const base::Closure& callback, const ErrorCallback& error_callback); // Disconnects the device, terminating the low-level ACL connection // and any application connections using it, and then discards link keys // and other pairing information. The device object remainds valid until // returing from the calling function, after which it should be assumed to // have been deleted. If the request fails, |error_callback| will be called. // There is no callback for success beause this object is often deleted // before that callback would be called. void Forget(const ErrorCallback& error_callback); // SocketCallback is used by ConnectToService to return a BluetoothSocket // to the caller, or NULL if there was an error. The socket will remain open // until the last reference to the returned BluetoothSocket is released. typedef base::Callback)> SocketCallback; // Attempts to open a socket to a service matching |uuid| on this device. If // the connection is successful, |callback| is called with a BluetoothSocket. // Otherwise |callback| is called with NULL. The socket is closed as soon as // all references to the BluetoothSocket are released. Note that the // BluetoothSocket object can outlive both this BluetoothDevice and the // BluetoothAdapter for this device. void ConnectToService(const std::string& service_uuid, const SocketCallback& callback); // Sets the Out Of Band pairing data for this device to |data|. Exactly one // of |callback| or |error_callback| will be run. virtual void SetOutOfBandPairingData( const chromeos::BluetoothOutOfBandPairingData& data, const base::Closure& callback, const ErrorCallback& error_callback); // Clears the Out Of Band pairing data for this device. Exactly one of // |callback| or |error_callback| will be run. virtual void ClearOutOfBandPairingData( const base::Closure& callback, const ErrorCallback& error_callback); private: friend class BluetoothAdapter; friend class MockBluetoothDevice; explicit BluetoothDevice(BluetoothAdapter* adapter); // Sets the dbus object path for the device to |object_path|, indicating // that the device has gone from being discovered to paired or bonded. void SetObjectPath(const dbus::ObjectPath& object_path); // Updates device information from the properties in |properties|, device // state properties such as |paired_| and |connected_| are ignored unless // |update_state| is true. void Update(const BluetoothDeviceClient::Properties* properties, bool update_state); // Called by BluetoothAdapterClient when a call to CreateDevice() or // CreatePairedDevice() succeeds, provides the new object path for the remote // device in |device_path|. |callback| and |error_callback| are the callbacks // provided to Connect(). void ConnectCallback(const base::Closure& callback, const ErrorCallback& error_callback, const dbus::ObjectPath& device_path); // Called by BluetoothAdapterClient when a call to CreateDevice() or // CreatePairedDevice() fails with the error named |error_name| and // optional message |error_message|, |error_callback| is the callback // provided to Connect(). void ConnectErrorCallback(const ErrorCallback& error_callback, const std::string& error_name, const std::string& error_message); // Called by BluetoothAdapterClient when a call to DiscoverServices() // completes. |callback| and |error_callback| are the callbacks provided to // GetServiceRecords. void CollectServiceRecordsCallback( const ServiceRecordsCallback& callback, const ErrorCallback& error_callback, const dbus::ObjectPath& device_path, const BluetoothDeviceClient::ServiceMap& service_map, bool success); // Called by BluetoothProperty when the call to Set() for the Trusted // property completes. |success| indicates whether or not the request // succeeded, |callback| and |error_callback| are the callbacks provided to // Connect(). void OnSetTrusted(const base::Closure& callback, const ErrorCallback& error_callback, bool success); // Connect application-level protocols of the device to the system, called // on a successful connection or to reconnect to a device that is already // paired or previously connected. |error_callback| is called on failure. // Otherwise, |callback| is called when the request is complete. void ConnectApplications(const base::Closure& callback, const ErrorCallback& error_callback); // Called by IntrospectableClient when a call to Introspect() completes. // |success| indicates whether or not the request succeeded, |callback| and // |error_callback| are the callbacks provided to ConnectApplications(), // |service_name| and |device_path| specify the remote object being // introspected and |xml_data| contains the XML-formatted protocol data. void OnIntrospect(const base::Closure& callback, const ErrorCallback& error_callback, const std::string& service_name, const dbus::ObjectPath& device_path, const std::string& xml_data, bool success); // Called by BluetoothInputClient when the call to Connect() succeeds. // |error_callback| is the callback provided to ConnectApplications(), // |interface_name| specifies the interface being connected and // |device_path| the remote object path. void OnConnect(const base::Closure& callback, const std::string& interface_name, const dbus::ObjectPath& device_path); // Called by BluetoothInputClient when the call to Connect() fails. // |error_callback| is the callback provided to ConnectApplications(), // |interface_name| specifies the interface being connected, // |device_path| the remote object path, // |error_name| the error name and |error_message| the optional message. void OnConnectError(const ErrorCallback& error_callback, const std::string& interface_name, const dbus::ObjectPath& device_path, const std::string& error_name, const std::string& error_message); // Called by BluetoothDeviceClient when a call to Disconnect() completes, // |success| indicates whether or not the request succeeded, |callback| and // |error_callback| are the callbacks provided to Disconnect() and // |device_path| is the device disconnected. void DisconnectCallback(const base::Closure& callback, const ErrorCallback& error_callback, const dbus::ObjectPath& device_path, bool success); // Called by BluetoothAdapterClient when a call to RemoveDevice() completes, // |success| indicates whether or not the request succeeded, |error_callback| // is the callback provided to Forget() and |adapter_path| is the d-bus // object path of the adapter that performed the removal. void ForgetCallback(const ErrorCallback& error_callback, const dbus::ObjectPath& adapter_path, bool success); // Called by BluetoothDeviceClient when a call to DiscoverServices() that was // initated from ProvidesServiceWithName completes. The |result_callback| is // called with true if a service with name matching |name| is discovered, or // with false otherwise. The rest of the parameters are as documented for a // BluetoothDeviceClient::ServicesCallback. void SearchServicesForNameCallback( const std::string& name, const ProvidesServiceCallback& callback, const dbus::ObjectPath& object_path, const BluetoothDeviceClient::ServiceMap& service_map, bool success); // Called by BluetoothDeviceClient when a call to DiscoverServices() that was // initated from ConnectToService completes. The |callback| is called with // true iff a connection was successfully established. The rest of the // parameters are as documented for a BluetoothDeviceClient::ServicesCallback. void ConnectToMatchingService( const std::string& service_uuid, const SocketCallback& callback, const dbus::ObjectPath& object_path, const BluetoothDeviceClient::ServiceMap& service_map, bool success); // Called by BlueoothDeviceClient in response to the AddRemoteData and // RemoveRemoteData method calls. void OnRemoteDataCallback(const base::Closure& callback, const ErrorCallback& error_callback, bool success); // BluetoothDeviceClient::Observer override. // // Called when the device with object path |object_path| is about // to be disconnected, giving a chance for application layers to // shut down cleanly. virtual void DisconnectRequested( const dbus::ObjectPath& object_path) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the agent is unregistered from the // Bluetooth daemon, generally at the end of a pairing request. It may be // used to perform cleanup tasks. virtual void Release() OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires a // PIN Code for authentication of the device with object path |device_path|, // the agent should obtain the code from the user and call |callback| // to provide it, or indicate rejection or cancellation of the request. // // PIN Codes are generally required for Bluetooth 2.0 and earlier devices // for which there is no automatic pairing or special handling. virtual void RequestPinCode(const dbus::ObjectPath& device_path, const PinCodeCallback& callback) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires a // Passkey for authentication of the device with object path |device_path|, // the agent should obtain the passkey from the user (a numeric in the // range 0-999999) and call |callback| to provide it, or indicate // rejection or cancellation of the request. // // Passkeys are generally required for Bluetooth 2.1 and later devices // which cannot provide input or display on their own, and don't accept // passkey-less pairing. virtual void RequestPasskey(const dbus::ObjectPath& device_path, const PasskeyCallback& callback) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires that the // user enter the PIN code |pincode| into the device with object path // |device_path| so that it may be authenticated. The Cancel() method // will be called to dismiss the display once pairing is complete or // cancelled. // // This is used for Bluetooth 2.0 and earlier keyboard devices, the // |pincode| will always be a six-digit numeric in the range 000000-999999 // for compatibilty with later specifications. virtual void DisplayPinCode(const dbus::ObjectPath& device_path, const std::string& pincode) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires that the // user enter the Passkey |passkey| into the device with object path // |device_path| so that it may be authenticated. The Cancel() method // will be called to dismiss the display once pairing is complete or // cancelled. // // This is used for Bluetooth 2.1 and later devices that support input // but not display, such as keyboards. The Passkey is a numeric in the // range 0-999999 and should be always presented zero-padded to six // digits. virtual void DisplayPasskey(const dbus::ObjectPath& device_path, uint32 passkey) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires that the // user confirm that the Passkey |passkey| is displayed on the screen // of the device with object path |object_path| so that it may be // authentication. The agent should display to the user and ask for // confirmation, then call |callback| to provide their response (success, // rejected or cancelled). // // This is used for Bluetooth 2.1 and later devices that support display, // such as other computers or phones. The Passkey is a numeric in the // range 0-999999 and should be always present zero-padded to six // digits. virtual void RequestConfirmation( const dbus::ObjectPath& device_path, uint32 passkey, const ConfirmationCallback& callback) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires that the // user confirm that the device with object path |object_path| is // authorized to connect to the service with UUID |uuid|. The agent should // confirm with the user and call |callback| to provide their response // (success, rejected or cancelled). virtual void Authorize(const dbus::ObjectPath& device_path, const std::string& uuid, const ConfirmationCallback& callback) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called when the Bluetooth daemon requires that the // user confirm that the device adapter may switch to mode |mode|. The // agent should confirm with the user and call |callback| to provide // their response (success, rejected or cancelled). virtual void ConfirmModeChange(Mode mode, const ConfirmationCallback& callback) OVERRIDE; // BluetoothAgentServiceProvider::Delegate override. // // This method will be called by the Bluetooth daemon to indicate that // the request failed before a reply was returned from the device. virtual void Cancel() OVERRIDE; // Creates a new BluetoothDevice object bound to the information of the // dbus object path |object_path| and the adapter |adapter|, representing // a paired device, with initial properties set from |properties|. static BluetoothDevice* CreateBound( BluetoothAdapter* adapter, const dbus::ObjectPath& object_path, const BluetoothDeviceClient::Properties* properties); // Creates a new BluetoothDevice object not bound to a dbus object path, // but bound to the adapter |adapter|, representing a discovered or unpaired // device, with initial properties set from |properties|. static BluetoothDevice* CreateUnbound( BluetoothAdapter* adapter, const BluetoothDeviceClient::Properties* properties); // Weak pointer factory for generating 'this' pointers that might live longer // than we do. base::WeakPtrFactory weak_ptr_factory_; // The adapter that owns this device instance. BluetoothAdapter* adapter_; // The dbus object path of the device, will be empty if the device has only // been discovered and not yet paired with. dbus::ObjectPath object_path_; // The Bluetooth address of the device. std::string address_; // The name of the device, as supplied by the remote device. std::string name_; // The Bluetooth class of the device, a bitmask that may be decoded using // https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm uint32 bluetooth_class_; // Tracked device state, updated by the adapter managing the lifecyle of // the device. bool bonded_; bool connected_; // The services (identified by UUIDs) that this device provides. std::vector service_uuids_; // During pairing this is set to an object that we don't own, but on which // we can make method calls to request, display or confirm PIN Codes and // Passkeys. Generally it is the object that owns this one. PairingDelegate* pairing_delegate_; // During pairing this is set to an instance of a D-Bus agent object // intialized with our own class as its delegate. scoped_ptr agent_; // During pairing these callbacks are set to those provided by method calls // made on us by |agent_| and are called by our own method calls such as // SetPinCode() and SetPasskey(). PinCodeCallback pincode_callback_; PasskeyCallback passkey_callback_; ConfirmationCallback confirmation_callback_; // Used to keep track of pending application connection requests. int connecting_applications_counter_; DISALLOW_COPY_AND_ASSIGN(BluetoothDevice); }; } // namespace chromeos #endif // CHROME_BROWSER_CHROMEOS_BLUETOOTH_BLUETOOTH_DEVICE_H_