local fix version of myBlueUSB (http://mbed.org/users/networker/code/myBlueUSB/). - merge deleted files which are required to compile. - enable echo back of received data via RFCOMM.

Dependencies:   AvailableMemory FatFileSystem mbed myUSBHost

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci.h Source File

hci.h

00001 /*
00002 Copyright (c) 2010 Peter Barrett
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 #ifndef HCI_H_INCLUDED
00024 #define HCI_H_INCLUDED
00025 
00026 //#define CONTR_HOST_FLOW     //Controller to Host flow control
00027 #define HOST_CONTR_FLOW     //Host to Controller flow control
00028 #define COMMAND_FLOW        //Command flow control
00029 
00030 #include "mbed.h"
00031 #include "Socket.h"
00032 
00033 #pragma pack(1)
00034 
00035 #define ERR_HCI_DEVICE_NOT_FOUND -300
00036 
00037 class HCI;
00038 class HCITransport;
00039 class BTDevice;
00040 
00041 typedef struct
00042 {
00043     u8  addr[6];
00044 } BD_ADDR;
00045 
00046 typedef struct
00047 {
00048     BD_ADDR bdaddr;
00049     u8  pscan_rep_mode;
00050     u8  pscan_period_mode;
00051     u8  pscan_mode;
00052     u8  dev_class[3];
00053     u16 clock_offset;
00054 } inquiry_info;
00055 
00056 typedef struct
00057 {
00058     u8  status;
00059     u16 handle;
00060     BD_ADDR bdaddr;
00061     u8  link_type;
00062     u8  encr_mode;
00063 } connection_info;
00064 
00065 //  Address struct for creating L2CAP sockets
00066 typedef struct {
00067     SocketAddrHdr hdr;
00068     BD_ADDR bdaddr;
00069     u16 psm;
00070 } L2CAPAddr;
00071 
00072 typedef struct {
00073     u16    handle;
00074     u16    length;            // total
00075     u16    l2capLength;    // length -4
00076     u16    cid;            // Signaling packet CID = 1
00077 
00078     // Payload
00079     u8    cmd;            //
00080     u8    id;
00081     u16    cmdLength;        // total-8
00082     u16 params[4];      // Params
00083 } L2CAPCmd;
00084 
00085 #pragma pack(4)
00086 
00087 class BTDevice;
00088 
00089 typedef struct
00090 {
00091     public:
00092     SocketInternal si;
00093     BTDevice* btdevice;
00094     u16 scid;
00095     u16 dcid;
00096 } L2CAPSocket;
00097 
00098 #define MAX_HCL_NAME_LENGTH 20  // TODO - BTDevice wants to be a multiple of 4
00099 
00100 //  BTDevice encapsulates individual device state
00101 //  It provides L2CAP layer sockets
00102 
00103 class BTDevice : public SocketHandler
00104 {
00105     public:
00106     HCITransport* _transport;
00107     inquiry_info  _info;
00108     u16 _handle;     // acl connection handle
00109     u8  _state;      // connection state
00110     u8  _txid;
00111     u16 peer_mtu;
00112 #ifdef HOST_CONTR_FLOW
00113     u8 pkts_sent;   //host to controller flow control
00114 #endif
00115 //u8 cntr_cred;
00116 u8 segments;
00117     char   _name[MAX_HCL_NAME_LENGTH];
00118 
00119     void Init();
00120 
00121     BD_ADDR* GetAddress() { return &_info.bdaddr; }
00122 
00123     //  Called from HCI
00124     int ACLRecv(const u8* data, int len);
00125     void ACLFwd(const u8* data, int len);
00126 
00127     // SocketHandler
00128     virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
00129     virtual int Accept(SocketInternal* sock, int scid, int rxid);
00130     virtual int Send(SocketInternal* sock, const u8* data, int len);
00131     virtual int Close(SocketInternal* sock);
00132     virtual char* Name() { return "BTDevice SocketHandler";}
00133 
00134 private:
00135     int l2cap_sock, plen, contPos, contState;
00136     unsigned char *contBuf;
00137     Timeout rtx;
00138     L2CAPCmd last_req;
00139     void repeat_cmd();
00140     
00141     L2CAPSocket* SCIDToSocket(int scid);
00142     int Send(const u8* data, int len);
00143     int Send(u8 c, u8 id, u16* params, int count);
00144     int Connect(int scid, int psm);
00145     int Disconnect(int scid, int dcid);
00146     int ConfigureRequest(int dcid);
00147     int CommandReject(u16 reason=0, u16 data0=0, u16 data1=0);
00148     int ConfigureResponse(u8 rxid, int dcid);
00149     int DisconnectResponse(u8 rxid, int scid, int dcid);
00150     void Control(const u8* data, int len);
00151 };
00152 
00153 enum HCI_CALLBACK_EVENT
00154 {
00155     CALLBACK_NONE,
00156     CALLBACK_READY,
00157     CALLBACK_INQUIRY_RESULT,
00158     CALLBACK_INQUIRY_DONE,
00159     CALLBACK_REMOTE_NAME,
00160     CALLBACK_CONNECTION_COMPLETE,
00161     CALLBACK_CONNECTION_FAILED,
00162     CALLBACK_PIN_REQ,
00163     CALLBACK_CMD_STATUS,
00164     CALLBACK_CONNECTION_REQUEST,
00165     CALLBACK_VENDOR
00166 };
00167 
00168 //  L2CAP Protocol/Service Multiplexor (PSM) values
00169 
00170 #define L2CAP_PSM_ANY                   0x0000  /* Any/Invalid PSM */
00171 #define L2CAP_PSM_SDP                   0x0001  /* Service Discovery Protocol */
00172 #define L2CAP_PSM_RFCOMM                0x0003  /* RFCOMM protocol */
00173 #define L2CAP_PSM_TCP                   0x0005  /* Telephony Control Protocol */
00174 #define L2CAP_PSM_TCS                   0x0007  /* TCS cordless */
00175 #define L2CAP_PSM_BNEP                  0x000f  /* Bluetooth Network Encapsulation Protocol*/
00176 #define L2CAP_PSM_HID_CNTL              0x0011  /* HID Control */
00177 #define L2CAP_PSM_HID_INTR              0x0013  /* HID Interrupt */
00178 #define L2CAP_PSM_ESDP                  0x0015  /* Extended Service Discovery Profile */
00179 #define L2CAP_PSM_AVCTP                 0x0017  /* Audio/Visual Control Transport Protocol */
00180 #define L2CAP_PSM_AVDTP                 0x0019  /* Audio/Visual Distribution */
00181 
00182 //  Callback from inquiry
00183 typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len);
00184 //typedef int (HCI::*HCICallback)(HCI_CALLBACK_EVENT evt, const u8* data, int len);
00185 
00186 #define MAX_BTDEVICES 8
00187 
00188 class HCITransport;
00189 class HCI : public SocketHandler
00190 {
00191     HCITransport* _transport;
00192     HCICallback _callback;
00193     BD_ADDR  _localAddr;
00194 
00195     BTDevice _devices[MAX_BTDEVICES];
00196     int _deviceCount;
00197 
00198     int _acl_mtu;
00199     int _acl_max_pkt;
00200     int _sco_mtu;
00201     int _sco_max_pkt;
00202 
00203     int _state;
00204 #ifdef COMMAND_FLOW
00205     char cmd_credits;//command flow control
00206 #endif
00207 //, data_credits;//host to controller flow control is per handle, hence is handled in BTDevice
00208     public:
00209 
00210     //  Open a local adapter
00211     int Open(HCITransport* transport, HCICallback callback=0);
00212 
00213     //  Return list of discovered addreses
00214     int GetDevices(BTDevice** devices, int maxDevices);
00215 
00216     //  Lookup a device by address or handle
00217     BTDevice* Find(const BD_ADDR* addr);
00218     BTDevice* Find(int handle);
00219 
00220     //  Disconnect from a remote device
00221     int Disconnect(const BD_ADDR* addr);
00222     int DisconnectAll();
00223 
00224     //  see what devies are in the system
00225     int Inquiry(int duration = 10);
00226 
00227     int SetEventFilter(u8 filterType, u8 filterConditionType, u8* condition);
00228     //  get a name, delivered in callback
00229     int RemoteNameRequest(const BD_ADDR* addr);
00230     int RemoteNameRequest(inquiry_info* ii);
00231 
00232     //  Connect to a remote device
00233     int CreateConnection(const BD_ADDR* remoteAddr);
00234 
00235     bool Busy();
00236 
00237     //  called from transport
00238     void HCIRecv(const u8* data, int len);
00239 
00240     //  called from transport
00241     void ACLRecv(const u8* data, int len);
00242 
00243     //  SocketHandler methods for maintaining L2CAP sockets
00244     virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
00245     virtual int Accept(SocketInternal* sock, int scid, int rxid);
00246     virtual int Send(SocketInternal* sock, const u8* data, int len);
00247     virtual int Close(SocketInternal* sock);
00248     virtual char* Name() { return "HCI SocketHandler";}
00249 
00250 private:
00251     void    InquiryResult(const inquiry_info* info);
00252     void    RemoteName(const BD_ADDR* addr, const char* name);
00253     void    ConnectComplete(const connection_info* info);
00254     void    DisconnectComplete(int handle);
00255     void    OnCommandComplete(int cmd, const u8* data, int len);
00256     virtual void    Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
00257     void Compl_pkts(int handle, u8 p = 1);
00258 protected:
00259 //    int     SendCmd(int cmd, const u8* params = 0, int len = 0);
00260     int     PinCodeReply(const u8* data, const u8* pin = "0000");
00261     void    Accept_Connection(const BD_ADDR* addr, bool slave=true);
00262 public:
00263     int     SendCmd(int cmd, const u8* params = 0, int len = 0);
00264 };
00265 
00266 class HCITransport
00267 {
00268 protected:
00269     HCI* _target;
00270 public:
00271 #ifdef HOST_CONTR_FLOW
00272     u8 data_credits;
00273 #endif
00274     u16 _acl_mtu;
00275     void Set(HCI* target) { _target = target; };
00276     virtual void HCISend(const u8* data, int len) = 0;
00277     virtual int ACLSend(const u8* data, int len) = 0;
00278 };
00279 
00280 #endif