[Bluetooth] Add BluetoothHidDevice APIs (#574)
authorWootak <nonsan1228@gmail.com>
Thu, 13 Dec 2018 00:45:27 +0000 (09:45 +0900)
committerGitHub <noreply@github.com>
Thu, 13 Dec 2018 00:45:27 +0000 (09:45 +0900)
[Bluetooth] Add BluetoothHidDevice APIs
- Interop
- BluetoothEnumerations
- BluetoothData
- BluetoothEventArgs

src/Tizen.Network.Bluetooth/Interop/Interop.Bluetooth.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothData.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothDevice.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEnumerations.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothError.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothEventArgs.cs
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDevice.cs [new file with mode: 0644]
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDeviceImpl.cs [new file with mode: 0644]
src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothStructs.cs

index d062b4e..9d2e737 100755 (executable)
@@ -62,9 +62,6 @@ internal static partial class Interop
         internal delegate void AudioConnectionStateChangedCallback(int result, bool connected, string deviceAddress, int profileType, IntPtr userData);
 
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void HidConnectionStateChangedCallback(int result, bool connected, string deviceAddress, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         internal delegate void ConnectionRequestedCallback(string deviceAddress, IntPtr userData);
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         internal delegate void PushRequestedCallback(string file, long size, IntPtr userData);
@@ -376,17 +373,42 @@ internal static partial class Interop
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_audio_unset_connection_state_changed_cb")]
         internal static extern int UnsetAudioConnectionStateChangedCallback();
 
-        //Bluetooth Hid
+        // Bluetooth Hid
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void HidConnectionStateChangedCallback(int result, bool connected, string deviceAddress, IntPtr userData);
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void HidDeviceConnectionStateChangedCallback(int result, bool connected, string deviceAddress, IntPtr userData);
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void HidDeviceDataReceivedCallback(ref BluetoothHidDeviceReceivedDataStruct receivedData, IntPtr userData);
+
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_host_initialize")]
         internal static extern int InitializeHid(HidConnectionStateChangedCallback hidConnectionChangedCb, IntPtr userData);
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_host_deinitialize")]
         internal static extern int DeinitializeHid();
-
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_host_connect")]
         internal static extern int Connect(string deviceAddress);
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_host_disconnect")]
         internal static extern int Disconnect(string deviceAddress);
 
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_activate")]
+        internal static extern int ActivateHidDevice(HidDeviceConnectionStateChangedCallback stateChangedCb, IntPtr userData);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_deactivate")]
+        internal static extern int DeactivateHidDevice();
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_connect")]
+        internal static extern int ConnectHidDevice(string deviceAddress);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_disconnect")]
+        internal static extern int DisconnectHidDevice(string deviceAddress);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_send_mouse_event")]
+        internal static extern int SendHidDeviceMouseEvent(string deviceAddress, BluetoothHidMouseData mouseData);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_send_key_event")]
+        internal static extern int SendHidDeviceKeyEvent(string deviceAddress, BluetoothHidKeyData keyData);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_set_data_received_cb")]
+        internal static extern int SetHidDeviceDataReceivedCallback(HidDeviceDataReceivedCallback dataReceivedCb, IntPtr userData);
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_unset_data_received_cb")]
+        internal static extern int UnsetHidDeviceDataReceivedCallback();
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_hid_device_reply_to_report")]
+        internal static extern int ReplyToReportHidDevice(string deviceAddress, BluetoothHidHeaderType headerType, BluetoothHidParamType paramType, byte[] value, int len, IntPtr userData);
+
         // Bluetooth OPP
         // Opp Server
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_opp_server_initialize")]
@@ -414,7 +436,7 @@ internal static partial class Interop
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_opp_client_initialize")]
         internal static extern int InitializeOppClient();
 
-        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_opp_client_dinitialize")]
+        [DllImport(Libraries.Bluetooth, EntryPoint = "bt_opp_client_deinitialize")]
         internal static extern int DeinitializeOppClient();
 
         [DllImport(Libraries.Bluetooth, EntryPoint = "bt_opp_client_add_file")]
index e3015d0..6bf97b5 100644 (file)
@@ -20,6 +20,7 @@ using System.Collections.Generic;
 using System.Collections.Concurrent;
 using System.Collections.ObjectModel;
 using System.Collections.Specialized;
+using System.ComponentModel;
 
 namespace Tizen.Network.Bluetooth
 {
@@ -542,4 +543,146 @@ namespace Tizen.Network.Bluetooth
             }
         }
     }
+
+    /// <summary>
+    /// This class contains the HID mouse event information.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class BluetoothHidMouseData
+    {
+        /// <summary>
+        /// The button values, we can combine key's values when we pressed multiple mouse buttons
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public int Buttons
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// The location's x value, -128 ~127
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public int AxisX
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// The location's y value, -128 ~127
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public int AxisY
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// The padding value, -128 ~127
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public int Padding
+        {
+            get;
+            set;
+        }
+    }
+
+    /// <summary>
+    /// This class contains the HID keyboard event information.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class BluetoothHidKeyData
+    {
+        /// <summary>
+        /// The modifier keys : such as shift, alt
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public byte Modifier
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// The key value - currently pressed keys : Max 8 at once
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public byte[] Key
+        {
+            get;
+            set;
+        }
+    }
+
+    /// <summary>
+    /// This class contains the data received from the HID Host.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class BluetoothHidDeviceReceivedData
+    {
+        /// <summary>
+        /// The default constructor. Initializes an object of the BluetoothHidReceivedData.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        internal static BluetoothHidDeviceReceivedData Create(BluetoothHidDeviceReceivedDataStruct structInfo)
+        {
+            BluetoothHidDeviceReceivedData receivedData = new BluetoothHidDeviceReceivedData();
+            receivedData.Address = structInfo.RemoteAddress;
+            receivedData.HeaderType = structInfo.headerType;
+            receivedData.ParamType = structInfo.paramType;
+            if (structInfo.dataSize > 0)
+            {
+                receivedData.Data = new byte[structInfo.dataSize];
+                Marshal.Copy(structInfo.data, receivedData.Data, 0, structInfo.dataSize);
+            }
+            return receivedData;
+        }
+
+        /// <summary>
+        /// The remote device's address
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public string Address
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// The header type
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public BluetoothHidHeaderType HeaderType
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// The parameter type
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public BluetoothHidParamType ParamType
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// The received data
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public byte[] Data
+        {
+            get;
+            private set;
+        }
+    }
 }
index 1a06057..34894a0 100644 (file)
@@ -679,37 +679,9 @@ namespace Tizen.Network.Bluetooth
         /// <since_tizen> 3 </since_tizen>
         public T GetProfile<T>() where T : BluetoothProfile
         {
-            /*
-             * FIXME: Find a proper way for dynamic allocation.
-             */
-            T profile = null;
-            String type = typeof(T).ToString();
-            if (type.Equals("Tizen.Network.Bluetooth.BluetoothAudio"))
-            {
-                BluetoothAudio audio = new BluetoothAudio();
-                profile = (audio as T);
-            }
-            else if (type.Equals("Tizen.Network.Bluetooth.BluetoothAvrcp"))
-            {
-                BluetoothAvrcp avrcp = new BluetoothAvrcp();
-                profile = (avrcp as T);
-            }
-            else if (type.Equals("Tizen.Network.Bluetooth.BluetoothHid"))
-            {
-                BluetoothHid hid = new BluetoothHid();
-                profile = (hid as T);
-            }
-
-            else if (type.Equals("Tizen.Network.Bluetooth.BluetoothOppClient"))
-            {
-                BluetoothOppClient oppClient = new BluetoothOppClient();
-                profile = (oppClient as T);
-            }
-
-            if (profile != null)
-            {
-                profile.RemoteAddress = RemoteDeviceAddress;
-            }
+            // TODO : Need to check capability of supporting profiles
+            var profile = Activator.CreateInstance<T>();
+            profile.RemoteAddress = RemoteDeviceAddress;
             return profile;
         }
 
index ac2fca9..b3b6a66 100644 (file)
@@ -16,6 +16,7 @@
 
 using System;
 using Tizen.Internals.Errors;
+using System.ComponentModel;
 
 namespace Tizen.Network.Bluetooth
 {
@@ -1232,4 +1233,62 @@ namespace Tizen.Network.Bluetooth
         /// </summary>
         Write = 1,
     }
+
+    /// <summary>
+    /// Enumeration for the Bluetooth HID header type.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public enum BluetoothHidHeaderType
+    {
+        /// <summary>
+        /// The Bluetooth HID header type: Handshake
+        /// </summary>
+        Handshake,
+        /// <summary>
+        /// The Bluetooth HID header type: HID control
+        /// </summary>
+        HidControl,
+        /// <summary>
+        /// The Bluetooth HID header type: Get report
+        /// </summary>
+        GetReport,
+        /// <summary>
+        /// The Bluetooth HID header type: Set report
+        /// </summary>
+        SetReport,
+        /// <summary>
+        /// The Bluetooth HID header type: Get protocol
+        /// </summary>
+        GetProtocol,
+        /// <summary>
+        /// The Bluetooth HID header type: Set protocol
+        /// </summary>
+        SetProtocol,
+        /// <summary>
+        /// The Bluetooth HID header type: Data
+        /// </summary>
+        Data,
+        /// <summary>
+        /// The Bluetooth HID header type: Unknown
+        /// </summary>
+        Unknown
+    }
+
+    /// <summary>
+    /// Enumeration for the Bluetooth HID parameter type.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public enum BluetoothHidParamType
+    {
+        /// <summary>
+        /// Parameter type: Input
+        /// </summary>
+        Input,
+        /// <summary>
+        /// Parameter type: Output
+        /// </summary>
+        Output
+    }
 }
index 83ce73d..3f245d9 100644 (file)
@@ -27,82 +27,90 @@ namespace Tizen.Network.Bluetooth
         /// Exceptions for Bluetooth Errors.
         /// </summary>
         /// <exception cref="InvalidOperationException">Thrown when the Bluetooth Error happens.</exception>
-        static internal void ThrowBluetoothException(int exception)
+        internal static void ThrowBluetoothException(int exception)
+        {
+            throw CreateBluetoothException(exception);
+        }
+
+        /// <summary>
+        /// Creates Bluetooth Exception.
+        /// </summary>
+        internal static Exception CreateBluetoothException(int exception)
         {
             BluetoothError error = (BluetoothError)exception;
             switch (error)
             {
-            case BluetoothError.InvalidParameter:
-                throw new InvalidOperationException("Invalid parameter");
+                case BluetoothError.InvalidParameter:
+                    return new InvalidOperationException("Invalid parameter");
 
-            case BluetoothError.Cancelled:
-                throw new InvalidOperationException("Operation cancelled");
+                case BluetoothError.Cancelled:
+                    return new InvalidOperationException("Operation cancelled");
 
-            case BluetoothError.AlreadyDone:
-                throw new InvalidOperationException("Operation already done");
+                case BluetoothError.AlreadyDone:
+                    return new InvalidOperationException("Operation already done");
 
-            case BluetoothError.TimedOut:
-                throw new InvalidOperationException("Timeout error");
+                case BluetoothError.TimedOut:
+                    return new InvalidOperationException("Timeout error");
 
-            case BluetoothError.AuthFailed:
-                throw new InvalidOperationException("Authentication failed");
+                case BluetoothError.AuthFailed:
+                    return new InvalidOperationException("Authentication failed");
 
-            case BluetoothError.AuthRejected:
-                throw new InvalidOperationException("Authentication rejected");
+                case BluetoothError.AuthRejected:
+                    return new InvalidOperationException("Authentication rejected");
 
-            case BluetoothError.NoData:
-                throw new InvalidOperationException("No data available");
+                case BluetoothError.NoData:
+                    return new InvalidOperationException("No data available");
 
-            case BluetoothError.NotEnabled:
-                throw new InvalidOperationException("Local adapter not enabled");
+                case BluetoothError.NotEnabled:
+                    return new InvalidOperationException("Local adapter not enabled");
 
-            case BluetoothError.NotInitialized:
-                throw new InvalidOperationException("Local adapter not initialized");
+                case BluetoothError.NotInitialized:
+                    return new InvalidOperationException("Local adapter not initialized");
 
-            case BluetoothError.NowInProgress:
-                throw new InvalidOperationException("Operation now in progress");
+                case BluetoothError.NowInProgress:
+                    return new InvalidOperationException("Operation now in progress");
 
-            case BluetoothError.NotInProgress:
-                throw new InvalidOperationException("Operation not in progress");
+                case BluetoothError.NotInProgress:
+                    return new InvalidOperationException("Operation not in progress");
 
-            case BluetoothError.NotSupported:
-                throw new NotSupportedException("Bluetooth is not supported");
+                case BluetoothError.NotSupported:
+                    return new NotSupportedException("Bluetooth is not supported");
 
-            case BluetoothError.OperationFailed:
-                throw new InvalidOperationException("Operation failed");
+                case BluetoothError.OperationFailed:
+                    return new InvalidOperationException("Operation failed");
 
-            case BluetoothError.OutOfMemory:
-                throw new InvalidOperationException("Out of memory");
+                case BluetoothError.OutOfMemory:
+                    return new InvalidOperationException("Out of memory");
 
-            case BluetoothError.PermissionDenied:
-                throw new InvalidOperationException("Permission denied");
+                case BluetoothError.PermissionDenied:
+                    return new InvalidOperationException("Permission denied");
 
-            case BluetoothError.QuotaExceeded:
-                throw new InvalidOperationException("Quota exceeded");
+                case BluetoothError.QuotaExceeded:
+                    return new InvalidOperationException("Quota exceeded");
 
-            case BluetoothError.RemoteDeviceNotBonded:
-                throw new InvalidOperationException("Remote device not bonded");
+                case BluetoothError.RemoteDeviceNotBonded:
+                    return new InvalidOperationException("Remote device not bonded");
 
-            case BluetoothError.RemoteDeviceNotConnected:
-                throw new InvalidOperationException("Remote device not connected");
+                case BluetoothError.RemoteDeviceNotConnected:
+                    return new InvalidOperationException("Remote device not connected");
 
-            case BluetoothError.RemoteDeviceNotFound:
-                throw new InvalidOperationException("Remote device not found");
+                case BluetoothError.RemoteDeviceNotFound:
+                    return new InvalidOperationException("Remote device not found");
 
-            case BluetoothError.ResourceBusy:
-                throw new InvalidOperationException("Device or resource busy");
+                case BluetoothError.ResourceBusy:
+                    return new InvalidOperationException("Device or resource busy");
 
-            case BluetoothError.ResourceUnavailable:
-                throw new InvalidOperationException("Resource temporarily unavailable");
+                case BluetoothError.ResourceUnavailable:
+                    return new InvalidOperationException("Resource temporarily unavailable");
 
-            case BluetoothError.ServiceNotFound:
-                throw new InvalidOperationException("Service Not Found");
+                case BluetoothError.ServiceNotFound:
+                    return new InvalidOperationException("Service Not Found");
 
-            case BluetoothError.ServiceSearchFailed:
-                throw new InvalidOperationException("Service search failed");
+                case BluetoothError.ServiceSearchFailed:
+                    return new InvalidOperationException("Service search failed");
 
-            default:
-                throw new InvalidOperationException("Unknown exception");
+                default:
+                    return new InvalidOperationException("Unknown exception");
             }
         }
     }
index ed9f8f5..d3288e8 100644 (file)
@@ -16,6 +16,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 
 namespace Tizen.Network.Bluetooth
 {
@@ -683,6 +684,76 @@ namespace Tizen.Network.Bluetooth
     }
 
     /// <summary>
+    /// An extended EventArgs class contains the connection state and the address of the remote Bluetooth device.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class HidDeviceConnectionStateChangedEventArgs : EventArgs
+    {
+        internal HidDeviceConnectionStateChangedEventArgs(bool isConnected, string address)
+        {
+            IsConnected = isConnected;
+            Address = address;
+        }
+
+        internal HidDeviceConnectionStateChangedEventArgs(int result, bool isConnected, string address)
+        {
+            Result = result;
+            IsConnected = isConnected;
+            Address = address;
+        }
+
+        internal int Result
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// A value indicating whether this instance is connected.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public bool IsConnected
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// The address.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public string Address
+        {
+            get;
+            private set;
+        }
+    }
+
+    /// <summary>
+    /// An extended EventArgs class contains the connection state and the address of the remote Bluetooth device.
+    /// </summary>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class HidDeviceDataReceivedEventArgs : EventArgs
+    {
+        internal HidDeviceDataReceivedEventArgs(BluetoothHidDeviceReceivedData receivedData)
+        {
+            ReceivedData = receivedData;
+        }
+
+        /// <summary>
+        /// The result.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        public BluetoothHidDeviceReceivedData ReceivedData
+        {
+            get;
+            private set;
+        }
+    }
+
+    /// <summary>
     /// An extended EventArgs class contains the changed equalizer state.
     /// </summary>
     /// <since_tizen> 3 </since_tizen>
diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDevice.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDevice.cs
new file mode 100644 (file)
index 0000000..5d57dd8
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading.Tasks;
+using System.ComponentModel;
+
+namespace Tizen.Network.Bluetooth
+{
+    /// <summary>
+    /// A class which is used to provide the HID Device role.
+    /// </summary>
+    /// <remarks>
+    /// In HID profile, there are two roles Host and Device.
+    /// The Host(BluetoothHid) is a device that uses or requests the service of a HID.
+    /// The Device(BluetoothHidDevice) is a device that provides the service of human data input/output to/from the host.
+    /// </remarks>
+    /// <since_tizen> 6 </since_tizen>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class BluetoothHidDevice : BluetoothProfile
+    {
+        private TaskCompletionSource<bool> _taskForConnection;
+        private TaskCompletionSource<bool> _taskForDisconnection;
+
+        internal BluetoothHidDevice()
+        {
+            BluetoothHidDeviceImpl.Instance.ConnectionStateChanged += (s, e) =>
+            {
+                if (e.Address == RemoteAddress)
+                {
+                    if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
+                    {
+                        if (e.Result == (int)BluetoothError.None)
+                        {
+                            _taskForConnection.SetResult(true);
+                        }
+                        else
+                        {
+                            _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
+                        }
+                    }
+
+                    if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
+                    {
+                        if (e.Result == (int)BluetoothError.None)
+                        {
+                            _taskForDisconnection.SetResult(true);
+                        }
+                        else
+                        {
+                            _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
+                        }
+                    }
+
+                    if (e.Result == (int)BluetoothError.None)
+                    {
+                        /* User does not need 'Result' in HidDeviceConnectionStateChangedEventArgs */
+                        ConnectionStateChanged?.Invoke(this, new HidDeviceConnectionStateChangedEventArgs(e.IsConnected, e.Address));
+                    }
+                }
+            };
+
+            BluetoothHidDeviceImpl.Instance.DataReceived += (s, e) =>
+            {
+                if (e.ReceivedData.Address == RemoteAddress)
+                {
+                    DataReceived?.Invoke(this, e);
+                }
+            };
+        }
+
+        /// <summary>
+        /// The ConnectionStateChanged event is called when the HID device connection state is changed.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public event EventHandler<HidDeviceConnectionStateChangedEventArgs> ConnectionStateChanged;
+
+        /// <summary>
+        /// Connects to the remote device asynchronously.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <returns> A task indicating whether the method is done or not.</returns>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Task ConnectAsync()
+        {   
+            if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
+            {
+                BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
+            }
+            _taskForConnection = new TaskCompletionSource<bool>();
+
+            int ret = BluetoothHidDeviceImpl.Instance.ConnectHidDevice(RemoteAddress);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to connect to the remote device, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+            return _taskForConnection.Task;
+        }
+
+        /// <summary>
+        /// Disconnects to the remote device asynchronously.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <returns> A task indicating whether the method is done or not.</returns>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Task DisconnectAsync()
+        {   
+            if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
+            {
+                BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
+            }
+            _taskForDisconnection = new TaskCompletionSource<bool>();
+
+            int ret = BluetoothHidDeviceImpl.Instance.DisconnectHidDevice(RemoteAddress);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to disconnect to the remote device, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+            return _taskForDisconnection.Task;
+        }
+
+        /// <summary>
+        /// Sends the mouse event data to the remote device.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <param name="mouseData">The mouse data to be passed to the remote device.</param>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SendMouseEvent(BluetoothHidMouseData mouseData)
+        {
+            BluetoothHidDeviceImpl.Instance.SendHidDeviceMouseEvent(RemoteAddress, mouseData);
+        }
+
+        /// <summary>
+        /// Sends the key event data to the remote device.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <param name="keyData">The key data to be passed to the remote device.</param>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SendKeyEvent(BluetoothHidKeyData keyData)
+        {
+            BluetoothHidDeviceImpl.Instance.SendHidDeviceKeyEvent(RemoteAddress, keyData);
+        }
+
+        /// <summary>
+        /// The DataReceived event is called when the device receives data from the HID Host.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public event EventHandler<HidDeviceDataReceivedEventArgs> DataReceived;
+
+        /// <summary>
+        /// Replies to reports from the HID Host.
+        /// </summary>
+        /// <since_tizen> 6 </since_tizen>
+        /// <param name="headerType">The header type to be there in response.</param>
+        /// <param name="paramType">The Parameter type to be there in response.</param>
+        /// <param name="data">Data to be present in data payload of response.</param>
+        /// <feature>http://tizen.org/feature/network.bluetooth</feature>
+        /// <feature>http://tizen.org/feature/network.bluetooth.hid_device</feature>
+        /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
+        /// <exception cref="InvalidOperationException">Thrown when the method is failed with message.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void ReplyToReport(BluetoothHidHeaderType headerType, BluetoothHidParamType paramType, byte[] data)
+        {
+            BluetoothHidDeviceImpl.Instance.ReplyToReportHidDevice(RemoteAddress, headerType, paramType, data);
+        }
+    }
+}
+
diff --git a/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDeviceImpl.cs b/src/Tizen.Network.Bluetooth/Tizen.Network.Bluetooth/BluetoothHidDeviceImpl.cs
new file mode 100644 (file)
index 0000000..7c05471
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading.Tasks;
+
+namespace Tizen.Network.Bluetooth
+{
+    internal class BluetoothHidDeviceImpl
+    {
+        private event EventHandler<HidDeviceConnectionStateChangedEventArgs> _hidDeviceConnectionStateChanged;
+        private event EventHandler<HidDeviceDataReceivedEventArgs> _hidDeviceDataReceived;
+
+        private static readonly BluetoothHidDeviceImpl _instance = new BluetoothHidDeviceImpl();
+
+        internal event EventHandler<HidDeviceConnectionStateChangedEventArgs> ConnectionStateChanged
+        {
+            add
+            {
+                _hidDeviceConnectionStateChanged += value;
+            }
+            remove
+            {
+                _hidDeviceConnectionStateChanged -= value;
+            }
+        }
+
+        internal int ConnectHidDevice(string deviceAddress)
+        {
+            return Interop.Bluetooth.ConnectHidDevice(deviceAddress);
+        }
+
+        internal int DisconnectHidDevice(string deviceAddress)
+        {
+            return Interop.Bluetooth.DisconnectHidDevice(deviceAddress);
+        }
+
+        internal void SendHidDeviceMouseEvent(string deviceAddress, BluetoothHidMouseData mouseData)
+        {
+            int ret = Interop.Bluetooth.SendHidDeviceMouseEvent(deviceAddress, mouseData);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to send mouse event to the remote device, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+
+        internal void SendHidDeviceKeyEvent(string deviceAddress, BluetoothHidKeyData keyData)
+        {
+            int ret = Interop.Bluetooth.SendHidDeviceKeyEvent(deviceAddress, keyData);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to send key event to the remote device, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+
+        internal event EventHandler<HidDeviceDataReceivedEventArgs> DataReceived
+        {
+            add
+            {
+                if (_hidDeviceDataReceived == null)
+                {
+                    RegisterHidDataReceivedEvent();
+                }
+                _hidDeviceDataReceived += value;
+            }
+            remove
+            {
+                _hidDeviceDataReceived -= value;
+                if (_hidDeviceDataReceived == null)
+                {
+                    UnregisterHidDataReceivedEvent();
+                }
+            }
+        }
+
+        private void RegisterHidDataReceivedEvent()
+        {
+            Interop.Bluetooth.HidDeviceDataReceivedCallback _hidDeviceDataReceivedCallback = (ref BluetoothHidDeviceReceivedDataStruct receivedData, IntPtr userData) =>
+            {
+                _hidDeviceDataReceived?.Invoke(null, new HidDeviceDataReceivedEventArgs(BluetoothHidDeviceReceivedData.Create(receivedData)));
+            };
+
+            int ret = Interop.Bluetooth.SetHidDeviceDataReceivedCallback(_hidDeviceDataReceivedCallback, IntPtr.Zero);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to set data received callback, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+
+        private void UnregisterHidDataReceivedEvent()
+        {
+            int ret = Interop.Bluetooth.UnsetHidDeviceDataReceivedCallback();
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to unset data received callback, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+
+        internal void ReplyToReportHidDevice(string deviceAddress, BluetoothHidHeaderType headerType, BluetoothHidParamType paramType, byte[] data)
+        {
+            int ret = Interop.Bluetooth.ReplyToReportHidDevice(deviceAddress, headerType, paramType, data, data.Length, IntPtr.Zero);
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to reply to report from hid host, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+
+        internal static BluetoothHidDeviceImpl Instance
+        {
+            get
+            {
+                return _instance;
+            }
+        }
+
+        private BluetoothHidDeviceImpl()
+        {
+            Initialize();
+        }
+
+        ~BluetoothHidDeviceImpl()
+        {
+            Deinitialize();
+        }
+
+        private void Initialize()
+        {
+            if (Globals.IsInitialize)
+            {
+                Interop.Bluetooth.HidDeviceConnectionStateChangedCallback _hidDeviceConnectionStateChangedCallback = (int result, bool isConnected, string address, IntPtr userData) =>
+                {
+                    _hidDeviceConnectionStateChanged?.Invoke(null, new HidDeviceConnectionStateChangedEventArgs(result, isConnected, address));
+                };
+
+                int ret = Interop.Bluetooth.ActivateHidDevice(_hidDeviceConnectionStateChangedCallback, IntPtr.Zero);
+                if (ret != (int)BluetoothError.None)
+                {
+                    Log.Error(Globals.LogTag, "Failed to activate to the remote device, Error - " + (BluetoothError)ret);
+                    BluetoothErrorFactory.ThrowBluetoothException(ret);
+                }
+            }
+            else
+            {
+                Log.Error(Globals.LogTag, "Failed to initialize HID Device, BT not initialized");
+                BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
+            }
+        }
+
+        private void Deinitialize()
+        {
+            int ret = Interop.Bluetooth.DeactivateHidDevice();
+            if (ret != (int)BluetoothError.None)
+            {
+                Log.Error(Globals.LogTag, "Failed to deactivate to the remote device, Error - " + (BluetoothError)ret);
+                BluetoothErrorFactory.ThrowBluetoothException(ret);
+            }
+        }
+    }
+}
+
index 44475aa..55cb1d1 100644 (file)
@@ -205,6 +205,17 @@ namespace Tizen.Network.Bluetooth
         internal int ServiceDataLength;
     }
 
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct BluetoothHidDeviceReceivedDataStruct
+    {
+        [MarshalAsAttribute(UnmanagedType.LPStr)]
+        internal string RemoteAddress;
+        internal BluetoothHidHeaderType headerType;
+        internal BluetoothHidParamType paramType;
+        internal int dataSize;
+        internal IntPtr data;
+    }
+
     internal static class BluetoothUtils
     {
         internal static BluetoothDevice ConvertStructToDeviceClass(BluetoothDeviceStruct device)