//
//  bt_hci.h
//
//  Bluetooth Protocol Stack - HCI Transport Layer Interface
//  Copyright (C) 2013 Toyohiko Togashi tog001@nifty.com
//
//
//  This program is free software; you can redistribute it and/or modify it under the terms of the
//  GNU General Public License as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//  See the GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License along with this program.
//  If not, see <http://www.gnu.org/licenses/>
//
//
//  Reference:
//      Bluetooth SIG (www.bluetooth.com)
//          BLUETOOTH SPECIFICATION Version 4.0
//          [Vol 4] Host Controller Interface [Transport Layer]
//          Part B: USB Transport Layer
//
//  Update history
//  ---------- ----- -------------------------------------------
//  2013.01.21 v0.0  First cording
//  2013.04.21 v0.1  Commit
//
#ifndef BT_HCI_H_
#define BT_HCI_H_

//
//  Control block
//
struct bt_hciBufCB {
    char               *id;             // Table entry name
    volatile size_t     lenPos;         // Data length field position
    volatile size_t     lenSize;        // Data length field size
    unsigned char      *buf;            // User buffer memory
    volatile size_t     bufSize;        // Buffer area size
    volatile enum {
        BT_HCI_BUFFER_INIT = 0,         // No exists user buffer
        BT_HCI_BUFFER_EMPTY,            // No data, it can change buffer
        BT_HCI_BUFFER_BUSY,             // Now working, do not change buffer
        BT_HCI_BUFFER_VALID             // Ok data
    }                   status;         //
    unsigned char      *current;        // Read or write buffer point
    volatile size_t     dataLen;        // Valid data length
};
extern struct bt_hciBufCB bt_hciBufCB[4];

//
//  Internal API
//
extern void bt_setHciBuffer(struct bt_hciBufCB *cb, unsigned char *buf, size_t bufsize);
extern void bt_sendHciBuffer(struct bt_hciBufCB *cb);
extern int  bt_recieveHciBuffer(struct bt_hciBufCB *cb);
extern int  bt_getHciBuffer(struct bt_hciBufCB *cb, unsigned char *buf, size_t len);
extern int  bt_putHciBuffer(struct bt_hciBufCB *cb, unsigned char *buf, size_t len);

//
//  L2CAP side API
//
#define bt_setHCIcommandBuf(buf, bufsize)   bt_setHciBuffer(&bt_hciBufCB[0], buf, bufsize)
#define bt_isIdleHCIcommand()               (bt_hciBufCB[0].status == BT_HCI_BUFFER_EMPTY)
#define bt_sendHCIcommand()                 bt_sendHciBuffer(&bt_hciBufCB[0])

#define bt_setHCIeventBuf(buf, bufsize)     bt_setHciBuffer(&bt_hciBufCB[1], buf, bufsize)
#define bt_recieveHCIevent()                bt_recieveHciBuffer(&bt_hciBufCB[1])

#define bt_setACLoutBuf(buf, bufsize)       bt_setHciBuffer(&bt_hciBufCB[2], buf, bufsize)
#define bt_isIdleACLout()                   (bt_hciBufCB[2].status == BT_HCI_BUFFER_EMPTY)
#define bt_sendACLout()                     bt_sendHciBuffer(&bt_hciBufCB[2])

#define bt_setACLinBuf(buf, bufsize)        bt_setHciBuffer(&bt_hciBufCB[3], buf, bufsize)
#define bt_recieveACLin()                   bt_recieveHciBuffer(&bt_hciBufCB[3])

#define bt_isAliveHCI()                     (bt_hciBufCB[0].status != BT_HCI_BUFFER_INIT)

//
//  Physical device side API
//
#define bt_getHCIcommand(buf, len)          bt_getHciBuffer(&bt_hciBufCB[0], buf, len)
#define bt_putHCIevent(buf, len)            bt_putHciBuffer(&bt_hciBufCB[1], buf, len)
#define bt_getACLout(buf, len)              bt_getHciBuffer(&bt_hciBufCB[2], buf, len)
#define bt_putHCIin(buf, len)               bt_putHciBuffer(&bt_hciBufCB[3], buf, len)
#define bt_setDeadHCI()                     (bt_hciBufCB[0].status = BT_HCI_BUFFER_INIT, bt_hciBufCB[2].status = BT_HCI_BUFFER_INIT)
#define bt_setAliveHCI()                    (bt_hciBufCB[0].status = BT_HCI_BUFFER_EMPTY, bt_hciBufCB[2].status = BT_HCI_BUFFER_EMPTY)

#endif /* BT_HCI_H_ */
