text: /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
   *
   * The information contained herein is property of Nordic Semiconductor ASA.
   * Terms and conditions of usage are described in detail in NORDIC
   * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
   *
   * Licensees are granted free, non-transferable use of the information. NO
   * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
   * the file.
   *
   */
  
  #include <string.h>
  #include "nfc_ndef_record.h"
  #include "app_util.h"
  #include "nrf.h"
  
  
  /* Sum of sizes of fields: TNF-flags, Type Length, Payload Length in long NDEF record. */
  #define NDEF_RECORD_BASE_LONG_SIZE          (2 + NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE)
  
  __STATIC_INLINE uint32_t record_header_size_calc(nfc_ndef_record_desc_t const * p_ndef_record_desc)
  {
      uint32_t len = NDEF_RECORD_BASE_LONG_SIZE;
  
      len += p_ndef_record_desc->id_length + p_ndef_record_desc->type_length;
  
      if (p_ndef_record_desc->id_length > 0)
      {
          len++;
      }
  
      return len;
  }
  
  
  ret_code_t nfc_ndef_record_encode(nfc_ndef_record_desc_t const * p_ndef_record_desc,
                                    nfc_ndef_record_location_t     record_location,
                                    uint8_t                      * p_record_buffer,
                                    uint32_t                     * p_record_len)
  {
      uint8_t * p_flags;              // use as pointer to TNF + flags field
      uint8_t * p_payload_len = NULL; // use as pointer to payload length field
      uint32_t  record_payload_len;
  
      if (p_ndef_record_desc == NULL)
      {
          return NRF_ERROR_NULL;
      }
  
      // count record length without payload
      uint32_t record_header_len = record_header_size_calc(p_ndef_record_desc);
      uint32_t err_code          = NRF_SUCCESS;
  
      if (p_record_buffer != NULL)
      {
          /* verify location range */
          if ((record_location & (~NDEF_RECORD_LOCATION_MASK)) != 0x00)
          {
              return NRF_ERROR_INVALID_PARAM;
          }
  
          /* verify if there is enough available memory */
          if (record_header_len > *p_record_len)
          {
              return NRF_ERROR_NO_MEM;
          }
  
          p_flags = p_record_buffer;
          p_record_buffer++;
  
          // set location bits and clear other bits in 1st byte.
          *p_flags = record_location;
  
          *p_flags |= p_ndef_record_desc->tnf;
  
          /* TYPE LENGTH */
          *(p_record_buffer++) = p_ndef_record_desc->type_length;
  
          // use always long record and remember payload len field memory offset.
          p_payload_len    = p_record_buffer;
          p_record_buffer += NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE;
  
          /* ID LENGTH - option */
          if (p_ndef_record_desc->id_length > 0)
          {
              *(p_record_buffer++) = p_ndef_record_desc->id_length;
  
              /* IL flag */
              *p_flags |= NDEF_RECORD_IL_MASK;
          }
  
          /* TYPE */
          memcpy(p_record_buffer, p_ndef_record_desc->p_type, p_ndef_record_desc->type_length);
          p_record_buffer += p_ndef_record_desc->type_length;
  
          /* ID */
          if (p_ndef_record_desc->id_length > 0)
          {
              memcpy(p_record_buffer, p_ndef_record_desc->p_id, p_ndef_record_desc->id_length);
              p_record_buffer += p_ndef_record_desc->id_length;
          }
  
          // count how much memory is left in record buffer for payload field.
          record_payload_len = (*p_record_len - record_header_len);
      }
  
      /* PAYLOAD */
      if (p_ndef_record_desc->payload_constructor != NULL)
      {
          err_code =
              p_ndef_record_desc->payload_constructor(p_ndef_record_desc->p_payload_descriptor,
                                                      p_record_buffer,
                                                      &record_payload_len);
  
          if (err_code != NRF_SUCCESS)
          {
              return err_code;
          }
      }
      else
      {
          return NRF_ERROR_NULL;
      }
  
      if (p_record_buffer != NULL)
      {
          /* PAYLOAD LENGTH */
          (void) uint32_big_encode(record_payload_len, p_payload_len);
      }
  
      *p_record_len = record_header_len + record_payload_len;
  
      return NRF_SUCCESS;
  }
  
  
  ret_code_t nfc_ndef_bin_payload_memcopy(nfc_ndef_bin_payload_desc_t * p_payload_descriptor,
                                          uint8_t                     * p_buffer,
                                          uint32_t                    * p_len)
  {
  
      if (p_buffer != NULL)
      {
          if ( *p_len < p_payload_descriptor->payload_length)
          {
              return NRF_ERROR_NO_MEM;
          }
  
          memcpy(p_buffer,
                 p_payload_descriptor->p_payload,
                 p_payload_descriptor->payload_length);
      }
  
      *p_len = p_payload_descriptor->payload_length;
  
      return NRF_SUCCESS;
  }
  
  
  