public void WriteTag(NdefLibrary.Ndef.NdefMessage message) { int messageSize = 0; foreach (NdefRecord record in message) { messageSize += record.Payload.Length; if (!record.CheckIfValid()) { throw new Exception("A record on NDEFMessage is not valid"); } } if (!isTagPresent) { throw new Exception("No Tag present or Tag is incompatible "); } if (!nfcTag.IsWriteable) { throw new Exception("Tag is write locked "); } if (nfcTag.MaxSize < messageSize) { throw new Exception("Tag is too small for this message"); } RaiseTagConnected(nfcTag); nfcDevice.PublishBinaryMessage("NDEF:WriteTag", message.ToByteArray().AsBuffer(), writerHandler); }
/// <summary> /// Deletes any details currently stored in the Smart Poster /// and re-initializes them by parsing the contents of the payload. /// </summary> private void ParsePayloadToData(byte[] payload) { InitializeData(); if (payload == null || payload.Length == 0) { return; } var message = NdefMessage.FromByteArray(payload); foreach (NdefRecord record in message) { var specializedType = record.CheckSpecializedType(false); if (specializedType == null) { continue; } if (specializedType == typeof(NdefUriRecord)) { // URI RecordUri = new NdefUriRecord(record); } else if (specializedType == typeof(NdefTextRecord)) { // Title var textRecord = new NdefTextRecord(record); if (Titles == null) { Titles = new List <NdefTextRecord>(); } Titles.Add(textRecord); } else if (specializedType == typeof(NdefSpActRecord)) { // Action _recordAction = new NdefSpActRecord(record); } else if (specializedType == typeof(NdefSpSizeRecord)) { // Size _recordSize = new NdefSpSizeRecord(record); } else if (specializedType == typeof(NdefSpMimeTypeRecord)) { // Mime Type _recordMimeType = new NdefSpMimeTypeRecord(record); } else if (specializedType == typeof(NdefMimeImageRecordBase)) { // Image _recordImage = new NdefMimeImageRecordBase(record); } else { Debug.WriteLine("Sp: Don't know how to handle this record: " + BitConverter.ToString(record.Type)); } } }
/// <summary> /// Create the payload based on the data stored in the properties. Usually called /// automatically when changing properties, but you might need to call this manually /// if you modify the list of alternative carrier records directly without using /// accessor method provided by this class. /// </summary> /// <exception cref="NdefException">Thrown if unable to assemble the payload. /// The exception message contains further details about the issue.</exception> public void AssemblePayload() { if (_handoverVersion == null) { throw new NdefException(NdefExceptionMessages.ExHandoverInvalidVersion); } // Convert child records to message var childMsg = new NdefMessage(); if (_handoverAlternativeCarrierRecords != null) { childMsg.AddRange(_handoverAlternativeCarrierRecords); } if (_handoverErrorRecord != null) { childMsg.Add(_handoverErrorRecord); } var childBytes = childMsg.ToByteArray(); var newPayload = new byte[childBytes.Length + 1]; // Frist byte: handover version newPayload[0] = _handoverVersion.Version; // Rest of the payload: child message containing Alternative Carrier records + Error record Array.Copy(childBytes, 0, newPayload, 1, childBytes.Length); _payload = newPayload; }
/// <summary> /// Go through the records stored in this message, parse them and assign /// them to the individual properties. This also checks if the child records /// are actually valid for a Handover Select message. /// </summary> public void SetAndAssignChildRecords(byte[] payloadToParse) { // Create NDEF message based on payload var childRecordsMsg = NdefMessage.FromByteArray(payloadToParse); // Clear previous child records _handoverAlternativeCarrierRecords = null; _handoverErrorRecord = null; // Assign new child records from the source message if (childRecordsMsg.Count < 1) { throw new NdefException(NdefExceptionMessages.ExHandoverSelectMsgInvalidRecords); } foreach (var curChildRecord in childRecordsMsg) { // Alternate carrier record if (curChildRecord.CheckSpecializedType(false) == typeof(NdefHandoverAlternativeCarrierRecord)) { if (HandoverErrorRecord != null) { // Error record needs to be last - there can't be an AC record // after we have already found an error record. throw new NdefException(NdefExceptionMessages.ExHandoverSelectMsgInvalidRecords); } if (_handoverAlternativeCarrierRecords == null) { _handoverAlternativeCarrierRecords = new List <NdefHandoverAlternativeCarrierRecord>(); } _handoverAlternativeCarrierRecords.Add(new NdefHandoverAlternativeCarrierRecord(curChildRecord)); } else if (curChildRecord.CheckSpecializedType(false) == typeof(NdefHandoverErrorRecord)) { if (_handoverErrorRecord != null) { // Only one error record is allowed throw new NdefException(NdefExceptionMessages.ExHandoverSelectMsgInvalidRecords); } _handoverErrorRecord = new NdefHandoverErrorRecord(curChildRecord); } else { // Unknown record found that should not be in this message throw new NdefException(NdefExceptionMessages.ExHandoverSelectMsgInvalidRecords); } } }
/// <summary> /// Reverse function to parseRecords() - this one takes /// the information stored in the individual record instances and assembles /// it into the payload of the base class. /// </summary> /// <remarks> /// As the URI is mandatory, the payload will not be assembled /// if no URI is defined. /// </remarks> /// <returns>Whether assembling the payload was successful.</returns> private bool AssemblePayload() { // Uri is mandatory - don't assemble the payload if it's not set if (RecordUri == null) { return(false); } // URI (mandatory) var message = new NdefMessage { RecordUri }; // Title(s) (optional) if (Titles != null && Titles.Count > 0) { message.AddRange(Titles); } // Action (optional) if (ActionInUse()) { message.Add(_recordAction); } // Size (optional) if (SizeInUse()) { message.Add(_recordSize); } // Mime Type (optional) if (MimeTypeInUse()) { message.Add(_recordMimeType); } // Image (optional) if (ImageInUse()) { message.Add(_recordImage); } SetPayloadAndParse(message.ToByteArray(), false); return(true); }
public ObservableCollection <string> ReadNdefMessage(NdefMessage message) { ObservableCollection <string> collection = new ObservableCollection <string>(); if (message == null) { return(collection); } foreach (NdefRecord record in message) { if (record.CheckSpecializedType(false) == typeof(NdefTextRecord)) { var textRecord = new NdefTextRecord(record); collection.Add(textRecord.Text); } } return(collection); }
public Task <WriteResult> WriteTag(NdefLibrary.Ndef.NdefMessage message, TimeSpan timeout) { return(WriteTag(message, CancellationToken.None, timeout)); }
public Task <WriteResult> WriteTag(NdefLibrary.Ndef.NdefMessage message, System.Threading.CancellationToken cancellationToken) { return(WriteTag(message, cancellationToken, TimeSpan.FromTicks(0))); }
/// <summary> /// Returns the NDEF message parsed from the contents of <paramref name="message"/>. /// </summary> /// <remarks> /// The <paramref name="message"/> parameter is interpreted as the raw message format /// defined in the NFC Forum specifications. /// </remarks> /// <param name="message">Raw byte array containing the NDEF message, which consists /// of 0 or more NDEF records.</param> /// <exception cref="NdefException">Thrown if there is an error parsing the NDEF /// message out of the byte array.</exception> /// <returns>If parsing was successful, the NDEF message containing 0 or more NDEF /// records.</returns> public static NdefMessage FromByteArray(byte[] message) { var result = new NdefMessage(); var seenMessageBegin = false; var seenMessageEnd = false; var partialChunk = new MemoryStream(); var record = new NdefRecord(); uint i = 0; while (i < message.Length) { //Debug.WriteLine("Parsing byte[] to NDEF message. New record starts at {0}", i); // Parse flags out of NDEF message header // The MB flag is a 1-bit field that when set indicates the start of an NDEF message. bool messageBegin = (message[i] & 0x80) != 0; // The ME flag is a 1-bit field that when set indicates the end of an NDEF message. // Note, that in case of a chunked payload, the ME flag is set only in the terminating record chunk of that chunked payload. bool messageEnd = (message[i] & 0x40) != 0; // The CF flag is a 1-bit field indicating that this is either the first record chunk or a middle record chunk of a chunked payload. bool cf = (message[i] & 0x20) != 0; // The SR flag is a 1-bit field indicating, if set, that the PAYLOAD_LENGTH field is a single octet. bool sr = (message[i] & 0x10) != 0; // The IL flag is a 1-bit field indicating, if set, that the ID_LENGTH field is present in the header as a single octet. // If the IL flag is zero, the ID_LENGTH field is omitted from the record header and the ID field is also omitted from the record. bool il = (message[i] & 0x08) != 0; var typeNameFormat = (NdefRecord.TypeNameFormatType)(message[i] & 0x07); //Debug.WriteLine("ShortRecord: " + (sr ? "yes" : "no")); //Debug.WriteLine("Id Length present: " + (il ? "yes" : "no")); if (messageBegin && seenMessageBegin) { throw new NdefException(NdefExceptionMessages.ExMessageBeginLate); } else if (!messageBegin && !seenMessageBegin) { throw new NdefException(NdefExceptionMessages.ExMessageBeginMissing); } else if (messageBegin && !seenMessageBegin) { seenMessageBegin = true; } if (messageEnd && seenMessageEnd) { throw new NdefException(NdefExceptionMessages.ExMessageEndLate); } else if (messageEnd && !seenMessageEnd) { seenMessageEnd = true; } if (cf && (typeNameFormat != NdefRecord.TypeNameFormatType.Unchanged) && partialChunk.Length > 0) { throw new NdefException(NdefExceptionMessages.ExMessagePartialChunk); } // Header length int headerLength = 1; headerLength += (sr) ? 1 : 4; headerLength += (il) ? 1 : 0; if (i + headerLength >= message.Length) { throw new NdefException(NdefExceptionMessages.ExMessageUnexpectedEnd); } // Type length byte typeLength = message[++i]; if ((typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) && (typeLength != 0)) { throw new NdefException(NdefExceptionMessages.ExMessageInvalidChunkedType); } // Payload length (short record?) uint payloadLength; if (sr) { // Short record - payload length is a single octet payloadLength = message[++i]; } else { // No short record - payload length is four octets representing a 32 bit unsigned integer (MSB-first) payloadLength = (uint)((message[++i]) << 24); payloadLength |= (uint)((message[++i]) << 16); payloadLength |= (uint)((message[++i]) << 8); payloadLength |= (uint)((message[++i]) << 0); } // ID length byte idLength; idLength = (byte)(il ? message[++i] : 0); // Total length of content (= type + payload + ID) uint contentLength = typeLength + payloadLength + idLength; if (i + contentLength >= message.Length) { throw new NdefException(NdefExceptionMessages.ExMessageUnexpectedEnd); } if ((typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) && (idLength != 0)) { throw new NdefException(NdefExceptionMessages.ExMessageInvalidChunkedId); } if (typeNameFormat != NdefRecord.TypeNameFormatType.Unchanged) { record.TypeNameFormat = typeNameFormat; } // Read type if (typeLength > 0) { record.Type = new byte[typeLength]; Array.Copy(message, (int)(++i), record.Type, 0, typeLength); i += (uint)typeLength - 1; } // Read ID if (idLength > 0) { record.Id = new byte[idLength]; Array.Copy(message, (int)(++i), record.Id, 0, idLength); i += (uint)idLength - 1; } // Read payload if (payloadLength > 0) { var payload = new byte[payloadLength]; Array.Copy(message, (int)(++i), payload, 0, (int)payloadLength); if (cf) { // chunked payload, except last partialChunk.Write(payload, 0, payload.Length); } else if (typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) { // last chunk of chunked payload partialChunk.Write(payload, 0, payload.Length); record.Payload = partialChunk.ToArray(); } else { // non-chunked payload record.Payload = payload; } i += payloadLength - 1; } if (!cf) { // Add record to the message and create a new record for the next loop iteration result.Add(record); record = new NdefRecord(); } if (!cf && seenMessageEnd) { break; } // move to start of next record ++i; } if (!seenMessageBegin && !seenMessageEnd) { throw new NdefException(NdefExceptionMessages.ExMessageNoBeginOrEnd); } return(result); }
/// <summary> /// Convert all the NDEF records currently stored in the NDEF message to a byte /// array suitable for writing to a tag or sending to another device. /// </summary> /// <returns>The NDEF record(s) converted to an NDEF message.</returns> public byte[] ToByteArray() { // Empty message: single empty record if (Count == 0) { var msg = new NdefMessage { new NdefRecord() }; return(msg.ToByteArray()); } var m = new MemoryStream(); for (int i = 0; i < Count; i++) { var record = this[i]; var flags = (byte)record.TypeNameFormat; // Message begin / end flags. If there is only one record in the message, // both flags are set. if (i == 0) { flags |= 0x80; // MB (message begin = first record in the message) } if (i == Count - 1) { flags |= 0x40; // ME (message end = last record in the message) } // cf (chunked records) not supported yet // SR (Short Record)? if (record.Payload == null || record.Payload.Length < 255) { flags |= 0x10; } // ID present? if (record.Id != null && record.Id.Length > 0) { flags |= 0x08; } m.WriteByte(flags); // Type length if (record.Type != null) { m.WriteByte((byte)record.Type.Length); } else { m.WriteByte(0); } // Payload length 1 byte (SR) or 4 bytes if (record.Payload == null) { m.WriteByte(0); } else { if ((flags & 0x10) != 0) { // SR m.WriteByte((byte)record.Payload.Length); } else { // No SR (Short Record) var payloadLength = (uint)record.Payload.Length; m.WriteByte((byte)(payloadLength >> 24)); m.WriteByte((byte)(payloadLength >> 16)); m.WriteByte((byte)(payloadLength >> 8)); m.WriteByte((byte)(payloadLength & 0x000000ff)); } } // ID length if (record.Id != null && (flags & 0x08) != 0) { m.WriteByte((byte)record.Id.Length); } // Type length if (record.Type != null && record.Type.Length > 0) { m.Write(record.Type, 0, record.Type.Length); } // ID data if (record.Id != null && record.Id.Length > 0) { m.Write(record.Id, 0, record.Id.Length); } // Payload data if (record.Payload != null && record.Payload.Length > 0) { m.Write(record.Payload, 0, record.Payload.Length); } } return(m.ToArray()); }
/// <summary> /// Returns the NDEF message parsed from the contents of <paramref name="message"/>. /// </summary> /// <remarks> /// The <paramref name="message"/> parameter is interpreted as the raw message format /// defined in the NFC Forum specifications. /// </remarks> /// <param name="message">Raw byte array containing the NDEF message, which consists /// of 0 or more NDEF records.</param> /// <exception cref="NdefException">Thrown if there is an error parsing the NDEF /// message out of the byte array.</exception> /// <returns>If parsing was successful, the NDEF message containing 0 or more NDEF /// records.</returns> public static NdefMessage FromByteArray(byte[] message) { var result = new NdefMessage(); var seenMessageBegin = false; var seenMessageEnd = false; var partialChunk = new MemoryStream(); var record = new NdefRecord(); uint i = 0; while (i < message.Length) { //Debug.WriteLine("Parsing byte[] to NDEF message. New record starts at {0}", i); // Parse flags out of NDEF message header bool messageBegin = (message[i] & 0x80) != 0; bool messageEnd = (message[i] & 0x40) != 0; bool cf = (message[i] & 0x20) != 0; bool sr = (message[i] & 0x10) != 0; bool il = (message[i] & 0x08) != 0; var typeNameFormat = (NdefRecord.TypeNameFormatType)(message[i] & 0x07); Debug.WriteLine("ShortRecord: " + (sr ? "yes" : "no")); Debug.WriteLine("Id Length present: " + (il ? "yes" : "no")); if (messageBegin && seenMessageBegin) { throw new NdefException("Message Begin Late"); } else if (!messageBegin && !seenMessageBegin) { throw new NdefException("Begin Missing"); } else if (messageBegin && !seenMessageBegin) { seenMessageBegin = true; } if (messageEnd && seenMessageEnd) { throw new NdefException("End Late"); } else if (messageEnd && !seenMessageEnd) { seenMessageEnd = true; } if (cf && (typeNameFormat != NdefRecord.TypeNameFormatType.Unchanged) && partialChunk.Length > 0) { throw new NdefException("Partial Chunk"); } int headerLength = 1; headerLength += (sr) ? 1 : 4; headerLength += (il) ? 1 : 0; if (i + headerLength >= message.Length) { throw new NdefException("NdefExceptionMessages.ExMessageUnexpectedEnd"); } byte typeLength = message[++i]; if ((typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) && (typeLength != 0)) { throw new NdefException("Invalid Chunk"); } uint payloadLength; if (sr) { // Short record - payload length is a single octet payloadLength = message[++i]; } else { // No short record - payload length is four octets representing a 32 bit unsigned integer (MSB-first) payloadLength = (uint)((message[++i]) << 24); payloadLength |= (uint)((message[++i]) << 16); payloadLength |= (uint)((message[++i]) << 8); payloadLength |= (uint)((message[++i]) << 0); } //Debug.WriteLine("Payload length: " + payloadLength); byte idLength; idLength = (byte)(il ? message[++i] : 0); uint contentLength = typeLength + payloadLength + idLength; if (i + contentLength >= message.Length) { throw new NdefException("Unexpected End"); } //Debug.WriteLine("Content length: {0} (Start at: {1})", contentLength, i); if ((typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) && (idLength != 0)) { throw new NdefException("Invalid Chunk Id"); } if (typeNameFormat != NdefRecord.TypeNameFormatType.Unchanged) { record.TypeNameFormat = typeNameFormat; } if (typeLength > 0) { record.Type = new byte[typeLength]; Array.Copy(message, (int)(++i), record.Type, 0, typeLength); i += (uint)typeLength - 1; } if (idLength > 0) { record.Id = new byte[idLength]; Array.Copy(message, (int)(++i), record.Id, 0, idLength); i += (uint)idLength - 1; } if (payloadLength > 0) { var payload = new byte[payloadLength]; Array.Copy(message, (int)(++i), payload, 0, (int)payloadLength); if (cf) { // chunked payload, except last partialChunk.Write(payload, 0, payload.Length); } else if (typeNameFormat == NdefRecord.TypeNameFormatType.Unchanged) { // last chunk of chunked payload partialChunk.Write(payload, 0, payload.Length); record.Payload = partialChunk.ToArray(); } else { // non-chunked payload record.Payload = payload; } i += payloadLength - 1; } if (!cf) { result.Add(record); record = new NdefRecord(); } if (!cf && seenMessageEnd) { break; } // move to start of next record ++i; } if (!seenMessageBegin && !seenMessageEnd) { throw new NdefException("No Begin Or End"); } return(result); }
static void Main(string[] args) { try { System.IO.StreamReader file = new System.IO.StreamReader("settings.txt"); reader_name = file.ReadLine(); //Console.WriteLine("SETTINGSFILE CONTENT: " + reader_name); } catch (System.IO.FileNotFoundException) { System.Environment.Exit(1); } ConsoleTraceListener consoleTraceListener = new ConsoleTraceListener(); Trace.Listeners.Add(consoleTraceListener); reader = new PCSCReader(); NdefLibrary.Ndef.NdefMessage message = new NdefLibrary.Ndef.NdefMessage(); //string input_text = ""; //while (input_text != "joo") //{ try { //turn_on_antenna(); //reader.SCard.Connect("",SCARD_SHARE_MODE.Direct, SCARD_PROTOCOL.Tx); //reader.Connect(); //reader.ActivateCard(); //set_buzzer_on(); //set_target_mode(); if (args[0] == "read") { //Console.WriteLine("Initing stuff"); //reader.SCard.Connect(reader.SCard.ListReaders()[1], SCARD_SHARE_MODE.Direct, SCARD_PROTOCOL.Default); //Console.WriteLine(reader.SCard.GetSCardCtlCode(3500)); reader.Connect(reader_name); Console.WriteLine(reader.SCard.ListReaders()[0]); reader.ActivateCard(SCARD_SHARE_MODE.Shared, SCARD_PROTOCOL.T1); turn_on_antenna(); message = NdefLibrary.Ndef.NdefMessage.FromByteArray(find_ndef()); Console.WriteLine("rd: " + parse_record(message)); //Console.WriteLine("Please press any key..."); //string input_text = Console.ReadLine(); //turn_off_antenna(); } else if (args[0] == "write" && args.Length == 2) { Console.WriteLine("writing to tag: ", args[1]); reader.Connect(); reader.ActivateCard(SCARD_SHARE_MODE.Shared, SCARD_PROTOCOL.T1); turn_on_antenna(); write_to_tag(args[1]); Console.WriteLine("wrote to tag:" + args[1]); } else if (args[0] == "list") { Console.WriteLine(reader.SCard.ListReaders()); System.Environment.Exit(1); } else { Console.WriteLine("Bad arguments"); reader.SCard.Disconnect(); System.Environment.Exit(1); } //WinSCard yhteys = new WinSCard(); //yhteys.Connect(yhteys.ListReaders()[0]); //yhteys.Control(0, hex_string_to_byte_array(APDU_commands[]), ); //write_to_tag(input_text = "Hassulla Tassulla kiva paijaa massua ai että kun on hassua:3"); //reader.ActivateCard(); //try_this(); //set_initiator_mode(); //For some reason Direct commands only work after card has been activated (the command above) //Also the reader resets to normal state after it's been unplugged. //TODO: check if mode changes can be made permanent //RespApdu respApdu = reader.Exchange(APDU_commands["get_card_uid"]); // Get Card UID ... /*if (respApdu.SW1SW2 == 0x9000) * { * Console.WriteLine("UID = 0x" + HexFormatting.ToHexString(respApdu.Data, true)); * }*/ //message = NdefLibrary.Ndef.NdefMessage.FromByteArray(find_ndef()); //parse_record(message); //set_initiator_mode(); //string input_text = Console.ReadLine(); //System.Environment.Exit(1); } catch (WinSCardException ex) { Console.WriteLine(ex.WinSCardFunctionName + " Error 0x" + ex.Status.ToString("X08") + ": " + ex.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { //direct_command(APDU_commands["enable_picc_polling"]); //turn_off_antenna(); //Console.WriteLine("Please press any key..."); //string input_text = Console.ReadLine(); turn_off_antenna(); reader.SCard.Disconnect(); System.Environment.Exit(1); } }