[Connection][WiFi] Use TizenSynchronizationContext.Post for asynchronous methods...
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.WiFi / Tizen.Network.WiFi / WiFiAP.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Threading.Tasks;
19 using System.Collections.Generic;
20 using Tizen.Applications;
21
22 namespace Tizen.Network.WiFi
23 {
24     /// <summary>
25     /// A class for managing the network information of the access point (AP).
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class WiFiAP : IDisposable
29     {
30         private IntPtr _apHandle = IntPtr.Zero;
31         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
32         private static Dictionary<IntPtr, Interop.WiFi.VoidCallback> s_callbackMap = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
33         private int _requestId = 0;
34         private static int s_requestId = 0;
35         private WiFiNetwork _network;
36         private WiFiSecurity _security;
37         private bool _disposed = false;
38
39         private TizenSynchronizationContext context = new TizenSynchronizationContext();
40         private static TizenSynchronizationContext s_context = new TizenSynchronizationContext();
41
42         /// <summary>
43         /// The network information of the access point (AP).
44         /// </summary>
45         /// <since_tizen> 3 </since_tizen>
46         /// <value>The WiFiNetwork instance containing the network information of the AP.</value>
47         public WiFiNetwork NetworkInformation
48         {
49             get
50             {
51                 return _network;
52             }
53         }
54
55         /// <summary>
56         /// The security information of the access point (AP).
57         /// </summary>
58         /// <since_tizen> 3 </since_tizen>
59         /// <value>The WiFiSecurity instance containing security information of the AP.</value>
60         public WiFiSecurity SecurityInformation
61         {
62             get
63             {
64                 return _security;
65             }
66         }
67
68         internal WiFiAP(IntPtr handle)
69         {
70             Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle);
71             _apHandle = handle;
72             Initialize();
73         }
74
75         /// <summary>
76         /// Creates an object for the access point.
77         /// </summary>
78         /// <since_tizen> 3 </since_tizen>
79         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
80         /// <feature>http://tizen.org/feature/network.wifi</feature>
81         /// <privilege>http://tizen.org/privilege/network.get</privilege>
82         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
83         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
84         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
85         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
86         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
87         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
88         public WiFiAP(string essid)
89         {
90             Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid);
91             createHandle(essid, true);
92             Initialize();
93         }
94
95         /// <summary>
96         /// Creates an object for the hidden access point.
97         /// </summary>
98         /// <since_tizen> 3 </since_tizen>
99         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
100         /// <param name="hidden">The value to set a hidden AP.</param>
101         /// <feature>http://tizen.org/feature/network.wifi</feature>
102         /// <privilege>http://tizen.org/privilege/network.get</privilege>
103         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
104         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
105         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
106         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
107         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
108         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
109         public WiFiAP(string essid, bool hidden)
110         {
111             createHandle(essid, hidden);
112             Initialize();
113         }
114
115         /// <summary>
116         /// Destroy the WiFiAP object
117         /// </summary>
118         ~WiFiAP()
119         {
120             Dispose(false);
121         }
122
123         /// <summary>
124         /// A method to destroy the managed WiFiAP objects.
125         /// </summary>
126         /// <since_tizen> 3 </since_tizen>
127         public void Dispose()
128         {
129             Dispose(true);
130             GC.SuppressFinalize(this);
131         }
132
133         private void Dispose(bool disposing)
134         {
135             if (_disposed)
136                 return;
137
138             if (disposing)
139             {
140                 Interop.WiFi.AP.Destroy(_apHandle);
141                 _apHandle = IntPtr.Zero;
142             }
143             _disposed = true;
144         }
145
146         private void createHandle(string id, bool hidden)
147         {
148             int ret = -1;
149             if (id == null)
150             {
151                 throw new ArgumentNullException("Essid is null");
152             }
153
154             if (hidden)
155             {
156                 ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
157             }
158
159             else
160             {
161                 ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
162             }
163
164             if (ret != (int)WiFiError.None)
165             {
166                 Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret);
167                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
168             }
169         }
170
171         private void Initialize()
172         {
173             Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle);
174             _network = new WiFiNetwork(apHandle);
175             _security = new WiFiSecurity(apHandle);
176         }
177
178         /// <summary>
179         /// Refreshes the access point information.
180         /// </summary>
181         /// <since_tizen> 3 </since_tizen>
182         /// <feature>http://tizen.org/feature/network.wifi</feature>
183         /// <privilege>http://tizen.org/privilege/network.get</privilege>
184         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
185         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
186         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
187         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
188         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
189         public void Refresh()
190         {
191             Log.Debug(Globals.LogTag, "Refresh");
192             if (_disposed)
193             {
194                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
195             }
196             int ret = Interop.WiFi.AP.Refresh(_apHandle);
197             if (ret != (int)WiFiError.None)
198             {
199                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
200                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get");
201             }
202         }
203
204         /// <summary>
205         /// Connects the access point asynchronously.
206         /// </summary>
207         /// <since_tizen> 3 </since_tizen>
208         /// <returns> A task indicating whether the connect method is done or not.</returns>
209         /// <feature>http://tizen.org/feature/network.wifi</feature>
210         /// <privilege>http://tizen.org/privilege/network.set</privilege>
211         /// <privilege>http://tizen.org/privilege/network.get</privilege>
212         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
213         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
214         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
215         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
216         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
217         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
218         public Task ConnectAsync()
219         {
220             Log.Info(Globals.LogTag, "ConnectAsync");
221             if (_disposed)
222             {
223                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
224             }
225             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
226             IntPtr id;
227             lock (_callback_map)
228             {
229                 id = (IntPtr)_requestId++;
230                 _callback_map[id] = (error, key) =>
231                 {
232                     Log.Info(Globals.LogTag, "ConnectAsync done " + (WiFiError)error);
233                     if (error != (int)WiFiError.None)
234                     {
235                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
236                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
237                     }
238                     else
239                     {
240                         task.SetResult(true);
241                     }
242                     lock (_callback_map)
243                     {
244                         _callback_map.Remove(key);
245                     }
246                 };
247             }
248
249             context.Post((x) =>
250             {
251                 Log.Info(Globals.LogTag, "Interop.WiFi.Connect");
252                 int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
253                 if (ret != (int)WiFiError.None)
254                 {
255                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
256                     WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
257                 }
258             }, null);
259
260             return task.Task;
261         }
262
263         /// <summary>
264         /// Connects the access point with the WPS asynchronously.
265         /// </summary>
266         /// <since_tizen> 3 </since_tizen>
267         /// <param name="info">A WpsInfo instance which is type of WpsPbcInfo or WpsPinInfo.</param>
268         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
269         /// <feature>http://tizen.org/feature/network.wifi</feature>
270         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
271         /// <privilege>http://tizen.org/privilege/network.get</privilege>
272         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
273         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
274         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
275         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
276         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is an empty string or more than 7 characters.</exception>
277         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
278         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
279         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
280         public Task ConnectWpsAsync(WpsInfo info)
281         {
282             Log.Info(Globals.LogTag, "ConnectWpsAsync");
283             if (_disposed)
284             {
285                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
286             }
287             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
288             IntPtr id;
289             lock (_callback_map)
290             {
291                 id = (IntPtr)_requestId++;
292                 _callback_map[id] = (error, key) =>
293                 {
294                     Log.Info(Globals.LogTag, "ConnectWpsAsync done");
295                     if (error != (int)WiFiError.None)
296                     {
297                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
298                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
299                     }
300                     else
301                     {
302                         task.SetResult(true);
303                     }
304                     lock (_callback_map)
305                     {
306                         _callback_map.Remove(key);
307                     }
308                 };
309             }
310
311             context.Post((x) =>
312             {
313                 int ret = -1;
314                 if (info.GetType() == typeof(WpsPbcInfo))
315                 {
316                     Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPb");
317                     ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
318                 }
319                 else if (info.GetType() == typeof(WpsPinInfo))
320                 {
321                     WpsPinInfo pinInfo = (WpsPinInfo)info;
322                     if (pinInfo.GetWpsPin() == null)
323                     {
324                         throw new ArgumentNullException("Wps pin should not be null");
325                     }
326
327                     if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8)
328                     {
329                         throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters");
330                     }
331
332                     Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPin");
333                     ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
334                 }
335
336                 if (ret != (int)WiFiError.None)
337                 {
338                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
339                     WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
340                 }
341             }, null);
342
343             return task.Task;
344         }
345
346         /// <summary>
347         /// Connects the access point with WPS without SSID asynchronously.
348         /// </summary>
349         /// <since_tizen> 3 </since_tizen>
350         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
351         /// <returns>A task which contains Connected access point information.</returns>
352         /// <remarks>
353         /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long.
354         /// </remarks>
355         /// <feature>http://tizen.org/feature/network.wifi</feature>
356         /// <privilege>http://tizen.org/privilege/network.set</privilege>
357         /// <privilege>http://tizen.org/privilege/network.get</privilege>
358         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
359         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
360         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
361         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
362         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is not of 4 or 8 characters long.</exception>
363         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
364         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
365         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
366         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
367         {
368             Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync");
369             TaskCompletionSource<WiFiAP> task = new TaskCompletionSource<WiFiAP>();
370             IntPtr id;
371             lock (s_callbackMap)
372             {
373                 id = (IntPtr)s_requestId++;
374                 s_callbackMap[id] = (error, key) =>
375                 {
376                     Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync done");
377                     if (error != (int)WiFiError.None)
378                     {
379                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
380                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
381                     }
382                     else
383                     {
384                         WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
385                         task.SetResult(ap);
386                     }
387                     lock (s_callbackMap)
388                     {
389                         s_callbackMap.Remove(key);
390                     }
391                 };
392             }
393
394             s_context.Post((x) =>
395             {
396                 int ret = -1;
397                 if (info.GetType() == typeof(WpsPbcInfo))
398                 {
399                     Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPbcWithoutSsid");
400                     ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);
401                 }
402                 else if (info.GetType() == typeof(WpsPinInfo))
403                 {
404                     WpsPinInfo pinInfo = (WpsPinInfo)info;
405                     if (pinInfo.GetWpsPin() == null)
406                     {
407                         throw new ArgumentNullException("Wps pin should not be null");
408                     }
409
410                     if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8)
411                     {
412                         throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long");
413                     }
414
415                     Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPinWithoutSsid");
416                     ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
417                 }
418
419                 if (ret != (int)WiFiError.None)
420                 {
421                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
422                     WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
423                 }
424             }, null);
425
426             return task.Task;
427         }
428
429         /// <summary>
430         /// Disconnects the access point asynchronously.
431         /// </summary>
432         /// <since_tizen> 3 </since_tizen>
433         /// <returns> A task indicating whether the disconnect method is done or not.</returns>
434         /// <feature>http://tizen.org/feature/network.wifi</feature>
435         /// <privilege>http://tizen.org/privilege/network.set</privilege>
436         /// <privilege>http://tizen.org/privilege/network.get</privilege>
437         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
438         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
439         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
440         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
441         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
442         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
443         public Task DisconnectAsync()
444         {
445             Log.Debug(Globals.LogTag, "DisconnectAsync");
446             if (_disposed)
447             {
448                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
449             }
450             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
451             IntPtr id;
452             lock (_callback_map)
453             {
454                 id = (IntPtr)_requestId++;
455                 _callback_map[id] = (error, key) =>
456                 {
457                     Log.Info(Globals.LogTag, "DisconnectAsync done");
458                     if (error != (int)WiFiError.None)
459                     {
460                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
461                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
462                     }
463                     else
464                     {
465                         task.SetResult(true);
466                     }
467                     lock (_callback_map)
468                     {
469                         _callback_map.Remove(key);
470                     }
471                 };
472             }
473
474             context.Post((x) =>
475             {
476                 Log.Info(Globals.LogTag, "Interop.WiFi.Disconnect");
477                 int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
478                 if (ret != (int)WiFiError.None)
479                 {
480                     Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
481                     WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
482                 }
483             }, null);
484
485             return task.Task;
486         }
487
488         /// <summary>
489         /// Deletes the information of a stored access point and disconnects it when the AP is connected.
490         /// If an AP is connected, then the connection information will be stored. This information is used when a connection to that AP is established automatically.
491         /// </summary>
492         /// <since_tizen> 3 </since_tizen>
493         /// <feature>http://tizen.org/feature/network.wifi</feature>
494         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
495         /// <privilege>http://tizen.org/privilege/network.get</privilege>
496         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
497         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
498         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
499         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
500         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
501         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
502         public void ForgetAP()
503         {
504             Log.Debug(Globals.LogTag, "ForgetAP");
505             if (_disposed)
506             {
507                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
508             }
509             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
510             if (ret != (int)WiFiError.None)
511             {
512                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
513                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
514             }
515         }
516    }
517
518     /// <summary>
519     /// An abstract class which is used to represent the WPS information of the access point.
520     /// </summary>
521     /// <since_tizen> 3 </since_tizen>
522     public abstract class WpsInfo
523     {
524     }
525
526     /// <summary>
527     /// A class which is used to represent WPS PBC information of the access point.
528     /// </summary>
529     /// <since_tizen> 3 </since_tizen>
530     public class WpsPbcInfo : WpsInfo
531     {
532     }
533
534     /// <summary>
535     /// A class which is used to represent WPS PIN information of the access point.
536     /// </summary>
537     /// <since_tizen> 3 </since_tizen>
538     public class WpsPinInfo : WpsInfo
539     {
540         private string _pin;
541
542         private WpsPinInfo()
543         {
544         }
545
546         /// <summary>
547         /// A public constructor which instantiates WpsPinInfo class with the given pin.
548         /// </summary>
549         /// <since_tizen> 3 </since_tizen>
550         /// <param name="pin">WPS Pin of the access point.</param>
551         /// <remarks>
552         /// Pin should not be null or empty. It should be of less than 8 characters.
553         /// </remarks>
554         public WpsPinInfo(string pin)
555         {
556             _pin = pin;
557         }
558
559         internal string GetWpsPin()
560         {
561             return _pin;
562         }
563     }
564 }