class library to access fischertechnik interfaces via USB

Dependencies:   FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp

Committer:
networker
Date:
Wed Jun 15 19:12:25 2011 +0000
Revision:
0:7da612835693
initial version
; Bluetooth support incomplete

Who changed what in which revision?

UserRevisionLine numberNew contents of line
networker 0:7da612835693 1 #ifndef RFCOMM_H
networker 0:7da612835693 2 #define RFCOMM_H
networker 0:7da612835693 3 #include "USBHost.h"
networker 0:7da612835693 4 #include "hci.h"
networker 0:7da612835693 5 #include "Utils.h"
networker 0:7da612835693 6
networker 0:7da612835693 7 #define MAX_RFCOMM_SCKTS 4
networker 0:7da612835693 8 /*
networker 0:7da612835693 9 template <class T>
networker 0:7da612835693 10 T min(T a, T b) {
networker 0:7da612835693 11 return a<b ? a : b;
networker 0:7da612835693 12 }
networker 0:7da612835693 13 */
networker 0:7da612835693 14
networker 0:7da612835693 15 #define MASK_BITRATE 0X0001
networker 0:7da612835693 16 #define MASK_DATABITS 0X0002
networker 0:7da612835693 17 #define MASK_STOPBITS 0X0004
networker 0:7da612835693 18 #define MASK_PARITYBITS 0X0008
networker 0:7da612835693 19 #define MASK_PARITYTYPE 0X0010
networker 0:7da612835693 20 #define MASK_XONCHAR 0X0020
networker 0:7da612835693 21 #define MASK_XOFFCHAR 0X0040
networker 0:7da612835693 22 #define MASK_XONXOFFIN 0X0100
networker 0:7da612835693 23 #define MASK_XONXOFFOUT 0X0200
networker 0:7da612835693 24 #define MASK_RTRIN 0X0400
networker 0:7da612835693 25 #define MASK_RTROUT 0X0800
networker 0:7da612835693 26 #define MASK_RTCIN 0X1000
networker 0:7da612835693 27 #define MASK_RTCOUT 0X2000
networker 0:7da612835693 28
networker 0:7da612835693 29 struct port_settings {
networker 0:7da612835693 30 unsigned char baud;
networker 0:7da612835693 31 unsigned char bits:
networker 0:7da612835693 32 2;
networker 0:7da612835693 33 unsigned char stop:
networker 0:7da612835693 34 1;
networker 0:7da612835693 35 unsigned char par:
networker 0:7da612835693 36 1;
networker 0:7da612835693 37 unsigned char par_t:
networker 0:7da612835693 38 2;
networker 0:7da612835693 39 unsigned char :
networker 0:7da612835693 40 2;
networker 0:7da612835693 41 unsigned char flow:
networker 0:7da612835693 42 6;
networker 0:7da612835693 43 unsigned char :
networker 0:7da612835693 44 2;
networker 0:7da612835693 45 unsigned char xon;
networker 0:7da612835693 46 unsigned char xoff;
networker 0:7da612835693 47 unsigned short mask;
networker 0:7da612835693 48 };
networker 0:7da612835693 49
networker 0:7da612835693 50 class rfcomm;
networker 0:7da612835693 51 class RFCOMMManager;
networker 0:7da612835693 52 #define MAX_RFCOMM_DEVICES 8 //physical devices
networker 0:7da612835693 53
networker 0:7da612835693 54 class RFCOMMSocket: public SocketInternal {//this object must not be larger than SocketInternalPad (socketinternal + 8 bytes)
networker 0:7da612835693 55 public:
networker 0:7da612835693 56 rfcomm* serdevice;
networker 0:7da612835693 57 u8 dlci; //channel + D bit, D bit is inverted initiator bit
networker 0:7da612835693 58 u8 my_credits, peer_credits;
networker 0:7da612835693 59 };
networker 0:7da612835693 60
networker 0:7da612835693 61 class rfcomm: public SocketHandler {
networker 0:7da612835693 62 int _l2cap; //socket to the l2cap layer
networker 0:7da612835693 63 int _devClass;
networker 0:7da612835693 64 BD_ADDR _addr;
networker 0:7da612835693 65 u8 initiator;
networker 0:7da612835693 66 u8 _pad[0]; // Struct align
networker 0:7da612835693 67 char sckts[MAX_RFCOMM_SCKTS];
networker 0:7da612835693 68 static unsigned maxframesize;
networker 0:7da612835693 69 int find_slot(unsigned ch);
networker 0:7da612835693 70 RFCOMMSocket* find_socket(unsigned dlci);
networker 0:7da612835693 71 void initChannels(int socket);
networker 0:7da612835693 72 unsigned release_channel(unsigned dlci);
networker 0:7da612835693 73 static void OnRfCommControl(int socket, SocketState state, const u8* data, int len, void* userData);//I guess this is called when data comes out of the socket
networker 0:7da612835693 74 int Disconnect(RFCOMMSocket*);
networker 0:7da612835693 75 public:
networker 0:7da612835693 76 rfcomm() : _l2cap(0), _devClass(0) {
networker 0:7da612835693 77 for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) sckts[i] = 0;
networker 0:7da612835693 78 }
networker 0:7da612835693 79
networker 0:7da612835693 80 bool InUse() {
networker 0:7da612835693 81 return _l2cap != 0;
networker 0:7da612835693 82 }
networker 0:7da612835693 83 virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
networker 0:7da612835693 84 virtual int Send(SocketInternal* sock, const u8* data, int len);//wrap data in RFCOMM frame and dispatch
networker 0:7da612835693 85 virtual int Close(SocketInternal* sock);
networker 0:7da612835693 86 virtual char* Name() {
networker 0:7da612835693 87 return "rfcomm SocketHandler";
networker 0:7da612835693 88 }
networker 0:7da612835693 89 void Recv(const u8* data, int len) {
networker 0:7da612835693 90 printf("rfcomm::Recv was called\n");
networker 0:7da612835693 91 }
networker 0:7da612835693 92 #if 0
networker 0:7da612835693 93 int Listen(unsigned char ch=0) {//passive open, similar semantics to 'Open' but connection is only made at request of the peer
networker 0:7da612835693 94 RFCOMMSocket *s = 0;//this entity may or may not be bound to a remote entity
networker 0:7da612835693 95 if (ch>0) {//specific channel
networker 0:7da612835693 96 s = find_socket(ch<<1);
networker 0:7da612835693 97 if (s) { //socket for this channel already in use
networker 0:7da612835693 98 printf("rfcomm::Listen: channel %d already in use\n", ch);
networker 0:7da612835693 99 return 0;
networker 0:7da612835693 100 } //else s==0, no socket for channel ch
networker 0:7da612835693 101 }//else listen to any channel
networker 0:7da612835693 102 int sn = find_slot(ch);
networker 0:7da612835693 103 if (sn<0) {
networker 0:7da612835693 104 printf("No socket could be found for channel %d\n", ch);
networker 0:7da612835693 105 return 0;
networker 0:7da612835693 106 } //else use slot 'sn' for the new rfcomm socket
networker 0:7da612835693 107 int sock = Socket_Create(SOCKET_RFCOM, OnRfCommControl, this);//allocate an rfcomm socket
networker 0:7da612835693 108 sckts[sn] = sock; //claim the socket
networker 0:7da612835693 109 RFCOMMSocket *rs = (RFCOMMSocket*)GetSocketInternal(sock);
networker 0:7da612835693 110 rs->serdevice = this;
networker 0:7da612835693 111 rs->dlci = (ch<<1)|1;//server socket
networker 0:7da612835693 112 //initiator = 0; what to do if already connected actively on different channel???
networker 0:7da612835693 113 /*l2cap is already present or is created when accepting the connection
networker 0:7da612835693 114 if (_l2cap == 0) { //no rfcomm -> l2cap connection yet
networker 0:7da612835693 115 printf("Need to open L2CAP channel first before opening RFCOMM channel %d\n", rs->dlci);
networker 0:7da612835693 116 ((L2CAPAddr*)addr)->psm = L2CAP_PSM_RFCOMM;//open the l2cap channel and the rfcomm_ch channel
networker 0:7da612835693 117 initiator = 0;
networker 0:7da612835693 118 _l2cap = Socket_Create(SOCKET_L2CAP, addr, OnRfCommControl, this);//this is the socket between the RFCOMM and the L2CAP layer
networker 0:7da612835693 119 if (_l2cap)
networker 0:7da612835693 120 printf("Successfully opened L2CAP channel on socket %d\n", _l2cap);
networker 0:7da612835693 121 else {
networker 0:7da612835693 122 printf("Opening L2CAP channel failed\n");
networker 0:7da612835693 123 return 0;
networker 0:7da612835693 124 }
networker 0:7da612835693 125 }
networker 0:7da612835693 126 */
networker 0:7da612835693 127 return sock;
networker 0:7da612835693 128 }
networker 0:7da612835693 129 #endif
networker 0:7da612835693 130 //int Open(BD_ADDR* bdAddr, inquiry_info* info);
networker 0:7da612835693 131 int set_remote_port_parameters(unsigned char dlci, port_settings *p);
networker 0:7da612835693 132 friend RFCOMMManager;
networker 0:7da612835693 133 };
networker 0:7da612835693 134
networker 0:7da612835693 135 class RFCOMMManager: public SocketHandler {
networker 0:7da612835693 136 rfcomm _devs[MAX_RFCOMM_DEVICES];
networker 0:7da612835693 137 int serverSock;
networker 0:7da612835693 138 char sckts[MAX_RFCOMM_SCKTS];//listening sockets
networker 0:7da612835693 139 public:
networker 0:7da612835693 140 virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
networker 0:7da612835693 141 L2CAPAddr* ad = (L2CAPAddr*)addr;
networker 0:7da612835693 142 BD_ADDR* a = &ad->bdaddr;
networker 0:7da612835693 143 rfcomm *r = FindRfCommDevice(a);
networker 0:7da612835693 144 if (r==0)
networker 0:7da612835693 145 r = NewRfCommDevice();
networker 0:7da612835693 146 if (r==0)
networker 0:7da612835693 147 return 0;
networker 0:7da612835693 148 return r->Open(sock, addr);
networker 0:7da612835693 149 }
networker 0:7da612835693 150
networker 0:7da612835693 151 int FindSocket(BTDevice* dev) {//finds the l2cap socket for a certain rfcomm-btdevice connection
networker 0:7da612835693 152 for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) {
networker 0:7da612835693 153 rfcomm *r = _devs+i;
networker 0:7da612835693 154 int l2cap = r->_l2cap;
networker 0:7da612835693 155 if (l2cap) {
networker 0:7da612835693 156 L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap);
networker 0:7da612835693 157 if (p->btdevice == dev)
networker 0:7da612835693 158 return l2cap;
networker 0:7da612835693 159 }
networker 0:7da612835693 160 }
networker 0:7da612835693 161 return 0;
networker 0:7da612835693 162 }
networker 0:7da612835693 163
networker 0:7da612835693 164 rfcomm* FindDev(BTDevice* dev) {//finds the rfcomm entity for a certain rfcomm-btdevice connection
networker 0:7da612835693 165 for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) {
networker 0:7da612835693 166 rfcomm *r = _devs+i;
networker 0:7da612835693 167 int l2cap = r->_l2cap;
networker 0:7da612835693 168 if (l2cap) {
networker 0:7da612835693 169 L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap);
networker 0:7da612835693 170 if (p->btdevice == dev)
networker 0:7da612835693 171 return r;
networker 0:7da612835693 172 }
networker 0:7da612835693 173 }
networker 0:7da612835693 174 return 0;
networker 0:7da612835693 175 }
networker 0:7da612835693 176
networker 0:7da612835693 177 int BindSocket(int s) {
networker 0:7da612835693 178 L2CAPSocket *ls = (L2CAPSocket*)GetSocketInternal(s);
networker 0:7da612835693 179 printf("Binding l2cap socket %d to a new rfcomm server entity\n", s);
networker 0:7da612835693 180 rfcomm *r = NewRfCommDevice();
networker 0:7da612835693 181 r->_l2cap = s;
networker 0:7da612835693 182 r->initiator = 0;//we are server
networker 0:7da612835693 183 ls->si.userData = r;//was BTDevice, make rfcomm
networker 0:7da612835693 184 return 0;
networker 0:7da612835693 185 }
networker 0:7da612835693 186
networker 0:7da612835693 187 int new_slot(unsigned ch) {
networker 0:7da612835693 188 for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
networker 0:7da612835693 189 if (sckts[i] != 0) { //socket is in use
networker 0:7da612835693 190 RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
networker 0:7da612835693 191 if (s==0) {
networker 0:7da612835693 192 printf("find_slot: socket %d not found\n", sckts[i]);
networker 0:7da612835693 193 continue;
networker 0:7da612835693 194 }
networker 0:7da612835693 195 if ((s->dlci >> 1) == ch) {
networker 0:7da612835693 196 printf("Channel %d is already in use on socket %d\n", ch, sckts[i]);
networker 0:7da612835693 197 return -1;
networker 0:7da612835693 198 }
networker 0:7da612835693 199 } else //slot is free
networker 0:7da612835693 200 return i;
networker 0:7da612835693 201 }
networker 0:7da612835693 202 return -2; //no free slots
networker 0:7da612835693 203 }
networker 0:7da612835693 204
networker 0:7da612835693 205 int find_socket(unsigned ch) {
networker 0:7da612835693 206 for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
networker 0:7da612835693 207 if (sckts[i] != 0) { //socket is in use
networker 0:7da612835693 208 RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
networker 0:7da612835693 209 if (s==0) {
networker 0:7da612835693 210 printf("find_slot: socket %d not found\n", sckts[i]);
networker 0:7da612835693 211 continue;
networker 0:7da612835693 212 }
networker 0:7da612835693 213 if ((s->dlci >> 1) == ch) {
networker 0:7da612835693 214 printf("Found Channel %d on socket %d\n", ch, sckts[i]);
networker 0:7da612835693 215 return sckts[i];
networker 0:7da612835693 216 }
networker 0:7da612835693 217 else
networker 0:7da612835693 218 printf("slot %d has socket %d has dlci %d\n", i, sckts[i], s->dlci);
networker 0:7da612835693 219 }
networker 0:7da612835693 220 else
networker 0:7da612835693 221 printf("Slot %d is free\n", i);
networker 0:7da612835693 222 }
networker 0:7da612835693 223 printf("channel %d not found\n", ch);
networker 0:7da612835693 224 return 0; //channel not found
networker 0:7da612835693 225 }
networker 0:7da612835693 226
networker 0:7da612835693 227 int remove_socket(int sock) {
networker 0:7da612835693 228 for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
networker 0:7da612835693 229 if (sckts[i] == sock) {
networker 0:7da612835693 230 sckts[i] = 0;
networker 0:7da612835693 231 return 0;
networker 0:7da612835693 232 }
networker 0:7da612835693 233 }
networker 0:7da612835693 234 return -1;
networker 0:7da612835693 235 }
networker 0:7da612835693 236
networker 0:7da612835693 237 virtual int Listen(SocketInternal* sock, int ch) {//called by Socket_Listen(SOCKET_RFCOM, channel, callback, userData)
networker 0:7da612835693 238 int slot = new_slot(ch);
networker 0:7da612835693 239 switch (slot) {
networker 0:7da612835693 240 case -1:
networker 0:7da612835693 241 printf("There is already someone listening on ch %d\n", ch);
networker 0:7da612835693 242 return ERR_SOCKET_CANT_LISTEN;//channel is occupied
networker 0:7da612835693 243 case -2:
networker 0:7da612835693 244 printf("All listener sockets are in use\n");
networker 0:7da612835693 245 return ERR_SOCKET_NONE_LEFT;
networker 0:7da612835693 246 }
networker 0:7da612835693 247 RFCOMMSocket *rs = (RFCOMMSocket*)sock;
networker 0:7da612835693 248 const char dir = 0;
networker 0:7da612835693 249 rs->dlci = (ch<<1)|dir;
networker 0:7da612835693 250 rs->State = SocketState_Listen;
networker 0:7da612835693 251 rs->serdevice = 0;//don't know yet
networker 0:7da612835693 252 sckts[slot] = rs->ID;
networker 0:7da612835693 253 printf("RFCOMM listener socket %d for ch %d (dlci 0x%02X) is assigned to slot %d\n", rs->ID, ch, rs->dlci, slot);
networker 0:7da612835693 254 return rs->ID;
networker 0:7da612835693 255 }
networker 0:7da612835693 256 /*
networker 0:7da612835693 257 virtual int Accept(SocketInternal *sock, int scid, int rxid) { //called indirectly from BTDevice::Control
networker 0:7da612835693 258 //sock is registered as an RFCOMM sock but we use it as an L2CAP sock
networker 0:7da612835693 259 //sock->type=RFCOM, meaning open/close/send/accept go to RFCOMMManager first
networker 0:7da612835693 260 //sock->userData = BTDevice, necessary to make the call back to BTDevice::Accept
networker 0:7da612835693 261 //Internal = L2CAPSocket, for scid, dcid
networker 0:7da612835693 262 BTDevice *l2cap = (BTDevice*)sock->userData;
networker 0:7da612835693 263 //sock->si.dcid = scid
networker 0:7da612835693 264 //sock->si.scid = something based on sock->ID
networker 0:7da612835693 265 serverSock = sock->ID;
networker 0:7da612835693 266 printf("Invoking accept on %p (%s) for sock %d and scid=%d\n", l2cap, l2cap->Name(), sock->ID, scid);
networker 0:7da612835693 267 return l2cap->Accept(sock, scid, rxid); //connect 'serverSock' to the remote RFCOMM client
networker 0:7da612835693 268 }
networker 0:7da612835693 269 */
networker 0:7da612835693 270 virtual int Send(SocketInternal* sock, const u8* data, int len) {
networker 0:7da612835693 271 RFCOMMSocket *s = (RFCOMMSocket*)sock;
networker 0:7da612835693 272 return s->serdevice->Send(sock, data, len);
networker 0:7da612835693 273 }
networker 0:7da612835693 274
networker 0:7da612835693 275 virtual int Close(SocketInternal* sock) {
networker 0:7da612835693 276 RFCOMMSocket *s = (RFCOMMSocket*)sock;
networker 0:7da612835693 277 return s->serdevice->Close(sock);
networker 0:7da612835693 278 }
networker 0:7da612835693 279
networker 0:7da612835693 280 virtual char* Name() {
networker 0:7da612835693 281 return "RFCOMMManager SocketHandler";
networker 0:7da612835693 282 }
networker 0:7da612835693 283
networker 0:7da612835693 284 rfcomm* NewRfCommDevice() {//allocate a new RFCOMM device from the pool
networker 0:7da612835693 285 for (int i = 0; i < MAX_RFCOMM_DEVICES; i++)
networker 0:7da612835693 286 if (!_devs[i].InUse())
networker 0:7da612835693 287 return _devs+i;
networker 0:7da612835693 288 return 0;
networker 0:7da612835693 289 }
networker 0:7da612835693 290
networker 0:7da612835693 291 rfcomm* FindRfCommDevice(BD_ADDR* ad) {//get a specific RFCOMM device from the pool
networker 0:7da612835693 292 for (int i = 0; i < MAX_RFCOMM_DEVICES; i++)
networker 0:7da612835693 293 if (_devs[i].InUse() && memcmp(ad, &_devs[i]._addr, 6)==0)
networker 0:7da612835693 294 return _devs+i;
networker 0:7da612835693 295 return 0;
networker 0:7da612835693 296 }
networker 0:7da612835693 297
networker 0:7da612835693 298 static void SerServer(int socket, SocketState state, const u8* data, int len, void* userData) {
networker 0:7da612835693 299 printfBytes("SerServer: ", data, len);
networker 0:7da612835693 300 //userData is the rfcomm
networker 0:7da612835693 301 rfcomm::OnRfCommControl(socket, state, data, len, userData);
networker 0:7da612835693 302 }
networker 0:7da612835693 303 //friend rfcomm;
networker 0:7da612835693 304 };
networker 0:7da612835693 305
networker 0:7da612835693 306 int set_remote_port_parameters(int socket, port_settings *p);
networker 0:7da612835693 307 extern RFCOMMManager rfcomm_manager;
networker 0:7da612835693 308
networker 0:7da612835693 309 #endif