2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Runtime.InteropServices;
19 using System.Collections.Generic;
20 using System.Threading.Tasks;
22 namespace Tizen.Network.Nfc
25 /// The class for managing the Tag information.
27 /// <since_tizen> 3 </since_tizen>
28 public class NfcTag : IDisposable
30 private bool disposed = false;
31 private IntPtr _tagHandle = IntPtr.Zero;
34 Dictionary<int, TaskCompletionSource<byte[]>> _transceiveTaskSource = new Dictionary<int, TaskCompletionSource<byte[]>>();
35 Interop.Nfc.TagTransceiveCompletedCallback _nativeTransceiveCallback;
37 Dictionary<int, TaskCompletionSource<NfcError>> _voidTaskSource = new Dictionary<int, TaskCompletionSource<NfcError>>();
38 Interop.Nfc.VoidCallback _nativeVoidCallback;
40 Dictionary<int, TaskCompletionSource<NfcNdefMessage>> _readNdefTaskSource = new Dictionary<int, TaskCompletionSource<NfcNdefMessage>>();
41 Interop.Nfc.TagReadCompletedCallback _nativeTagReadCallback;
44 /// Constructor of NfcTag
48 // A method is need to convert delegate to pass unmanaged layer through Interop call
49 // If we do not convert explicitly it, implicitly convert was occurred
50 // and temporal delegate was created. and it could be released by GC
51 _nativeTransceiveCallback = TransceiveCompletedCallback;
52 _nativeVoidCallback = VoidCallback;
53 _nativeTagReadCallback = ReadNdefCallback;
57 /// The type of the NFC tag.
59 /// <since_tizen> 3 </since_tizen>
60 public NfcTagType Type
65 int ret = Interop.Nfc.Tag.GetType(_tagHandle, out type);
66 if (ret != (int)NfcError.None)
68 Log.Error(Globals.LogTag, "Failed to get tag type, Error - " + (NfcError)ret);
70 return (NfcTagType)type;
75 /// Whether the given NFC tag supports the NDEF messages.
77 /// <since_tizen> 3 </since_tizen>
78 public bool IsSupportNdef
83 int ret = Interop.Nfc.Tag.IsSupportNdef(_tagHandle, out isSupport);
84 if (ret != (int)NfcError.None)
86 Log.Error(Globals.LogTag, "Failed to get support state, Error - " + (NfcError)ret);
94 /// The maximum NDEF message size that can be stored in the NFC tag.
96 /// <since_tizen> 3 </since_tizen>
97 public uint MaximumNdefSize
102 int ret = Interop.Nfc.Tag.GetMaximumNdefSize(_tagHandle, out maxSize);
103 if (ret != (int)NfcError.None)
105 Log.Error(Globals.LogTag, "Failed to get max ndef size, Error - " + (NfcError)ret);
112 /// The size of the NDEF message stored in the tag.
114 /// <since_tizen> 3 </since_tizen>
120 int ret = Interop.Nfc.Tag.GetNdefSize(_tagHandle, out ndefSize);
121 if (ret != (int)NfcError.None)
123 Log.Error(Globals.LogTag, "Failed to get ndef size, Error - " + (NfcError)ret);
129 internal NfcTag(IntPtr handle)
132 _nativeTransceiveCallback = TransceiveCompletedCallback;
133 _nativeVoidCallback = VoidCallback;
134 _nativeTagReadCallback = ReadNdefCallback;
138 /// NfcTag destructor.
148 /// <since_tizen> 3 </since_tizen>
149 public void Dispose()
152 GC.SuppressFinalize(this);
155 private void Dispose(bool disposing)
162 // Free managed objects.
164 //Free unmanaged objects
169 /// Retrieves all the tag information.
171 /// <since_tizen> 3 </since_tizen>
172 /// <returns>The list of the NfcTagInformation objects.</returns>
173 /// <privilege>http://tizen.org/privilege/nfc</privilege>
174 /// <exception cref="NotSupportedException">Thrown when the NFC is not supported.</exception>
175 /// <exception cref="InvalidOperationException">Thrown when the method fails due to an invalid operation.</exception>
176 public IEnumerable<NfcTagInformation> ForeachInformation()
178 List<NfcTagInformation> infoList = new List<NfcTagInformation>();
179 Interop.Nfc.TagInformationCallback callback = (IntPtr key, IntPtr infoValue, int valueSize, IntPtr userData) =>
181 if (key != IntPtr.Zero && infoValue != IntPtr.Zero)
183 NfcTagInformation tagInfo = new NfcTagInformation(Marshal.PtrToStringAnsi(key), new byte[valueSize]);
185 Marshal.Copy(infoValue, tagInfo.InformationValue, 0, valueSize);
187 infoList.Add(tagInfo);
194 int ret = Interop.Nfc.Tag.ForeachInformation(_tagHandle, callback, IntPtr.Zero);
195 if (ret != (int)NfcError.None)
197 Log.Error(Globals.LogTag, "Failed to get all Tag information, Error - " + (NfcError)ret);
198 NfcErrorFactory.ThrowNfcException(ret);
205 /// Transceives the data of the raw format card.
207 /// <since_tizen> 3 </since_tizen>
208 /// <param name="buffer">The binary data for a parameter or additional commands.</param>
209 /// <privilege>http://tizen.org/privilege/nfc</privilege>
210 /// <exception cref="NotSupportedException">Thrown when the NFC is not supported.</exception>
211 /// <exception cref="ArgumentException">Thrown when the method fails due to an invalid parameter.</exception>
212 /// <exception cref="InvalidOperationException">Thrown when the the method fails due to an invalid operation.</exception>
213 public Task<byte[]> TransceiveAsync(byte[] buffer)
216 var task = new TaskCompletionSource<byte[]>();
219 requestId = _requestId++;
220 _transceiveTaskSource[requestId] = task;
223 int ret = Interop.Nfc.Tag.Transceive(_tagHandle, buffer, buffer.Length, _nativeTransceiveCallback, (IntPtr)requestId);
224 if (ret != (int)NfcError.None)
226 Log.Error(Globals.LogTag, "Failed to transceive data, Error - " + (NfcError)ret);
227 _transceiveTaskSource.Remove(requestId);
228 NfcErrorFactory.ThrowNfcException(ret);
234 /// Reads the NDEF formatted data from the NFC tag.
236 /// <since_tizen> 3 </since_tizen>
237 /// <privilege>http://tizen.org/privilege/nfc</privilege>
238 /// <exception cref="NotSupportedException">Thrown when the NFC is not supported.</exception>
239 /// <exception cref="InvalidOperationException">Thrown when the method fails due to an invalid operation.</exception>
240 public Task<NfcNdefMessage> ReadNdefMessageAsync()
243 var task = new TaskCompletionSource<NfcNdefMessage>();
247 requestId = _requestId++;
248 _readNdefTaskSource[requestId] = task;
251 int ret = Interop.Nfc.Tag.ReadNdef(_tagHandle, _nativeTagReadCallback, (IntPtr)requestId);
252 if (ret != (int)NfcError.None)
254 Log.Error(Globals.LogTag, "Failed to read ndef message, Error - " + (NfcError)ret);
255 _readNdefTaskSource.Remove(requestId);
256 NfcErrorFactory.ThrowNfcException(ret);
262 /// Writes the NDEF formatted data.
264 /// <since_tizen> 3 </since_tizen>
265 /// <param name="ndefMessage">The NfcNdefMessage object.</param>
266 /// <privilege>http://tizen.org/privilege/nfc</privilege>
267 /// <exception cref="NotSupportedException">Thrown when the NFC is not supported.</exception>
268 /// <exception cref="ArgumentException">Thrown when the method fails due to an invalid parameter.</exception>
269 /// <exception cref="InvalidOperationException">Thrown when the method fails due to an invalid operation.</exception>
270 public Task<NfcError> WriteNdefMessageAsync(NfcNdefMessage ndefMessage)
273 var task = new TaskCompletionSource<NfcError>();
277 requestId = _requestId++;
278 _voidTaskSource[requestId] = task;
281 int ret = Interop.Nfc.Tag.WriteNdef(_tagHandle, ndefMessage.GetHandle(), _nativeVoidCallback, (IntPtr)requestId);
283 if (ret != (int)NfcError.None)
285 Log.Error(Globals.LogTag, "Failed to write ndef message, Error - " + (NfcError)ret);
286 _voidTaskSource.Remove(requestId);
287 NfcErrorFactory.ThrowNfcException(ret);
294 /// Formats the detected tag that can store the NDEF message.
296 /// <since_tizen> 3 </since_tizen>
297 /// <param name="keyValue">The key value that may need to format the tag.</param>
298 /// <privilege>http://tizen.org/privilege/nfc</privilege>
299 /// <exception cref="NotSupportedException">Thrown when the NFC is not supported.</exception>
300 /// <exception cref="ArgumentException">Thrown when method fails due to an invalid parameter.</exception>
301 /// <exception cref="InvalidOperationException">Thrown when the method fails due to an invalid operation.</exception>
302 public Task<NfcError> FormatNdefMessageAsync(byte[] keyValue)
305 var task = new TaskCompletionSource<NfcError>();
309 requestId = _requestId++;
310 _voidTaskSource[requestId] = task;
313 int ret = Interop.Nfc.Tag.FormatNdef(_tagHandle, keyValue, keyValue.Length, _nativeVoidCallback, (IntPtr)requestId);
314 if (ret != (int)NfcError.None)
316 Log.Error(Globals.LogTag, "Failed to format ndef message, Error - " + (NfcError)ret);
317 _voidTaskSource.Remove(requestId);
318 NfcErrorFactory.ThrowNfcException(ret);
324 void TransceiveCompletedCallback(int result, IntPtr resultData, int dataSize, IntPtr userData)
326 int requestId = (int)userData;
327 if (_transceiveTaskSource.ContainsKey(requestId))
329 if (result == (int)NfcError.None)
331 byte[] resultBuffer = new byte[dataSize];
332 Marshal.Copy(resultData, resultBuffer, 0, dataSize);
333 _transceiveTaskSource[requestId].TrySetResult(resultBuffer);
335 _transceiveTaskSource.Remove(requestId);
340 void VoidCallback(int result, IntPtr userData)
342 int requestId = (int)userData;
343 if (_voidTaskSource.ContainsKey(requestId))
345 _voidTaskSource[requestId].TrySetResult((NfcError)result);
346 _voidTaskSource.Remove(requestId);
350 bool ReadNdefCallback(int result, IntPtr ndefMessage, IntPtr userData)
353 int requestId = (int)userData;
354 if (_readNdefTaskSource.ContainsKey(requestId))
356 if (result == (int)NfcError.None)
358 var ndefMsg = new NfcNdefMessage(ndefMessage);
359 _readNdefTaskSource[requestId].TrySetResult(ndefMsg);
362 _readNdefTaskSource.Remove(requestId);