mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Type 4 Target and dependencies implementation
							parent
							
								
									fdd8d0b9b6
								
							
						
					
					
						commit
						d4c29207cc
					
				| 
						 | 
				
			
			@ -29,6 +29,8 @@ namespace nfc {
 | 
			
		|||
     * @addtogroup nfc
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    class Type4RemoteInitiator;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * This base class represents an ISO7816-4 application.
 | 
			
		||||
| 
						 | 
				
			
			@ -85,27 +87,34 @@ namespace nfc {
 | 
			
		|||
        private:
 | 
			
		||||
            CAPDU _command;
 | 
			
		||||
            RAPDU _response;
 | 
			
		||||
            ISO7816App* _app;
 | 
			
		||||
            ISO7816App* _iso7816_app;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /** 
 | 
			
		||||
         * Construct ISO7816 app instance
 | 
			
		||||
         */ 
 | 
			
		||||
        ISO7816App();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        friend class Type4RemoteInitiator;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve the application's identifier (AID).
 | 
			
		||||
         * AIDs are composed of a RID (Registered Application Provider Identifier) that needs to be registered and a custom suffix.
 | 
			
		||||
         * 
 | 
			
		||||
         * @return a pointer to a const buffer containing the application's identifier (AID).
 | 
			
		||||
         */ 
 | 
			
		||||
        virtual const ac_buffer_t* get_aid() const;
 | 
			
		||||
        virtual const ac_buffer_t* get_aid() const = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Called when the application is selected and before any exchange is performed.
 | 
			
		||||
         */ 
 | 
			
		||||
        virtual void on_selected();
 | 
			
		||||
        virtual void on_selected() = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Called when the application is deselected (or link is lost).
 | 
			
		||||
         */ 
 | 
			
		||||
        virtual void on_deselected();
 | 
			
		||||
        virtual void on_deselected() = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Called when an exchange is performed.
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +122,9 @@ namespace nfc {
 | 
			
		|||
         * 
 | 
			
		||||
         * @param[in] exchange an instance of the Exchange class populated with the C-APDU which was received
 | 
			
		||||
         */ 
 | 
			
		||||
        virtual void on_exchange(Exchange* exchange);
 | 
			
		||||
        virtual void on_exchange(Exchange* exchange) = 0;
 | 
			
		||||
 | 
			
		||||
        nfc_tech_iso7816_app_t iso7816_app;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,6 +138,9 @@ namespace nfc {
 | 
			
		|||
        nfc_err_t cancel_discovery();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        friend class NFCRemoteEndpoint;
 | 
			
		||||
        friend class NFCRemoteInitiator;
 | 
			
		||||
        nfc_transceiver_t* transceiver() const;
 | 
			
		||||
        void polling_callback(nfc_err_t ret);
 | 
			
		||||
                
 | 
			
		||||
        // Callbacks from NFC stack
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,8 +36,10 @@ namespace nfc {
 | 
			
		|||
    public:
 | 
			
		||||
        /**
 | 
			
		||||
         * Construct a NFCNDEFCapable instance.
 | 
			
		||||
         * @param[in] buffer a bytes array used to store NDEF messages
 | 
			
		||||
         * @param[in] buffer_size the array size in bytes
 | 
			
		||||
         */ 
 | 
			
		||||
        NFCNDEFCapable();
 | 
			
		||||
        NFCNDEFCapable(uint8_t* buffer, size_t buffer_size);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check if this instance actually supports NDEF content.
 | 
			
		||||
| 
						 | 
				
			
			@ -88,8 +90,22 @@ namespace nfc {
 | 
			
		|||
         */ 
 | 
			
		||||
        void build_ndef_message(ac_buffer_builder_t& buffer_builder);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve underlying NDEF message instance
 | 
			
		||||
         * @return pointer to NDEF message instance
 | 
			
		||||
         */ 
 | 
			
		||||
        ndef_msg_t* ndef_message();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        // Callbacks from NDEF stack
 | 
			
		||||
        static nfc_err_t s_ndef_encode(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData);
 | 
			
		||||
        static nfc_err_t s_ndef_decode(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData);
 | 
			
		||||
        nfc_err_t ndef_encode(buffer_builder_t* pBufferBldr);
 | 
			
		||||
        nfc_err_t ndef_decode(buffer_t* pBuffer);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Delegate* _delegate;
 | 
			
		||||
        ndef_msg_t _ndef_message;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,8 @@ namespace nfc {
 | 
			
		|||
     * @addtogroup nfc
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    class NFCController;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * This is the base class for all remote endpoints (initiators and targets)
 | 
			
		||||
| 
						 | 
				
			
			@ -35,28 +37,65 @@ namespace nfc {
 | 
			
		|||
     */ 
 | 
			
		||||
    class NFCRemoteEndpoint {
 | 
			
		||||
    public:
 | 
			
		||||
        NFCRemoteEndpoint();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The NFCRemoteEndpoint base delegate.
 | 
			
		||||
         */
 | 
			
		||||
        struct Delegate {
 | 
			
		||||
            /**
 | 
			
		||||
             * This method is called when the endpoint is connected
 | 
			
		||||
             */
 | 
			
		||||
            virtual void on_connected() {};           
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * This method is called when the endpoint is lost (air interface link disconnnected)
 | 
			
		||||
             */
 | 
			
		||||
            virtual void on_lost() {};           
 | 
			
		||||
            virtual void on_disconnected() {};           
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check if the endpoint is lost.
 | 
			
		||||
         * @return whether the endpoint is lost
 | 
			
		||||
         * Connect the remote endpoint
 | 
			
		||||
         * 
 | 
			
		||||
         * @return NFC_OK or an error code
 | 
			
		||||
         */
 | 
			
		||||
        virtual nfc_err_t connect() = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Disconnect the remote endpoint
 | 
			
		||||
         * 
 | 
			
		||||
         * @return NFC_OK or an error code
 | 
			
		||||
         */
 | 
			
		||||
        virtual nfc_err_t disconnect() = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check if the endpoint is connected.
 | 
			
		||||
         * @return whether the endpoint is connected
 | 
			
		||||
         */ 
 | 
			
		||||
        bool is_lost() const;
 | 
			
		||||
        virtual bool is_connected() const = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check if the endpoint is disconnected/lost.
 | 
			
		||||
         * @return whether the endpoint has been disconnected
 | 
			
		||||
         */ 
 | 
			
		||||
        virtual bool is_disconnected() const = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Get the list of RF protocols supported and activated over the air interface.
 | 
			
		||||
         * @return a bitmask of activated protocols
 | 
			
		||||
         */ 
 | 
			
		||||
        nfc_rf_protocols_bitmask_t rf_protocols() const;
 | 
			
		||||
        virtual nfc_rf_protocols_bitmask_t rf_protocols() = 0;
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        /**
 | 
			
		||||
         * Mark endpoint as connected
 | 
			
		||||
         */ 
 | 
			
		||||
        void connected();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Mark endpoint as disconnected
 | 
			
		||||
         */
 | 
			
		||||
        void disconnected();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,8 @@ namespace nfc {
 | 
			
		|||
     * @addtogroup nfc
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    class NFCController;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * This class represents a remote NFC initiator (the local controller being in target mode).
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +42,7 @@ namespace nfc {
 | 
			
		|||
    public:
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a NFCRemoteInitiator.
 | 
			
		||||
         * 
 | 
			
		||||
         */ 
 | 
			
		||||
        NFCRemoteInitiator();
 | 
			
		||||
        virtual ~NFCRemoteInitiator();
 | 
			
		||||
| 
						 | 
				
			
			@ -48,15 +51,7 @@ namespace nfc {
 | 
			
		|||
         * The NFCRemoteInitiator delegate. Users of the NFCRemoteInitiator class need to implement this delegate's methods to receive events.
 | 
			
		||||
         */
 | 
			
		||||
        struct Delegate : NFCEndpoint::Delegate, NFCNDEFCapable::Delegate {
 | 
			
		||||
            /**
 | 
			
		||||
             * The controller was selected by the initiator.
 | 
			
		||||
             */ 
 | 
			
		||||
            virtual void on_selected() {}
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * The controller was deselected by the initiator.
 | 
			
		||||
             */ 
 | 
			
		||||
            virtual void on_deselected() {}
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /** 
 | 
			
		||||
| 
						 | 
				
			
			@ -64,28 +59,31 @@ namespace nfc {
 | 
			
		|||
         * 
 | 
			
		||||
         * @oaram[in] delegate the delegate instance to use
 | 
			
		||||
         */ 
 | 
			
		||||
        void set_delegate(Delegate* delegate);
 | 
			
		||||
        void set_remote_initiator_delegate(Delegate* delegate);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve the NFC tag type exposed by the controller to communicate with the initiator.
 | 
			
		||||
         * 
 | 
			
		||||
         * @return the relevant NFC tag type
 | 
			
		||||
         */ 
 | 
			
		||||
        nfc_tag_type_t nfc_tag_type() const;
 | 
			
		||||
        virtual nfc_tag_type_t nfc_tag_type() const = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve whether ISO7816 applications are supported by the underlying technology.
 | 
			
		||||
         * 
 | 
			
		||||
         * @return whether ISO7816 applications are supported
 | 
			
		||||
         */ 
 | 
			
		||||
        bool is_iso7816_supported() const;
 | 
			
		||||
        virtual bool is_iso7816_supported() const = 0;
 | 
			
		||||
 | 
			
		||||
        /** 
 | 
			
		||||
         * Register an ISO7816 application to be used by the initiator.
 | 
			
		||||
         * 
 | 
			
		||||
         * @param[in] application a pointer to an ISO7816App instance
 | 
			
		||||
         */
 | 
			
		||||
        void add_iso7816_application(ISO7816App* application);
 | 
			
		||||
        virtual void add_iso7816_application(ISO7816App* application) = 0;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        Delegate* _delegate;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,18 +37,39 @@ namespace nfc {
 | 
			
		|||
    /**
 | 
			
		||||
     * This class is an implementation of the Type 4 tag application.
 | 
			
		||||
     */
 | 
			
		||||
    class Type4RemoteInitiator : public NFCRemoteInitiator, public ISO7816App, public NFCNDEFCapable {
 | 
			
		||||
    class Type4RemoteInitiator : public NFCRemoteInitiator, public NFCNDEFCapable {
 | 
			
		||||
    private:
 | 
			
		||||
        Type4RemoteInitiator(nfc_transceiver_t* transceiver);
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a Type4RemoteInitiator.
 | 
			
		||||
         * 
 | 
			
		||||
         * @param[in] controller pointer to the NFCController instance that created this object
 | 
			
		||||
         */ 
 | 
			
		||||
        Type4RemoteInitiator(NFCController* controller);
 | 
			
		||||
 | 
			
		||||
        // NFCRemoteEndpoint implementation
 | 
			
		||||
        virtual nfc_err_t connect();
 | 
			
		||||
        virtual nfc_err_t disconnect();
 | 
			
		||||
        virtual bool is_connected();
 | 
			
		||||
        virtual bool is_disconnected();
 | 
			
		||||
        virtual nfc_rf_protocols_bitmask_t rf_protocols();
 | 
			
		||||
 | 
			
		||||
        // NFCRemoteInitiator implementation
 | 
			
		||||
        virtual nfc_tag_type_t nfc_tag_type() const;
 | 
			
		||||
        virtual bool is_iso7816_supported() const;
 | 
			
		||||
        virtual void add_iso7816_application(ISO7816App* application);
 | 
			
		||||
 | 
			
		||||
        // NFCNDEFCapable implementation 
 | 
			
		||||
        virtual bool is_ndef_supported() const;
 | 
			
		||||
 | 
			
		||||
        // ISO7816App implementation
 | 
			
		||||
        virtual const ac_buffer_t* get_aid() const;
 | 
			
		||||
        virtual void on_selected();
 | 
			
		||||
        virtual void on_deselected();
 | 
			
		||||
        virtual void on_exchange(Exchange* exchange);
 | 
			
		||||
        // Callbacks from NFC stack
 | 
			
		||||
        void disconnected_callback(bool deselected);
 | 
			
		||||
        static void s_disconnected_callback(nfc_tech_iso7816_t* pIso7816, bool deselected, void* pUserData);
 | 
			
		||||
 | 
			
		||||
        NFCController* _controller;
 | 
			
		||||
        bool _is_connected;
 | 
			
		||||
        bool _is_disconnected;
 | 
			
		||||
        nfc_tech_iso7816_t _iso7816;
 | 
			
		||||
        nfc_tech_type4_target_t _type4;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,6 +109,11 @@ nfc_err_t NFCController::cancel_discovery()
 | 
			
		|||
    transceiver_abort(_transceiver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_transceiver_t* NFCController::transceiver() const
 | 
			
		||||
{
 | 
			
		||||
    return _transceiver;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NFCController::polling_callback(nfc_err_t ret)
 | 
			
		||||
{
 | 
			
		||||
    // Polling has completed
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,12 +20,14 @@
 | 
			
		|||
#include "acore/buffer_reader.h"
 | 
			
		||||
#include "acore/buffer_builder.h"
 | 
			
		||||
 | 
			
		||||
#include "ndef/ndef.h"
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
using namespace mbed::nfc;
 | 
			
		||||
 | 
			
		||||
NFCNDEFCapable::NFCNDEFCapable() : _delegate(NULL)
 | 
			
		||||
NFCNDEFCapable::NFCNDEFCapable(uint8_t* buffer, size_t buffer_size) : _delegate(NULL)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    ndef_msg_init(&_ndef_message, s_encode_callback, s_decode_callback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NFCNDEFCapable::set_ndef_delegate(NFCNDEFCapable::Delegate* delegate)
 | 
			
		||||
| 
						 | 
				
			
			@ -49,3 +51,23 @@ void NFCNDEFCapable::build_ndef_message(ac_buffer_builder_t& buffer_builder)
 | 
			
		|||
        ac_buffer_builder_write_n_skip(&buffer_builder, count);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t NFCNDEFCapable::s_ndef_encode(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData) {
 | 
			
		||||
    NFCNDEFCapable* self = (NFCNDEFCapable*)pUserData;
 | 
			
		||||
    self->ndef_encode(pBufferBldr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t NFCNDEFCapable::s_ndef_decode(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData) {
 | 
			
		||||
    NFCNDEFCapable* self = (NFCNDEFCapable*)pUserData;
 | 
			
		||||
    self->ndef_decode(pBuffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t NFCNDEFCapable::ndef_encode(buffer_builder_t* pBufferBldr) {
 | 
			
		||||
    build_ndef_message(buffer_builder);
 | 
			
		||||
    return NFC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t NFCNDEFCapable::ndef_decode(buffer_t* pBuffer) {
 | 
			
		||||
    parse_ndef_message(pBuffer);
 | 
			
		||||
    return NFC_OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "NFCRemoteEndpoint.h"
 | 
			
		||||
 | 
			
		||||
#include "acore/buffer.h"
 | 
			
		||||
#include "acore/buffer_reader.h"
 | 
			
		||||
#include "acore/buffer_builder.h"
 | 
			
		||||
 | 
			
		||||
#include "stack/transceiver/transceiver.h"
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
using namespace mbed::nfc;
 | 
			
		||||
 | 
			
		||||
NFCRemoteEndpoint::NFCRemoteEndpoint(NFCController* controller) : _controller(controller), _is_lost(false) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool NFCRemoteEndpoint::is_lost() const {
 | 
			
		||||
    return _is_lost;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols() {
 | 
			
		||||
    nfc_rf_protocols_bitmask_t rf_protocols = {0};
 | 
			
		||||
    nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
 | 
			
		||||
    if(!transceiver_is_initiator_mode(_transceiver))
 | 
			
		||||
    {
 | 
			
		||||
        // Note: We only support ISO-DEP for now
 | 
			
		||||
        rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return rf_protocols;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NFCRemoteEndpoint::set_lost() {
 | 
			
		||||
    _is_lost = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NFCController* NFCRemoteEndpoint::nfc_controller() const {
 | 
			
		||||
    return _controller;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "NFCRemoteInitiator.h"
 | 
			
		||||
 | 
			
		||||
#include "acore/buffer.h"
 | 
			
		||||
#include "acore/buffer_reader.h"
 | 
			
		||||
#include "acore/buffer_builder.h"
 | 
			
		||||
 | 
			
		||||
#include "stack/transceiver/transceiver.h"
 | 
			
		||||
#include "stack/tech/iso7816/iso7816.h"
 | 
			
		||||
#include "stack/tech/iso7816/iso7816_app.h"
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
using namespace mbed::nfc;
 | 
			
		||||
 | 
			
		||||
NFCRemoteInitiator::NFCRemoteInitiator(NFCController* controller) : NFCRemoteEndpoint(controller) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NFCRemoteInitiator::~NFCRemoteInitiator() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void NFCRemoteInitiator::set_remote_initiator_delegate(Delegate* delegate)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_tag_type_t NFCRemoteInitiator::nfc_tag_type() const
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool NFCRemoteInitiator::is_iso7816_supported() const
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NFCRemoteInitiator::add_iso7816_application(ISO7816App* application)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "Type4RemoteInitiator.h"
 | 
			
		||||
 | 
			
		||||
#include "acore/buffer.h"
 | 
			
		||||
#include "acore/buffer_reader.h"
 | 
			
		||||
#include "acore/buffer_builder.h"
 | 
			
		||||
 | 
			
		||||
#include "stack/transceiver/transceiver.h"
 | 
			
		||||
#include "stack/tech/iso7816/iso7816.h"
 | 
			
		||||
#include "stack/tech/iso7816/iso7816_app.h"
 | 
			
		||||
#include "stack/tech/type4/type4_target.h"
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
using namespace mbed::nfc;
 | 
			
		||||
 | 
			
		||||
Type4RemoteInitiator::Type4RemoteInitiator(NFCController* controller) : 
 | 
			
		||||
    _controller(controller), _is_connected(false) , _is_disconnected(false), _apps(NULL) {
 | 
			
		||||
    // Init ISO7816
 | 
			
		||||
    nfc_tech_iso7816_init(&_iso7816, _controller->transceiver(), &Type4RemoteInitiator::s_disconnected_callback, this);
 | 
			
		||||
    
 | 
			
		||||
    // Init Type 4 app
 | 
			
		||||
    nfc_tech_type4_target_init(&_type4, &_iso7816, ndef_message());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t Type4RemoteInitiator::connect() {
 | 
			
		||||
    if(_is_connected) {
 | 
			
		||||
        return NFC_BUSY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(_is_disconnected) {
 | 
			
		||||
        return NFC_ERR_DISCONNECTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Connect ISO7816 stack
 | 
			
		||||
    nfc_tech_iso7816_connect(&_iso7816);
 | 
			
		||||
 | 
			
		||||
    // Call callback as it's a synchronous API
 | 
			
		||||
    connected();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t Type4RemoteInitiator::disconnect() {
 | 
			
		||||
    if(!_is_connected) {
 | 
			
		||||
        return NFC_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(_is_disconnected) {
 | 
			
		||||
        return NFC_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Disconnect ISO7816 stack
 | 
			
		||||
    nfc_tech_iso7816_disconnect(&_iso7816);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Type4RemoteInitiator::is_connected() const {
 | 
			
		||||
    return _is_connected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Type4RemoteInitiator::is_disconnected() const {
 | 
			
		||||
    return _is_disconnected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols() {
 | 
			
		||||
    nfc_rf_protocols_bitmask_t rf_protocols = {0};
 | 
			
		||||
    nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
 | 
			
		||||
    if(!transceiver_is_initiator_mode(_transceiver))
 | 
			
		||||
    {
 | 
			
		||||
        // We only support ISO-DEP
 | 
			
		||||
        rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return rf_protocols;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
virtual nfc_tag_type_t Type4RemoteInitiator::nfc_tag_type() const {
 | 
			
		||||
    nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
 | 
			
		||||
    if(active_tech.nfc_iso_dep_a) {
 | 
			
		||||
        return nfc_tag_type_4a;
 | 
			
		||||
    }
 | 
			
		||||
    else { // if(active_tech.nfc_iso_dep_b)
 | 
			
		||||
        return nfc_tag_type_4b;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
virtual bool Type4RemoteInitiator::is_iso7816_supported() const {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
virtual void Type4RemoteInitiator::add_iso7816_application(ISO7816App* application) {
 | 
			
		||||
    nfc_tech_iso7816_add_app(&_iso7816, application->_iso7816_app);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
virtual bool Type4RemoteInitiator::is_ndef_supported() const {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
 * not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * \file ndef.c
 | 
			
		||||
 * \copyright Copyright (c) ARM Ltd 2013
 | 
			
		||||
 * \author Donatien Garnier
 | 
			
		||||
 * \details NDEF tag abstraction
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "inc/nfc.h"
 | 
			
		||||
#include "ndef.h"
 | 
			
		||||
 | 
			
		||||
/** \addtogroup NDEF
 | 
			
		||||
 *  @{
 | 
			
		||||
 *  \name Generic NDEF Tag
 | 
			
		||||
 *  @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** Initialize NDEF tag abstraction
 | 
			
		||||
 * \param pNdefTag pointer to ndef_tag_t structure to initialize
 | 
			
		||||
 * \param encode function that will be called to generate the NDEF message before sending it to the other party
 | 
			
		||||
 * \param decode function that will be called to parse the NDEF message after receiving it from the other party
 | 
			
		||||
 * \param buffer underlying buffer to use (it should be big enough so that any NDEF message you might need could be stored inside)
 | 
			
		||||
 * \param buffer_size size of the underlying buffer
 | 
			
		||||
 * \param pImpl pointer to actual implementation
 | 
			
		||||
 */
 | 
			
		||||
void ndef_msg_init( ndef_msg_t* pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t* data, size_t size, void* pUserData )
 | 
			
		||||
{
 | 
			
		||||
  pNdef->encode = encode;
 | 
			
		||||
  pNdef->decode = decode;
 | 
			
		||||
  buffer_builder_init(&pNdef->bufferBldr, data, size);
 | 
			
		||||
  pNdef->pUserData = pUserData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get NDEF tag implementation
 | 
			
		||||
 * \param pNdefTag pointer to ndef_tag_t structure
 | 
			
		||||
 * \return implementation
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
void* ndef_tag_impl(ndef_tag_t* pNdefTag)
 | 
			
		||||
{
 | 
			
		||||
  return pNdefTag->pImpl;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @}
 | 
			
		||||
 * @}
 | 
			
		||||
 * */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,99 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
 * not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * \file ndef.h
 | 
			
		||||
 * \copyright Copyright (c) ARM Ltd 2013
 | 
			
		||||
 * \author Donatien Garnier
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \addtogroup NDEF
 | 
			
		||||
 *  @{
 | 
			
		||||
 *  \name Generic NDEF Tag
 | 
			
		||||
 *  @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef NDEF_H_
 | 
			
		||||
#define NDEF_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "inc/nfc.h"
 | 
			
		||||
 | 
			
		||||
//Generic interface for NDEF messages
 | 
			
		||||
 | 
			
		||||
typedef struct __ndef_msg ndef_msg_t;
 | 
			
		||||
 | 
			
		||||
/** Function called to generate the tag's content on read (target mode)
 | 
			
		||||
 * \param pTag pointer to ndef_tag_t instance
 | 
			
		||||
 * \param type pMem buffer in which to store the generated content
 | 
			
		||||
 */
 | 
			
		||||
typedef nfc_err_t (*ndef_encode_fn_t)(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData);
 | 
			
		||||
 | 
			
		||||
/** Function called to decode the tag's content on write (target mode) or read (reader mode)
 | 
			
		||||
 * \param pTag pointer to ndef_tag_t instance
 | 
			
		||||
 * \param type pMem buffer containing the tag's content
 | 
			
		||||
 */
 | 
			
		||||
typedef nfc_err_t (*ndef_decode_fn_t)(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData);
 | 
			
		||||
 | 
			
		||||
typedef struct __ndef_msg
 | 
			
		||||
{
 | 
			
		||||
  ndef_encode_fn_t encode;
 | 
			
		||||
  ndef_decode_fn_t decode;
 | 
			
		||||
  buffer_builder_t bufferBldr;
 | 
			
		||||
  void* pUserData;
 | 
			
		||||
} ndef_msg_t;
 | 
			
		||||
 | 
			
		||||
void ndef_msg_init( ndef_msg_t* pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t* data, size_t size, void* pUserData );
 | 
			
		||||
 | 
			
		||||
static inline nfc_err_t ndef_msg_encode(ndef_msg_t* pNdef)
 | 
			
		||||
{
 | 
			
		||||
  if(pNdef->encode == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    return NFC_OK;
 | 
			
		||||
  }
 | 
			
		||||
  return pNdef->encode(pNdef, &pNdef->bufferBldr, pNdef->pUserData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline nfc_err_t ndef_msg_decode(ndef_msg_t* pNdef)
 | 
			
		||||
{
 | 
			
		||||
  if(pNdef->decode == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    return NFC_OK;
 | 
			
		||||
  }
 | 
			
		||||
  return pNdef->decode(pNdef, buffer_builder_buffer(&pNdef->bufferBldr), pNdef->pUserData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline buffer_builder_t* ndef_msg_buffer_builder(ndef_msg_t* pNdef)
 | 
			
		||||
{
 | 
			
		||||
  return &pNdef->bufferBldr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//void* ndef_tag_impl(ndef_tag_t* pNdefTag);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* NDEF_H_ */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @}
 | 
			
		||||
 * @}
 | 
			
		||||
 * */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,312 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
 * not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * \file type4_target.c
 | 
			
		||||
 * \copyright Copyright (c) ARM Ltd 2015
 | 
			
		||||
 * \author Donatien Garnier
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define __DEBUG__ 0
 | 
			
		||||
#ifndef __MODULE__
 | 
			
		||||
#define __MODULE__ "type4_target.c"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "inc/nfc.h"
 | 
			
		||||
 | 
			
		||||
#include "type4_target.h"
 | 
			
		||||
#include "tech/iso7816/iso7816_defs.h"
 | 
			
		||||
 | 
			
		||||
#define TYPE4_NDEF_VERSION 2
 | 
			
		||||
 | 
			
		||||
#if TYPE4_NDEF_VERSION == 2
 | 
			
		||||
static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
 | 
			
		||||
#else
 | 
			
		||||
static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
 | 
			
		||||
#endif
 | 
			
		||||
#define CC_FILE 0xE103 //Must not be changed
 | 
			
		||||
#define NDEF_FILE 0xA443
 | 
			
		||||
#define DEFAULT_FILE 0x0000
 | 
			
		||||
 | 
			
		||||
static void app_selected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData );
 | 
			
		||||
static void app_deselected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData );
 | 
			
		||||
static void app_apdu( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData );
 | 
			
		||||
 | 
			
		||||
static nfc_err_t data_read(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off, size_t len);
 | 
			
		||||
static nfc_err_t data_write(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off);
 | 
			
		||||
 | 
			
		||||
void nfc_tech_type4_target_init(nfc_tech_type4_target_t* pType4Target, nfc_tech_iso7816_t* pIso7816, ndef_msg_t* pNdef)
 | 
			
		||||
{
 | 
			
		||||
  buffer_builder_init(&pType4Target->ccFileBldr, pType4Target->ccFileBuf, /*sizeof(pType4Target->ccFileBuf)*/15);
 | 
			
		||||
 | 
			
		||||
  buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2);
 | 
			
		||||
 | 
			
		||||
  pType4Target->selFile = DEFAULT_FILE;
 | 
			
		||||
  pType4Target->pNdef = pNdef;
 | 
			
		||||
  pType4Target->written = false;
 | 
			
		||||
 | 
			
		||||
  nfc_tech_iso7816_app_init(&pType4Target->app, pIso7816, aid, sizeof(aid), app_selected, app_deselected, app_apdu, pType4Target);
 | 
			
		||||
 | 
			
		||||
  nfc_tech_iso7816_add_app(pIso7816, &pType4Target->app);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void app_selected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData )
 | 
			
		||||
{
 | 
			
		||||
  nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData;
 | 
			
		||||
  DBG("Selected");
 | 
			
		||||
 | 
			
		||||
  (void) pIso7816App;
 | 
			
		||||
 | 
			
		||||
  buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef));
 | 
			
		||||
 | 
			
		||||
  //Populate CC file
 | 
			
		||||
  buffer_builder_reset(&pType4Target->ccFileBldr);
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ccFileBldr, 15 ); //CC file is 15 bytes long
 | 
			
		||||
#if TYPE4_NDEF_VERSION == 2
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x20 ); //NFC Forum Tag Type 4 V2.0 compliant
 | 
			
		||||
#else
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x10 ); //NFC Forum Tag Type 4 V1.0 compliant
 | 
			
		||||
#endif
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ccFileBldr, 256 /* Max frame size */ - 2 /* SW */ - 3 /* ISO-DEP PFB + DID + NAD */ ); //Max data size that can be read from the tag
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ccFileBldr, 256 /* Max frame size */ - 6 /* CLA INS P1 P2 LC LE */ - 3 /* ISO-DEP PFB + DID + NAD */ ); //Max data size that can be written to the tag
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x04 ); //NDEF File Control TLV - Type
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 6 ); //NDEF File Control TLV - Length
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ccFileBldr, NDEF_FILE ); //NDEF file id
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ccFileBldr, 2 /* length header */ + buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) ) ); //Max size of NDEF data
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x00 ); //Open read access
 | 
			
		||||
  buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x00 ); //Open write access
 | 
			
		||||
 | 
			
		||||
  //Encode NDEF file
 | 
			
		||||
  ndef_msg_encode(pType4Target->pNdef);
 | 
			
		||||
 | 
			
		||||
  //Populate NDEF file
 | 
			
		||||
  buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2);
 | 
			
		||||
 | 
			
		||||
  buffer_builder_write_nu16( &pType4Target->ndefFileBldr, buffer_reader_readable( buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)) ) );
 | 
			
		||||
 | 
			
		||||
  //Pad NDEF file with 0s
 | 
			
		||||
  while( buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) ) > 0 )
 | 
			
		||||
  {
 | 
			
		||||
    buffer_builder_write_nu8(ndef_msg_buffer_builder(pType4Target->pNdef), 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //No file selected
 | 
			
		||||
  pType4Target->selFile = DEFAULT_FILE;
 | 
			
		||||
 | 
			
		||||
  pType4Target->written = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void app_deselected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData )
 | 
			
		||||
{
 | 
			
		||||
  nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData;
 | 
			
		||||
 | 
			
		||||
  (void) pIso7816App;
 | 
			
		||||
 | 
			
		||||
  //Reset buffers
 | 
			
		||||
  buffer_builder_reset(&pType4Target->ccFileBldr);
 | 
			
		||||
  buffer_builder_set_full(&pType4Target->ndefFileBldr); //To read length
 | 
			
		||||
  buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef));
 | 
			
		||||
 | 
			
		||||
  DBG("Deselected");
 | 
			
		||||
 | 
			
		||||
  if(pType4Target->written)
 | 
			
		||||
  {
 | 
			
		||||
    DBG("New content has been written");
 | 
			
		||||
    //Try to parse NDEF
 | 
			
		||||
    //Set buffer length based on file header
 | 
			
		||||
    size_t length = buffer_read_nu16(buffer_builder_buffer(&pType4Target->ndefFileBldr));
 | 
			
		||||
    DBG("Length is %lu", length);
 | 
			
		||||
    if( length < buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) ))
 | 
			
		||||
    {
 | 
			
		||||
      buffer_builder_set_write_offset( ndef_msg_buffer_builder(pType4Target->pNdef), length );
 | 
			
		||||
      ndef_msg_decode(pType4Target->pNdef);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      ERR("Invalid length");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void app_apdu( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData )
 | 
			
		||||
{
 | 
			
		||||
  nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData;
 | 
			
		||||
 | 
			
		||||
  //Reset buffers
 | 
			
		||||
  buffer_builder_set_full(&pType4Target->ccFileBldr);
 | 
			
		||||
  buffer_builder_set_full(&pType4Target->ndefFileBldr);
 | 
			
		||||
  buffer_builder_set_full( ndef_msg_buffer_builder(pType4Target->pNdef) ); //Set offset to 0, size to max
 | 
			
		||||
 | 
			
		||||
  buffer_set_next(buffer_builder_buffer(&pType4Target->ndefFileBldr), buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)));
 | 
			
		||||
 | 
			
		||||
  //Recover PDU
 | 
			
		||||
  nfc_tech_iso7816_c_apdu_t* pCApdu = nfc_tech_iso7816_app_c_apdu(pIso7816App);
 | 
			
		||||
  nfc_tech_iso7816_r_apdu_t* pRApdu = nfc_tech_iso7816_app_r_apdu(pIso7816App);
 | 
			
		||||
 | 
			
		||||
  nfc_err_t ret;
 | 
			
		||||
  switch(pCApdu->ins)
 | 
			
		||||
  {
 | 
			
		||||
  case ISO7816_INS_SELECT:
 | 
			
		||||
    switch (pCApdu->p1)
 | 
			
		||||
    {
 | 
			
		||||
    case 0x00: //Selection by ID
 | 
			
		||||
    case 0x02: //Selection by child ID
 | 
			
		||||
      if ( buffer_reader_readable(&pCApdu->dataIn) != 2)
 | 
			
		||||
      {
 | 
			
		||||
        pRApdu->sw = ISO7816_SW_NOT_FOUND;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      uint16_t file = buffer_read_nu16(&pCApdu->dataIn);
 | 
			
		||||
      if ( file == NDEF_FILE )
 | 
			
		||||
      {
 | 
			
		||||
        pType4Target->selFile = NDEF_FILE;
 | 
			
		||||
        DBG("NDEF File selected");
 | 
			
		||||
        pRApdu->sw = ISO7816_SW_OK;
 | 
			
		||||
      }
 | 
			
		||||
      else if ( file == CC_FILE )
 | 
			
		||||
      {
 | 
			
		||||
        pType4Target->selFile = CC_FILE;
 | 
			
		||||
        DBG("CC File selected");
 | 
			
		||||
        pRApdu->sw = ISO7816_SW_OK;
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        //file = DEFAULT_FILE;
 | 
			
		||||
        DBG("Could not select file %04X", file);
 | 
			
		||||
        pRApdu->sw = ISO7816_SW_NOT_FOUND;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      pRApdu->sw = ISO7816_SW_NOT_FOUND;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  case 0xB0: //Read binary
 | 
			
		||||
    DBG("Trying to read %d bytes at offset %d from file %04x", pCApdu->maxRespLength, (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
 | 
			
		||||
    ret = data_read(pType4Target, &pRApdu->dataOut, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2, pCApdu->maxRespLength);
 | 
			
		||||
    if (ret == NFC_OK)
 | 
			
		||||
    {
 | 
			
		||||
      DBG("Read %d bytes", buffer_reader_readable(&pRApdu->dataOut));
 | 
			
		||||
      DBG_BLOCK( buffer_dump(&pRApdu->dataOut); )
 | 
			
		||||
      pRApdu->sw = ISO7816_SW_OK;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      DBG("Failed with ret code %d", ret);
 | 
			
		||||
      pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  case 0xD6: //Update binary
 | 
			
		||||
    DBG("Trying to write %d bytes at offset %d to file %04x", buffer_reader_readable(&pCApdu->dataIn), (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
 | 
			
		||||
    ret = data_write(pType4Target, &pCApdu->dataIn, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2);
 | 
			
		||||
    if (ret == NFC_OK)
 | 
			
		||||
    {
 | 
			
		||||
      DBG("OK");
 | 
			
		||||
      pRApdu->sw = ISO7816_SW_OK;
 | 
			
		||||
      pType4Target->written = true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      DBG("Failed with ret code %d", ret);
 | 
			
		||||
      pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    pRApdu->sw = ISO7816_SW_INVALID_INS;
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Send reply
 | 
			
		||||
  nfc_tech_iso7816_app_reply(pIso7816App);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t data_read(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off, size_t len)
 | 
			
		||||
{
 | 
			
		||||
  buffer_t* pFile;
 | 
			
		||||
  switch(file)
 | 
			
		||||
  {
 | 
			
		||||
  case CC_FILE:
 | 
			
		||||
    pFile = buffer_builder_buffer(&pType4Target->ccFileBldr);
 | 
			
		||||
    break;
 | 
			
		||||
  case NDEF_FILE:
 | 
			
		||||
    pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr);
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    return NFC_ERR_NOT_FOUND;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if( off > buffer_reader_readable(pFile) )
 | 
			
		||||
  {
 | 
			
		||||
    return NFC_ERR_LENGTH;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  buffer_read_n_skip(pFile, off);
 | 
			
		||||
 | 
			
		||||
  if( len > buffer_reader_readable(pFile))
 | 
			
		||||
  {
 | 
			
		||||
    len = buffer_reader_readable(pFile);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  buffer_split(pBuf, pFile, pFile, len);
 | 
			
		||||
 | 
			
		||||
  return NFC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nfc_err_t data_write(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off)
 | 
			
		||||
{
 | 
			
		||||
  buffer_t* pFile;
 | 
			
		||||
  switch(file)
 | 
			
		||||
  {
 | 
			
		||||
  case NDEF_FILE:
 | 
			
		||||
    pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr);
 | 
			
		||||
    break;
 | 
			
		||||
  case CC_FILE: //Cannot write to CC file!
 | 
			
		||||
  default:
 | 
			
		||||
    return NFC_ERR_NOT_FOUND;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  size_t len = buffer_reader_readable(pBuf);
 | 
			
		||||
 | 
			
		||||
  if( off > buffer_reader_readable(pFile) )
 | 
			
		||||
  {
 | 
			
		||||
    return NFC_ERR_LENGTH;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  buffer_read_n_skip(pFile, off);
 | 
			
		||||
 | 
			
		||||
  if( len > buffer_reader_readable(pFile) )
 | 
			
		||||
  {
 | 
			
		||||
    len = buffer_reader_readable(pFile);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  while( len > 0 )
 | 
			
		||||
  {
 | 
			
		||||
    size_t cpy;
 | 
			
		||||
    buffer_builder_t builder;
 | 
			
		||||
    buffer_dup(buffer_builder_buffer(&builder), pFile);
 | 
			
		||||
    buffer_builder_from_buffer(&builder);
 | 
			
		||||
    cpy = buffer_builder_writeable(&builder);
 | 
			
		||||
    cpy = MIN(cpy, len);
 | 
			
		||||
    buffer_builder_copy_n_bytes(&builder, pBuf, cpy);
 | 
			
		||||
    pFile = buffer_next(pFile);
 | 
			
		||||
    len -= cpy;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return NFC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
 * not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * \file type4_target.h
 | 
			
		||||
 * \copyright Copyright (c) ARM Ltd 2015
 | 
			
		||||
 * \author Donatien Garnier
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TECH_TYPE4_TYPE4_TARGET_H_
 | 
			
		||||
#define TECH_TYPE4_TYPE4_TARGET_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "inc/nfc.h"
 | 
			
		||||
 | 
			
		||||
#include "tech/iso7816/iso7816.h"
 | 
			
		||||
#include "tech/iso7816/iso7816_app.h"
 | 
			
		||||
#include "ndef/ndef.h"
 | 
			
		||||
 | 
			
		||||
typedef struct nfc_tech_type4_target nfc_tech_type4_target_t;
 | 
			
		||||
 | 
			
		||||
typedef void (*nfc_tech_type4_cb)(nfc_tech_type4_target_t* pType4Target, nfc_err_t ret, void* pUserData);
 | 
			
		||||
 | 
			
		||||
struct nfc_tech_type4_target
 | 
			
		||||
{
 | 
			
		||||
  nfc_tech_iso7816_app_t app;
 | 
			
		||||
 | 
			
		||||
  ndef_msg_t* pNdef;
 | 
			
		||||
 | 
			
		||||
  uint8_t ccFileBuf[15];
 | 
			
		||||
  buffer_builder_t ccFileBldr;
 | 
			
		||||
 | 
			
		||||
  uint8_t ndefFileBuf[2];
 | 
			
		||||
  buffer_builder_t ndefFileBldr;
 | 
			
		||||
 | 
			
		||||
  uint16_t selFile;
 | 
			
		||||
 | 
			
		||||
  bool written;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void nfc_tech_type4_target_init(nfc_tech_type4_target_t* pType4Target, nfc_tech_iso7816_t* pIso7816, ndef_msg_t* pNdef);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* TECH_TYPE4_TYPE4_TARGET_H_ */
 | 
			
		||||
		Loading…
	
		Reference in New Issue