BlueUSB and Waveplayer merged

Dependencies:   SDFileSystem mbed-rtos mbed wave_player

Fork of z_test_BlueUSBv1 by Stuart Kent

hci.h

Committer:
peterbarrett1967
Date:
2010-04-10
Revision:
0:606b230e5b4a

File content as of revision 0:606b230e5b4a:

/*
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

#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;

#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;
    char   _name[MAX_HCL_NAME_LENGTH];

    void Init();

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

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

    // SocketHandler
    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
    virtual int Send(SocketInternal* sock, const u8* data, int len);
    virtual int Close(SocketInternal* sock);

private:
    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 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
};

//  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);

#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;

    public:

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

    //  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);

    //  get a name, delivered in callback
    int RemoteNameRequest(const BD_ADDR* addr);

    //  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 Send(SocketInternal* sock, const u8* data, int len);
    virtual int Close(SocketInternal* sock);

    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);
    int     SendCmd(int cmd, const u8* params = 0, int len = 0);
    void    OnCommandComplete(int cmd, const u8* data, int len);
    void    Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
    int     PinCodeReply(const u8* data);
};

class HCITransport
{
protected:
    HCI* _target;
public:
    void Set(HCI* target) { _target = target; };
    virtual void HCISend(const u8* data, int len) = 0;
    virtual void ACLSend(const u8* data, int len) = 0;
};

#endif