Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers isodep_target.c Source File

isodep_target.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 /**
00018  * \file isodep_target.c
00019  * \copyright Copyright (c) ARM Ltd 2015
00020  * \author Donatien Garnier
00021  */
00022 
00023 #define __DEBUG__ 0
00024 #ifndef __MODULE__
00025 #define __MODULE__ "isodep_target.c"
00026 #endif
00027 
00028 #include "isodep_target.h"
00029 
00030 #include "stack/nfc_errors.h"
00031 #include "transceiver/transceiver.h"
00032 
00033 //Private defines
00034 #define RATS 0xE0
00035 #define FSDI_TO_FSD(x) (((x)<5)?(((x)<<3) + 16):((x)<8)?(((x)<<5)-96):256)
00036 #define FSC_TO_FSCI(x) (((x)<=48)?(((x)-16)>>3):((x)<=128)?(((x)+96)>>5):8) //returns the closest lower or equal value
00037 #define DID(x) ((x) & 0x0F)
00038 #define FSDI(x) (((x) >> 4) & 0x0F)
00039 
00040 #define FSCI_TO_FSC(x) FSDI_TO_FSD(x)
00041 #define FSD_TO_FSDI(x) FSC_TO_FSCI(x)
00042 
00043 //#define DI_TO_D(x) (1 << (x))
00044 #define DI_TO_BITRATE(x) ((RF_BITRATE)((x) + RF_BITRATE_106K))
00045 
00046 
00047 #define GET_FRAME_TYPE(pcb) ((((pcb) & 0xF0) == 0xD0)?PPS_FRAME:(((pcb) & 0xC0) == (0x00 << 6))?I_FRAME:((((pcb) & 0xC0) == (0x2 << 6))?R_FRAME:S_FRAME))
00048 
00049 #define I_BLOCK_PCB 0
00050 #define R_BLOCK_PCB 2
00051 #define S_BLOCK_PCB 3
00052 
00053 #define PCB_TYPE(pcb) (((pcb)>>6)&0x03)
00054 
00055 #define BUILD_I_BLOCK_PCB(chaining, cid, nad, block_toggle) ( (0x0 << 6) | (((chaining)?1:0) << 4) \
00056     | (((cid)?1:0) << 3) | (((nad)?1:0) << 2) | (1 << 1) | (((block_toggle)?1:0)) )
00057 #define BUILD_S_BLOCK_PCB(cid, wtx_n_deselect) ( (0x3 << 6) | (((wtx_n_deselect)?0x3:0) << 4) \
00058     | (((cid)?1:0) << 3) | (1 << 1) )
00059 #define BUILD_R_BLOCK_PCB(cid, block_toggle, nak) ( (0x2 << 6) | (1 <<5) | (((nak)?1:0) << 4) \
00060     | (((cid)?1:0) << 3) | (1 << 1) | (((block_toggle)?1:0)) )
00061 
00062 #define PCB_IS_CID(pcb) (((pcb) & (1 << 3))?true:false)
00063 #define PCB_BLOCK_TOGGLE(pcb) (((pcb) & 1)?true:false)
00064 #define PCB_CHAINING(pcb) (((pcb) & 0x10)?true:false)
00065 #define PCB_NACK(pcb) (((pcb) & 0x10)?true:false)
00066 #define PCB_WTX(pcb) (((pcb)&0x30)==0x30)
00067 
00068 #define WTXM_DEFAULT 10
00069 
00070 //Parameters
00071 #define FSC 256 //Maximum frame size the PICC (us) can receive -- TODO should be a parameter at some point -- linked to PN512 buffer
00072 #define SFGI 2 //Guard time ~ 1.2ms
00073 //#define FWI 6 //Max time before answer is ~ 19.3ms
00074 #define FWI 14 //Max time before answer is ~ 19.3ms
00075 
00076 typedef enum __dep_type dep_type_t;
00077 enum __dep_type {
00078     dep_type_information,
00079     dep_type_response,
00080     dep_type_supervisory,
00081 };
00082 
00083 //Local functions
00084 static void dep_init(nfc_tech_isodep_target_t *pIsodepTarget);
00085 static bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget);
00086 
00087 static void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber);
00088 static void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber);
00089 static void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm);
00090 
00091 static dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget);
00092 static void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber);
00093 static void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber);
00094 static void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm);
00095 
00096 static void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected);
00097 
00098 static void command_init(nfc_tech_isodep_target_t *pIsodepTarget);
00099 
00100 static nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget);
00101 static nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget);
00102 
00103 static nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget);
00104 static nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget);
00105 
00106 static void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait);
00107 static void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData);
00108 
00109 //High-level Target functions
00110 void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver,
00111                                  ac_buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData)
00112 {
00113     pIsodepTarget->pTransceiver = pTransceiver;
00114 
00115     pIsodepTarget->pHist = pHist;
00116 
00117     pIsodepTarget->disconnectedCb = disconnectedCb;
00118     pIsodepTarget->pUserData = pUserData;
00119 
00120     dep_init(pIsodepTarget);
00121     command_init(pIsodepTarget);
00122 }
00123 
00124 nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget)
00125 {
00126     NFC_DBG("Connecting");
00127     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING;
00128 
00129     transceiver_set_crc(pIsodepTarget->pTransceiver, true, true);
00130     command_transceiver_cb(pIsodepTarget->pTransceiver, NFC_OK, pIsodepTarget);
00131 
00132     return NFC_OK;
00133 }
00134 
00135 void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget)
00136 {
00137     // This should not be called within a callback
00138 
00139     transceiver_abort(pIsodepTarget->pTransceiver);
00140 
00141     dep_disconnected(pIsodepTarget, false);
00142 }
00143 
00144 nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, ac_istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData)
00145 {
00146     if (pIsodepTarget->dep.pReqStream != NULL) {
00147         return NFC_ERR_BUSY;
00148     }
00149 
00150     pIsodepTarget->dep.pResStream = pStream;
00151     pIsodepTarget->dep.resCb = cb;
00152     pIsodepTarget->dep.pResUserData = pUserData;
00153 
00154     //Do we need to start transceiving?
00155     if (pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) {
00156         command_reply(pIsodepTarget, false); //Force reply
00157     }
00158 
00159     return NFC_OK;
00160 }
00161 
00162 nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ac_ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData)
00163 {
00164     if (pIsodepTarget->dep.pResStream != NULL) {
00165         return NFC_ERR_BUSY;
00166     }
00167 
00168     pIsodepTarget->dep.pReqStream = pStream;
00169     pIsodepTarget->dep.reqCb = cb;
00170     pIsodepTarget->dep.pReqUserData = pUserData;
00171 
00172     return NFC_OK;
00173 }
00174 
00175 //DEP Layer
00176 void dep_init(nfc_tech_isodep_target_t *pIsodepTarget)
00177 {
00178     //ac_buffer_init(&pIsodepTarget->dep.res, NULL, 0);
00179     pIsodepTarget->dep.pReqStream = NULL;
00180     pIsodepTarget->dep.pResStream = NULL;
00181 
00182     pIsodepTarget->dep.reqCb = NULL;
00183     pIsodepTarget->dep.pReqUserData = NULL;
00184 
00185     pIsodepTarget->dep.resCb = NULL;
00186     pIsodepTarget->dep.pResUserData = NULL;
00187 
00188     pIsodepTarget->dep.blockNumber = 1; //Rule C
00189 
00190     //pIsodepTarget->dep.pduState = ISO_DEP_TARGET_DEP_PDU_IDLE;
00191     pIsodepTarget->dep.chaining = false;
00192     pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_IDLE;
00193 }
00194 
00195 bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget)
00196 {
00197     //Anything to send back?
00198     if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED) {
00199         return true;
00200     }
00201 
00202     if ((pIsodepTarget->dep.pResStream != NULL)) {
00203         return true;
00204     } else {
00205         return false;
00206     }
00207 }
00208 
00209 void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber)
00210 {
00211     (void) blockNumber;
00212 
00213     pIsodepTarget->dep.blockNumber++;
00214     pIsodepTarget->dep.blockNumber %= 2;
00215 
00216     // Note: callbacks can call nfc_tech_isodep_target_transmit() - however we must make sure that we wait AFTER this routine has been processed to actually transmit
00217     // To do so, reset state to ATS_RES_SENT state
00218     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT;
00219 
00220     if (!pIsodepTarget->dep.chaining
00221             && (pIsodepTarget->dep.pResStream != NULL)) {
00222         //Sent the full frame
00223         pIsodepTarget->dep.pResStream = NULL;
00224         pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pResUserData);
00225     }
00226     if (pIsodepTarget->dep.pReqStream != NULL) {
00227         // Pull more
00228         ac_ostream_push(pIsodepTarget->dep.pReqStream, pReq, !moreInformation);
00229         if (!moreInformation) {
00230             //Got the full frame
00231             pIsodepTarget->dep.pReqStream = NULL;
00232             pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pReqUserData);
00233         }
00234     }
00235 
00236     // Update state
00237     pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED;
00238     pIsodepTarget->dep.chaining = moreInformation;
00239 }
00240 
00241 void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber)
00242 {
00243     if (blockNumber != pIsodepTarget->dep.blockNumber) {
00244         //Should be NACK
00245         pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED;
00246     } else {
00247         if (ack) {
00248             pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED;
00249         } else {
00250             pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED;
00251         }
00252     }
00253 }
00254 
00255 void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm)
00256 {
00257     (void) wtxm;
00258 
00259     if (wtxNDeselect) {
00260         if ((pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_WTX_SENT)) {
00261             NFC_WARN("Unexpected WTX frame");
00262         }
00263         pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED;
00264     } else {
00265         pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED;
00266     }
00267 }
00268 
00269 dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget)
00270 {
00271     dep_type_t depType;
00272     switch (pIsodepTarget->dep.frameState) {
00273         case ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED:
00274             depType = dep_type_supervisory; //Deselect
00275             break;
00276         case ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED:
00277         case ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED:
00278             if (pIsodepTarget->dep.chaining) { //Need to ack?
00279                 depType = dep_type_response;
00280             } else if (pIsodepTarget->dep.pResStream != NULL) { //Anything to send back?
00281                 depType = dep_type_information;
00282             } else {
00283                 depType = dep_type_supervisory; //WTX
00284             }
00285             break;
00286         case ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED:
00287             if ((pIsodepTarget->dep.pResStream != NULL) && (pIsodepTarget->dep.chaining)) {
00288                 depType = dep_type_information;
00289             } else {
00290                 depType = dep_type_supervisory; //WTX
00291             }
00292             break;
00293         case ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED:
00294             depType = dep_type_response; //Should send ACK
00295             break;
00296         case ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED:
00297             depType = dep_type_information;
00298             break;
00299         default:
00300             depType = dep_type_supervisory; //ATN
00301             break;
00302     }
00303     return depType;
00304 }
00305 
00306 void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber)
00307 {
00308     *pBlockNumber = pIsodepTarget->dep.blockNumber;
00309     if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED) {
00310         if (pIsodepTarget->dep.pResStream != NULL) {
00311             bool lastFrame = true;
00312             ac_istream_pull(pIsodepTarget->dep.pResStream, &pIsodepTarget->dep.res, &lastFrame, maxLength);
00313             pIsodepTarget->dep.chaining = !lastFrame;
00314         }
00315     } else {
00316         //Retransmit previous frame (leave it as it is)
00317     }
00318     *ppRes = &pIsodepTarget->dep.res;
00319     *pMoreInformation = pIsodepTarget->dep.chaining;
00320     pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT;
00321 }
00322 
00323 void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber)
00324 {
00325     //Continue chaining or send ACK
00326     *pAck = true;
00327     *pBlockNumber = pIsodepTarget->dep.blockNumber;
00328     pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_SENT;
00329 }
00330 
00331 void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm)
00332 {
00333     if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED) {
00334         *pWtxNDeselect = false;
00335         pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT;
00336     } else {
00337         *pWtxNDeselect = true;
00338         *pWtxm = WTXM_DEFAULT;
00339         pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_SENT;
00340     }
00341 }
00342 
00343 void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected)
00344 {
00345     //Call callbacks if needed
00346     if (pIsodepTarget->dep.pReqStream != NULL) {
00347         pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pReqUserData);
00348         pIsodepTarget->dep.pReqStream = NULL;
00349     }
00350     if (pIsodepTarget->dep.pReqStream != NULL) {
00351         pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pResUserData);
00352         pIsodepTarget->dep.pResStream = NULL;
00353     }
00354     if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_DISCONNECTED) {
00355         pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED;
00356         pIsodepTarget->disconnectedCb((nfc_tech_isodep_t *)pIsodepTarget, deselected, pIsodepTarget->pUserData);
00357     }
00358 }
00359 
00360 //Commands Layer
00361 void command_init(nfc_tech_isodep_target_t *pIsodepTarget)
00362 {
00363     ac_buffer_builder_init(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.respBuf, sizeof(pIsodepTarget->commands.respBuf));
00364     pIsodepTarget->commands.pReq = NULL;
00365     // Update if/when we support DIDs
00366     //pIsodepTarget->commands.did = 0;
00367     //pIsodepTarget->commands.didUsed = false;
00368     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED;
00369     pIsodepTarget->commands.inPayloadSize = 0;
00370 }
00371 
00372 nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget)
00373 {
00374     //Check we are in a correct state -- this should be the first command received
00375     if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_CONNECTING) {
00376         return NFC_ERR_PROTOCOL;
00377     }
00378 
00379     if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 2) {
00380         NFC_ERR("Payload too short");
00381         return NFC_ERR_PROTOCOL;
00382     }
00383 
00384     ac_buffer_read_n_skip(pIsodepTarget->commands.pReq, 1);
00385 
00386     uint8_t b = ac_buffer_read_nu8(pIsodepTarget->commands.pReq);
00387 
00388     //Save DID -- not supported for now
00389     //pIsodepTarget->commands.did = DID(b);
00390 
00391     uint8_t fsdi = FSDI(b);
00392     pIsodepTarget->commands.inPayloadSize = FSDI_TO_FSD(fsdi);
00393 
00394     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD;
00395 
00396     return NFC_OK;
00397 }
00398 
00399 nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget)
00400 {
00401     if (pIsodepTarget->commands.state < ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT) {
00402         return NFC_ERR_PROTOCOL;
00403     }
00404 
00405     if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) {
00406         NFC_ERR("Payload too short");
00407         return NFC_ERR_PROTOCOL;
00408     }
00409 
00410     uint8_t pcb = ac_buffer_read_nu8(pIsodepTarget->commands.pReq);
00411 
00412     // Udpate if/when we support DIDs
00413     /*
00414       if( pfb & PFB_DID )
00415       {
00416         uint8_t did = ac_buffer_read_nu8(pIsodepTarget->commands.pReq);
00417         if( pIsodepTarget->commands.did != did )
00418         {
00419           //Not for us
00420           return NFC_ERR_PROTOCOL;
00421         }
00422         pIsodepTarget->commands.didUsed = true;
00423       }
00424       else
00425       {
00426         pIsodepTarget->commands.didUsed = false;
00427       }
00428 
00429       if( pfb & PFB_NAD )
00430       {
00431         ac_buffer_read_nu8(pIsodepTarget->commands.pReq); //Skip NAD
00432       }
00433     */
00434 
00435     uint8_t wtxm = 0;
00436     switch (PCB_TYPE(pcb)) {
00437         case I_BLOCK_PCB:
00438             dep_req_information(pIsodepTarget, pIsodepTarget->commands.pReq, PCB_CHAINING(pcb), PCB_BLOCK_TOGGLE(pcb));
00439             break;
00440         case R_BLOCK_PCB:
00441             dep_req_response(pIsodepTarget, !PCB_NACK(pcb), PCB_BLOCK_TOGGLE(pcb));
00442             break;
00443         case S_BLOCK_PCB:
00444             if (PCB_WTX(pcb)) {
00445                 if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) {
00446                     NFC_ERR("Payload too short");
00447                     return NFC_ERR_PROTOCOL;
00448                 }
00449                 wtxm = ac_buffer_read_nu8(pIsodepTarget->commands.pReq);
00450             }
00451             dep_req_supervisory(pIsodepTarget, PCB_WTX(pcb), wtxm);
00452             break;
00453         default:
00454             NFC_ERR("PCB is invalid");
00455             return NFC_ERR_PROTOCOL;
00456     }
00457 
00458     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD;
00459 
00460     return NFC_OK;
00461 }
00462 
00463 nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget)
00464 {
00465     //Send ATS back
00466     if (ac_buffer_builder_writable(&pIsodepTarget->commands.respBldr) < 5) {
00467         return NFC_ERR_BUFFER_TOO_SMALL;
00468     }
00469 
00470     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (5 + ac_buffer_size(pIsodepTarget->pHist)) & 0xFF);
00471 
00472     //T0
00473     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0x7 << 4) | FSC_TO_FSCI(FSC));   //TA(1), TB(1) and TC(1) are transmitted
00474 
00475     //TA(1)
00476     //For now only 106kbps supported
00477     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (1 << 7) | (0x0 << 4) | 0x0);
00478 
00479     //TODO when supporting other bitrates
00480     //ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 7) | (0x3 << 4) | 0x3); //106, 212, 414 kbps bitrates
00481 
00482     //TB(1)
00483     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (FWI << 4) | SFGI); //Specify guard-time and time between frames
00484 
00485     //TC(1)
00486     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 1) | 0); //DID not supported, NAD not supported
00487 
00488     ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pIsodepTarget->pHist); //Queue general bytes
00489 
00490     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT;
00491 
00492     //TODO PPS
00493 
00494     return NFC_OK;
00495 }
00496 
00497 nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget)
00498 {
00499     uint8_t pcb = 0;
00500 
00501     // If/when supporting DIDs
00502     /*
00503     if( pIsodepTarget->commands.didUsed )
00504     {
00505       pcb |= PFB_DID;
00506     }*/
00507 
00508     ac_buffer_t *pDepBuf = NULL;
00509     bool moreInformation = false;
00510     bool ack = false;
00511     bool wtxNDeselect = false;
00512     uint8_t wtxm = 0;
00513     uint8_t blockNumber = 0;
00514 
00515     size_t maxLength = pIsodepTarget->commands.inPayloadSize - 1;
00516 
00517     switch (dep_res_type(pIsodepTarget)) {
00518         case dep_type_information:
00519             dep_res_information(pIsodepTarget, maxLength, &pDepBuf, &moreInformation, &blockNumber);
00520             pcb = BUILD_I_BLOCK_PCB(moreInformation, false, false, blockNumber);
00521             break;
00522         case dep_type_response:
00523             dep_res_response(pIsodepTarget, &ack, &blockNumber);
00524             pcb = BUILD_R_BLOCK_PCB(0, blockNumber, !ack);
00525             break;
00526         case dep_type_supervisory:
00527             dep_res_supervisory(pIsodepTarget, &wtxNDeselect, &wtxm);
00528             pcb = BUILD_S_BLOCK_PCB(0, wtxNDeselect);
00529             break;
00530     }
00531 
00532     ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pcb);
00533     /*
00534       if( pIsodepTarget->commands.didUsed )
00535       {
00536         ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.did);
00537       }
00538     */
00539     if (pDepBuf != NULL) {
00540         ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pDepBuf);
00541     } else if (wtxNDeselect) {
00542         ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, wtxm);
00543     }
00544 
00545     pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT;
00546 
00547     return NFC_OK;
00548 }
00549 
00550 void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait)
00551 {
00552     nfc_err_t ret;
00553 
00554     //Check whether we want to reply or wait for the higher layer to send us something
00555     if ((pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) && depWait && !dep_ready(pIsodepTarget)) {
00556         return;
00557     }
00558 
00559     //Reply
00560     ac_buffer_builder_reset(&pIsodepTarget->commands.respBldr);
00561 
00562     switch (pIsodepTarget->commands.state) {
00563         case ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD:
00564             ret = command_ats_res(pIsodepTarget);
00565             break;
00566         case ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD:
00567             ret = command_dep_res(pIsodepTarget);
00568             break;
00569         default:
00570             NFC_ERR("Unknown state %d", pIsodepTarget->commands.state);
00571             //Go back to receive mode
00572             nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget);
00573             return;
00574     }
00575 
00576     if (ret) {
00577         NFC_ERR("Error %d", ret);
00578         //Go back to receive mode
00579         nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget);
00580         return;
00581     }
00582 
00583     NFC_DBG("Transceive");
00584 
00585     if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) {
00586         transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, false, true);
00587     } else {
00588         transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, true, false);
00589     }
00590 
00591     NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr));)
00592 
00593     //Send next frame
00594     transceiver_set_write(pIsodepTarget->pTransceiver, ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr));
00595     nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget);
00596 
00597     NFC_DBG("Processed");
00598 }
00599 
00600 void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData)
00601 {
00602     nfc_tech_isodep_target_t *pIsodepTarget = (nfc_tech_isodep_target_t *) pUserData;
00603 
00604     if (ret == NFC_ERR_ABORTED) {
00605         // Just return
00606         return;
00607     }
00608 
00609     if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) {
00610         NFC_DBG("Deselect sent and re-polled: %u", ret);
00611         //We are now disconnected (deselected)
00612         //Reset status
00613         dep_init(pIsodepTarget);
00614         command_init(pIsodepTarget);
00615 
00616         transceiver_set_crc(pIsodepTarget->pTransceiver, true, true);
00617         pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING;
00618 
00619         //Call so that we can reinit higher layer
00620         dep_disconnected(pIsodepTarget, true); //This will call us again
00621         return;
00622     }
00623 
00624     //Prepare default empty reply
00625     transceiver_set_write(pTransceiver, NULL);
00626     transceiver_set_transceive_options(pTransceiver, false, true, false);
00627 
00628     if (ret == NFC_ERR_FIELD) {
00629         NFC_WARN("Lost initiator");
00630         dep_disconnected(pIsodepTarget, false);
00631         return;
00632     } else if (ret) {
00633         //We should ignore this error and wait for another frame
00634         NFC_WARN("Got invalid frame (error %d)", ret);
00635 
00636         nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget);
00637         return;
00638     }
00639 
00640     NFC_DBG("Reading data from initiator");
00641     ac_buffer_t *pDataInitiator = transceiver_get_read(pTransceiver); //In buffer
00642 
00643     NFC_DBG_BLOCK(ac_buffer_dump(pDataInitiator);)
00644 
00645     //Framing is handled by transceiver
00646     if ((ac_buffer_reader_readable(pDataInitiator) < 1)) {
00647         NFC_ERR("Empty initiator message");
00648 
00649         //Go back to receive mode
00650         nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget);
00651         return;
00652     }
00653 
00654     pIsodepTarget->commands.pReq = pDataInitiator;
00655 
00656     //Duplicate to peek on req
00657     ac_buffer_t dataInitiatorDup;
00658     ac_buffer_dup(&dataInitiatorDup, pDataInitiator);
00659     uint8_t req = ac_buffer_read_nu8(&dataInitiatorDup);
00660 
00661     switch (req) {
00662         case RATS:
00663             ret = command_ats_req(pIsodepTarget);
00664             break;
00665         default:
00666             ret = command_dep_req(pIsodepTarget);
00667             break;
00668     }
00669 
00670     if (ret) {
00671         NFC_ERR("Error %d", ret);
00672 
00673         //Go back to receive mode
00674         nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget);
00675         return;
00676     }
00677 
00678     NFC_DBG("Reply");
00679 
00680     //Reply
00681     command_reply(pIsodepTarget, true); //Make sure we send a WTX frame if we cannot respond straight away
00682 }
00683 
00684 
00685