ndef.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Copyright (c) 2021 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "ndef.h"
  16. #include <string.h>
  17. #include "nfcForum.h"
  18. #include "rtdTypes.h"
  19. #include "NT3H.h"
  20. typedef uint8_t (*composeRtdPtr)(const NDEFDataStr *ndef, NDEFRecordStr *ndefRecord, uint8_t *I2CMsg);
  21. static composeRtdPtr composeRtd[] = {composeRtdText,composeRtdUri};
  22. int16_t firstRecord(UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition) {
  23. NDEFRecordStr record;
  24. NDEFHeaderStr header;
  25. uint8_t typeFunct=0;
  26. switch (data->rtdType){
  27. case RTD_TEXT:
  28. typeFunct =0;
  29. break;
  30. case RTD_URI:
  31. typeFunct = 1;
  32. break;
  33. default:
  34. return -1;
  35. break;
  36. }
  37. // clear all buffers
  38. memset(&record,0,sizeof(NDEFRecordStr));
  39. memset(nfcPageBuffer, 0, NFC_PAGE_SIZE);
  40. // this is the first record
  41. nfcPageBuffer[0] = NDEF_START_BYTE;
  42. composeNDEFMBME(true, true, &record);
  43. uint8_t recordLength;
  44. // prepare the NDEF Header and payload
  45. if(data->rtdPayloadlength>248){
  46. recordLength = composeRtd[typeFunct](data, &record, &nfcPageBuffer[4]);
  47. header.payloadLength = data->rtdPayloadlength + recordLength;
  48. }
  49. else{
  50. recordLength = composeRtd[typeFunct](data, &record, &nfcPageBuffer[2]);
  51. header.payloadLength = data->rtdPayloadlength + recordLength;
  52. }
  53. if(header.payloadLength>255){
  54. nfcPageBuffer[1] = 0xff;
  55. nfcPageBuffer[2] = header.payloadLength/256;
  56. nfcPageBuffer[3] = header.payloadLength%256;
  57. return 4+recordLength;
  58. }
  59. nfcPageBuffer[1] = header.payloadLength;
  60. return 2+recordLength;
  61. }
  62. int16_t addRecord(UncompletePageStr *pageToUse, const NDEFDataStr *data, RecordPosEnu rtdPosition) {
  63. NDEFRecordStr record;
  64. NDEFHeaderStr header={0};
  65. uint8_t newRecordPtr, mbMe;
  66. bool ret = true;
  67. uint8_t tmpBuffer[NFC_PAGE_SIZE];
  68. uint8_t typeFunct=0;
  69. switch (data->rtdType){
  70. case RTD_TEXT:
  71. typeFunct =0;
  72. break;
  73. case RTD_URI:
  74. typeFunct = 1;
  75. break;
  76. default:
  77. return -1;
  78. break;
  79. }
  80. // first Change the Header of the first Record
  81. NT3HReadHeaderNfc(&newRecordPtr, &mbMe);
  82. record.header = mbMe;
  83. composeNDEFMBME(true, false, &record); // this is the first record
  84. mbMe = record.header;
  85. memset(&record,0,sizeof(NDEFRecordStr));
  86. memset(tmpBuffer,0,NFC_PAGE_SIZE);
  87. // prepare second record
  88. uint8_t recordLength = composeRtd[typeFunct](data, &record, tmpBuffer);
  89. if (rtdPosition == NDEFMiddlePos) {
  90. // this is a record in the middle adjust it on the buffet
  91. composeNDEFMBME(false, false, &record);
  92. } else if (rtdPosition == NDEFLastPos){
  93. // this is the last record adjust it on the buffet
  94. composeNDEFMBME(false, true, &record);
  95. }
  96. tmpBuffer[0] = record.header;
  97. header.payloadLength += data->rtdPayloadlength + recordLength;
  98. // save the new value of length on the first page
  99. NT3HWriteHeaderNfc((newRecordPtr+header.payloadLength), mbMe);
  100. // use the last valid page and start to add the new record
  101. NT3HReadUserData(pageToUse->page);
  102. if (pageToUse->usedBytes+recordLength< NFC_PAGE_SIZE) {
  103. memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, recordLength);
  104. return recordLength+pageToUse->usedBytes;
  105. } else {
  106. uint8_t byteToCopy = NFC_PAGE_SIZE-pageToUse->usedBytes;
  107. memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, byteToCopy);
  108. NT3HWriteUserData(pageToUse->page, nfcPageBuffer);
  109. // update the info with the new page
  110. pageToUse->page++;
  111. pageToUse->usedBytes=recordLength-byteToCopy;
  112. //copy the remain part in the pageBuffer because this is what the caller expect
  113. memcpy(nfcPageBuffer, &tmpBuffer[byteToCopy], pageToUse->usedBytes);
  114. return pageToUse->usedBytes;
  115. }
  116. }
  117. static bool writeUserPayload(int16_t payloadPtr, const NDEFDataStr *data, UncompletePageStr *addPage){
  118. uint16_t addedPayload;
  119. bool ret=false;
  120. uint8_t finish=payloadPtr+data->rtdPayloadlength;
  121. bool endRecord = false;
  122. uint8_t copyByte=0;
  123. // if the header is less then the NFC_PAGE_SIZE, fill it with the payload
  124. if (NFC_PAGE_SIZE>payloadPtr) {
  125. if (data->rtdPayloadlength > NFC_PAGE_SIZE-payloadPtr)
  126. copyByte = NFC_PAGE_SIZE-payloadPtr;
  127. else
  128. copyByte = data->rtdPayloadlength;
  129. }
  130. // Copy the payload
  131. memcpy(&nfcPageBuffer[payloadPtr], data->rtdPayload, copyByte);
  132. addedPayload = copyByte;
  133. //if it is sufficient one send add the NDEF_END_BYTE
  134. if ((addedPayload >= data->rtdPayloadlength)&&((payloadPtr+copyByte) < NFC_PAGE_SIZE)) {
  135. nfcPageBuffer[(payloadPtr+copyByte)] = NDEF_END_BYTE;
  136. endRecord = true;
  137. }
  138. ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
  139. while (!endRecord) {
  140. addPage->page++; // move to a new register
  141. memset(nfcPageBuffer,0,NFC_PAGE_SIZE);
  142. //special case just the NDEF_END_BYTE remain out
  143. if (addedPayload == data->rtdPayloadlength) {
  144. nfcPageBuffer[0] = NDEF_END_BYTE;
  145. ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
  146. endRecord = true;
  147. if (ret == false) {
  148. errNo = NT3HERROR_WRITE_NDEF_TEXT;
  149. }
  150. goto end;
  151. }
  152. if (addedPayload < data->rtdPayloadlength) {
  153. // add the NDEF_END_BYTE if there is enough space
  154. if ((data->rtdPayloadlength-addedPayload) < NFC_PAGE_SIZE){
  155. memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], (data->rtdPayloadlength-addedPayload));
  156. nfcPageBuffer[(data->rtdPayloadlength-addedPayload)] = NDEF_END_BYTE;
  157. } else {
  158. memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], NFC_PAGE_SIZE);
  159. }
  160. addedPayload += NFC_PAGE_SIZE;
  161. ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
  162. if (ret == false) {
  163. errNo = NT3HERROR_WRITE_NDEF_TEXT;
  164. goto end;
  165. }
  166. } else {
  167. endRecord = true;
  168. }
  169. }
  170. end:
  171. return ret;
  172. }
  173. typedef int16_t (*addFunct_T) (UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition);
  174. static addFunct_T addFunct[] = {firstRecord, addRecord, addRecord};
  175. bool NT3HwriteRecord(const NDEFDataStr *data) {
  176. uint8_t recordLength=0, mbMe;
  177. UncompletePageStr addPage;
  178. addPage.page = 0;
  179. // calculate the last used page
  180. if (data->ndefPosition != NDEFFirstPos ) {
  181. NT3HReadHeaderNfc(&recordLength, &mbMe);
  182. addPage.page = (recordLength+sizeof(NDEFHeaderStr)+1)/NFC_PAGE_SIZE;
  183. //remove the NDEF_END_BYTE byte because it will overwrite by the new Record
  184. addPage.usedBytes = (recordLength+sizeof(NDEFHeaderStr)+1)%NFC_PAGE_SIZE - 1;
  185. }
  186. // call the appropriate function and consider the pointer
  187. // within the NFC_PAGE_SIZE that need to be used
  188. int16_t payloadPtr = addFunct[data->ndefPosition](&addPage, data, data->ndefPosition);
  189. if (payloadPtr == -1) {
  190. errNo = NT3HERROR_TYPE_NOT_SUPPORTED;
  191. return false;
  192. }
  193. return writeUserPayload(payloadPtr, data, &addPage);
  194. }