Pulse Oximeter (NONIN) communicates with mbed via Bluetooth dongle and sends Heart Rate and Oxygen Saturation via GPRS module

Dependencies:   C12832 GPS GSM mbed

Fork of myBlueUSB_localfix by Nobuaki Aoki

hci.h

Committer:
samialshorman
Date:
2015-04-14
Revision:
3:55a622e3dbb5
Parent:
0:003889bc474f

File content as of revision 3:55a622e3dbb5:

/*
Copyright (c) 2010 Peter Barrett

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef HCI_H_INCLUDED
#define HCI_H_INCLUDED

//#define CONTR_HOST_FLOW     //Controller to Host flow control
#define HOST_CONTR_FLOW     //Host to Controller flow control
#define COMMAND_FLOW        //Command flow control

#include "mbed.h"
#include "Socket.h"

#pragma pack(1)

#define ERR_HCI_DEVICE_NOT_FOUND -300

class HCI;
class HCITransport;
class BTDevice;

typedef struct
{
    u8  addr[6];
} BD_ADDR;

typedef struct
{
    BD_ADDR bdaddr;
    u8  pscan_rep_mode;
    u8  pscan_period_mode;
    u8  pscan_mode;
    u8  dev_class[3];
    u16 clock_offset;
} inquiry_info;

typedef struct
{
    u8  status;
    u16 handle;
    BD_ADDR bdaddr;
    u8  link_type;
    u8  encr_mode;
} connection_info;

//  Address struct for creating L2CAP sockets
typedef struct {
    SocketAddrHdr hdr;
    BD_ADDR bdaddr;
    u16 psm;
} L2CAPAddr;

typedef struct {
    u16    handle;
    u16    length;            // total
    u16    l2capLength;    // length -4
    u16    cid;            // Signaling packet CID = 1

    // Payload
    u8    cmd;            //
    u8    id;
    u16    cmdLength;        // total-8
    u16 params[4];      // Params
} L2CAPCmd;

#pragma pack(4)

class BTDevice;

typedef struct
{
    public:
    SocketInternal si;
    BTDevice* btdevice;
    u16 scid;
    u16 dcid;
} L2CAPSocket;

#define MAX_HCL_NAME_LENGTH 20  // TODO - BTDevice wants to be a multiple of 4

//  BTDevice encapsulates individual device state
//  It provides L2CAP layer sockets

class BTDevice : public SocketHandler
{
    public:
    HCITransport* _transport;
    inquiry_info  _info;
    u16 _handle;     // acl connection handle
    u8  _state;      // connection state
    u8  _txid;
    u16 peer_mtu;
#ifdef HOST_CONTR_FLOW
    u8 pkts_sent;   //host to controller flow control
#endif
//u8 cntr_cred;
u8 segments;
    char   _name[MAX_HCL_NAME_LENGTH];

    void Init();

    BD_ADDR* GetAddress() { return &_info.bdaddr; }

    //  Called from HCI
    int ACLRecv(const u8* data, int len);
    void ACLFwd(const u8* data, int len);

    // SocketHandler
    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
    virtual int Accept(SocketInternal* sock, int scid, int rxid);
    virtual int Send(SocketInternal* sock, const u8* data, int len);
    virtual int Close(SocketInternal* sock);
    virtual char* Name() { return "BTDevice SocketHandler";}

private:
    int l2cap_sock, plen, contPos, contState;
    unsigned char *contBuf;
    Timeout rtx;
    L2CAPCmd last_req;
    void repeat_cmd();
    
    L2CAPSocket* SCIDToSocket(int scid);
    int Send(const u8* data, int len);
    int Send(u8 c, u8 id, u16* params, int count);
    int Connect(int scid, int psm);
    int Disconnect(int scid, int dcid);
    int ConfigureRequest(int dcid);
    int CommandReject(u16 reason=0, u16 data0=0, u16 data1=0);
    int ConfigureResponse(u8 rxid, int dcid);
    int DisconnectResponse(u8 rxid, int scid, int dcid);
    void Control(const u8* data, int len);
};

enum HCI_CALLBACK_EVENT
{
    CALLBACK_NONE,
    CALLBACK_READY,
    CALLBACK_INQUIRY_RESULT,
    CALLBACK_INQUIRY_DONE,
    CALLBACK_REMOTE_NAME,
    CALLBACK_CONNECTION_COMPLETE,
    CALLBACK_CONNECTION_FAILED,
    CALLBACK_PIN_REQ,
    CALLBACK_CMD_STATUS,
    CALLBACK_CONNECTION_REQUEST,
    CALLBACK_VENDOR
};

//  L2CAP Protocol/Service Multiplexor (PSM) values

#define L2CAP_PSM_ANY                   0x0000  /* Any/Invalid PSM */
#define L2CAP_PSM_SDP                   0x0001  /* Service Discovery Protocol */
#define L2CAP_PSM_RFCOMM                0x0003  /* RFCOMM protocol */
#define L2CAP_PSM_TCP                   0x0005  /* Telephony Control Protocol */
#define L2CAP_PSM_TCS                   0x0007  /* TCS cordless */
#define L2CAP_PSM_BNEP                  0x000f  /* Bluetooth Network Encapsulation Protocol*/
#define L2CAP_PSM_HID_CNTL              0x0011  /* HID Control */
#define L2CAP_PSM_HID_INTR              0x0013  /* HID Interrupt */
#define L2CAP_PSM_ESDP                  0x0015  /* Extended Service Discovery Profile */
#define L2CAP_PSM_AVCTP                 0x0017  /* Audio/Visual Control Transport Protocol */
#define L2CAP_PSM_AVDTP                 0x0019  /* Audio/Visual Distribution */

//  Callback from inquiry
typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len);
//typedef int (HCI::*HCICallback)(HCI_CALLBACK_EVENT evt, const u8* data, int len);

#define MAX_BTDEVICES 8

class HCITransport;
class HCI : public SocketHandler
{
    HCITransport* _transport;
    HCICallback _callback;
    BD_ADDR  _localAddr;

    BTDevice _devices[MAX_BTDEVICES];
    int _deviceCount;

    int _acl_mtu;
    int _acl_max_pkt;
    int _sco_mtu;
    int _sco_max_pkt;

    int _state;
#ifdef COMMAND_FLOW
    char cmd_credits;//command flow control
#endif
//, data_credits;//host to controller flow control is per handle, hence is handled in BTDevice
    public:

    //  Open a local adapter
    int Open(HCITransport* transport, HCICallback callback=0);

    //  Return list of discovered addreses
    int GetDevices(BTDevice** devices, int maxDevices);

    //  Lookup a device by address or handle
    BTDevice* Find(const BD_ADDR* addr);
    BTDevice* Find(int handle);

    //  Disconnect from a remote device
    int Disconnect(const BD_ADDR* addr);
    int DisconnectAll();

    //  see what devies are in the system
    int Inquiry(int duration = 10);

    int SetEventFilter(u8 filterType, u8 filterConditionType, u8* condition);
    //  get a name, delivered in callback
    int RemoteNameRequest(const BD_ADDR* addr);
    int RemoteNameRequest(inquiry_info* ii);

    //  Connect to a remote device
    int CreateConnection(const BD_ADDR* remoteAddr);

    bool Busy();

    //  called from transport
    void HCIRecv(const u8* data, int len);

    //  called from transport
    void ACLRecv(const u8* data, int len);

    //  SocketHandler methods for maintaining L2CAP sockets
    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
    virtual int Accept(SocketInternal* sock, int scid, int rxid);
    virtual int Send(SocketInternal* sock, const u8* data, int len);
    virtual int Close(SocketInternal* sock);
    virtual char* Name() { return "HCI SocketHandler";}

private:
    void    InquiryResult(const inquiry_info* info);
    void    RemoteName(const BD_ADDR* addr, const char* name);
    void    ConnectComplete(const connection_info* info);
    void    DisconnectComplete(int handle);
    void    OnCommandComplete(int cmd, const u8* data, int len);
    virtual void    Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
    void Compl_pkts(int handle, u8 p = 1);
protected:
//    int     SendCmd(int cmd, const u8* params = 0, int len = 0);
    int     PinCodeReply(const u8* data, const u8* pin = "0000");
    void    Accept_Connection(const BD_ADDR* addr, bool slave=true);
public:
    int     SendCmd(int cmd, const u8* params = 0, int len = 0);
};

class HCITransport
{
protected:
    HCI* _target;
public:
#ifdef HOST_CONTR_FLOW
    u8 data_credits;
#endif
    u16 _acl_mtu;
    void Set(HCI* target) { _target = target; };
    virtual void HCISend(const u8* data, int len) = 0;
    virtual int ACLSend(const u8* data, int len) = 0;
};

#endif