/*
 * can_hal.hpp
 *
 *  Created on: 28 нояб. 2018 г.
  *      Author: alexrayne <alexraynepe196@gmail.com>
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   - Neither the name of ARM nor the names of its contributors may be used
     to endorse or promote products derived from this software without
     specific prior written permission.
   *
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. *
  ------------------------------------------------------------------------
     базовое АПИ CAN контролера. Умеет:
     - присоединяться на прослушивание адреса, принятые сообщения кидаются
       в пользовательский обработчик
         connect(address, ev_recv, ev_arg)
     - отправлять пакет по произвольному адресу
         writeData(address, data, size)
     - обрыв отправки сообщений на адрес
         writeAbort(address)
     - индикация состояния ошибки
         is_error()/errors()
     TODO:
     - не реализовано управление типом адреса
     - не реализовано прослушивание адресов по маске
 */

#ifndef HAL_CAN_HPP_
#define HAL_CAN_HPP_

#include "hal_device.h"


class CAN_Device
    //: public HAL_IO_Block_Device
{
public:
    typedef unsigned addr_t;

    // \arg address - received message adress
    // \arg data    - received message
    // \arg size    - recv message size, when <data>!= NULL
    // \param data=NULL - error received:
    //          \param size == 0 - device is close connection and down
    //          \param size != 0 - error code
    typedef void (*recv_handle)(void* self, addr_t address, const u8 *data, unsigned size);

    // allcate message buffers for receive on address
    //      received messages are passed to ev_recv !!!in IRQ
    virtual
    DevResult connect(addr_t address, recv_handle ev_recv, void* ev_self)
        {return  DEV_NOT_IMPLEMENTED;};

    enum {
        //этот флаг можно передать с адресом посылки во writeData, чтобы
        //  указать на то что абонент может отсутствовать, и его ошибки доставки
        //  следует игнорировать
          adrMAY_ABSENT = 0x10000000ul
        , adrMASK = 0xffffffful
    };

    // \arg data == NULL - abort all sending on specified adress
    // \return DEV_OK   - if sent message
    // \return DEV_BUSY - if sent message override previous send on <address>
    //          TODO: maybe should return fail, instead of overwrite previous message?
    virtual
    DevResult writeData(addr_t adress, const void *data, size_t size)
        {return  DEV_NOT_IMPLEMENTED;};

    //  abort all sends on <address>. and cleanup error counts.
    virtual
    DevResult writeAbort(addr_t address)
        {return  DEV_NOT_IMPLEMENTED;};
    //  abort all sends - terminate all transmitions. and cleanup error counts.
    virtual
    DevResult writeAbort(void)
        {return  DEV_NOT_IMPLEMENTED;};

    bool   is_error() const {return can_error_state != errOK;};
    unsigned errors() const {return can_error_state;};

    enum ErrorsID{ errCAN = 1, errOK = 0 };

protected:
    int can_error_state;
};



#endif /* HAL_CAN_HPP_ */
