![](/media/cache/profiles/67b3bc4441cb4e9e2e38cb5586931c0c.jpg.50x50_q85.jpg)
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
Diff: rfcomm/RFCOMM.h
- Revision:
- 0:003889bc474f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rfcomm/RFCOMM.h Sat Dec 07 14:19:00 2013 +0000 @@ -0,0 +1,326 @@ +#ifndef RFCOMM_H +#define RFCOMM_H +#include "USBHost.h" +#include "hci.h" +#include "Utils.h" + +#define MAX_RFCOMM_SCKTS 4 +//#define MAX_FRAME_SIZE 350 //ACL buffer - some headroom +#define MAX_FRAME_SIZE 127 //ft size + +/* +template <class T> +T min(T a, T b) { + return a<b ? a : b; +} +*/ + +#define MASK_BITRATE 0X0001 +#define MASK_DATABITS 0X0002 +#define MASK_STOPBITS 0X0004 +#define MASK_PARITYBITS 0X0008 +#define MASK_PARITYTYPE 0X0010 +#define MASK_XONCHAR 0X0020 +#define MASK_XOFFCHAR 0X0040 +#define MASK_XONXOFFIN 0X0100 +#define MASK_XONXOFFOUT 0X0200 +#define MASK_RTRIN 0X0400 +#define MASK_RTROUT 0X0800 +#define MASK_RTCIN 0X1000 +#define MASK_RTCOUT 0X2000 + +struct port_settings { + unsigned char baud; +unsigned char bits: + 2; +unsigned char stop: + 1; +unsigned char par: + 1; +unsigned char par_t: + 2; +unsigned char : + 2; +unsigned char flow: + 6; +unsigned char : + 2; + unsigned char xon; + unsigned char xoff; + unsigned short mask; +}; + +class rfcomm; +class RFCOMMManager; +#define MAX_RFCOMM_DEVICES 8 //physical devices + +class RFCOMMSocket: public SocketInternal {//this object must not be larger than SocketInternalPad (socketinternal + 8 bytes) +public: + rfcomm* serdevice; + u8 dlci; //channel + D bit, D bit is inverted initiator bit + u8 my_credits, peer_credits; +}; + +class rfcomm: public SocketHandler { + int _l2cap; //socket to the l2cap layer + int _devClass; + BD_ADDR _addr; + u8 initiator; + u8 _pad[0]; // Struct align + char sckts[MAX_RFCOMM_SCKTS]; + //static + unsigned maxframesize; + int find_slot(unsigned ch); + RFCOMMSocket* find_socket(unsigned dlci); + void initChannels(int socket); + unsigned release_channel(unsigned dlci); + 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 + int Disconnect(RFCOMMSocket*); +public: + rfcomm() : _l2cap(0), _devClass(0) { + for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) sckts[i] = 0; + maxframesize = MAX_FRAME_SIZE; + } + + bool InUse() { + return _l2cap != 0; + } + virtual int Open(SocketInternal* sock, SocketAddrHdr* addr); + virtual int Send(SocketInternal* sock, const u8* data, int len);//wrap data in RFCOMM frame and dispatch + virtual int SetOpt(SocketInternal *sock, int so, int* data, int len); + virtual int GetOpt(SocketInternal *sock, int so, int* data, int len); + virtual int Close(SocketInternal* sock); + virtual char* Name() { + return "rfcomm SocketHandler"; + } + void Recv(const u8* data, int len) { + printf("rfcomm::Recv was called\n"); + } +#if 0 + int Listen(unsigned char ch=0) {//passive open, similar semantics to 'Open' but connection is only made at request of the peer + RFCOMMSocket *s = 0;//this entity may or may not be bound to a remote entity + if (ch>0) {//specific channel + s = find_socket(ch<<1); + if (s) { //socket for this channel already in use + printf("rfcomm::Listen: channel %d already in use\n", ch); + return 0; + } //else s==0, no socket for channel ch + }//else listen to any channel + int sn = find_slot(ch); + if (sn<0) { + printf("No socket could be found for channel %d\n", ch); + return 0; + } //else use slot 'sn' for the new rfcomm socket + int sock = Socket_Create(SOCKET_RFCOM, OnRfCommControl, this);//allocate an rfcomm socket + sckts[sn] = sock; //claim the socket + RFCOMMSocket *rs = (RFCOMMSocket*)GetSocketInternal(sock); + rs->serdevice = this; + rs->dlci = (ch<<1)|1;//server socket + //initiator = 0; what to do if already connected actively on different channel??? + /*l2cap is already present or is created when accepting the connection + if (_l2cap == 0) { //no rfcomm -> l2cap connection yet + printf("Need to open L2CAP channel first before opening RFCOMM channel %d\n", rs->dlci); + ((L2CAPAddr*)addr)->psm = L2CAP_PSM_RFCOMM;//open the l2cap channel and the rfcomm_ch channel + initiator = 0; + _l2cap = Socket_Create(SOCKET_L2CAP, addr, OnRfCommControl, this);//this is the socket between the RFCOMM and the L2CAP layer + if (_l2cap) + printf("Successfully opened L2CAP channel on socket %d\n", _l2cap); + else { + printf("Opening L2CAP channel failed\n"); + return 0; + } + } + */ + return sock; + } +#endif + //int Open(BD_ADDR* bdAddr, inquiry_info* info); + int set_remote_port_parameters(unsigned char dlci, port_settings *p); + friend RFCOMMManager; +}; + +class RFCOMMManager: public SocketHandler { + rfcomm _devs[MAX_RFCOMM_DEVICES]; + int serverSock; + char sckts[MAX_RFCOMM_SCKTS];//listening sockets +public: + virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) { + L2CAPAddr* ad = (L2CAPAddr*)addr; + BD_ADDR* a = &ad->bdaddr; + rfcomm *r = FindRfCommDevice(a); + if (r==0) + r = NewRfCommDevice(); + if (r==0) + return 0; + return r->Open(sock, addr); + } + + int FindSocket(BTDevice* dev) {//finds the l2cap socket for a certain rfcomm-btdevice connection + for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) { + rfcomm *r = _devs+i; + int l2cap = r->_l2cap; + if (l2cap) { + L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap); + if (p->btdevice == dev) + return l2cap; + } + } + return 0; + } + + rfcomm* FindDev(BTDevice* dev) {//finds the rfcomm entity for a certain rfcomm-btdevice connection + for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) { + rfcomm *r = _devs+i; + int l2cap = r->_l2cap; + if (l2cap) { + L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap); + if (p->btdevice == dev) + return r; + } + } + return 0; + } + + int BindSocket(int s) { + L2CAPSocket *ls = (L2CAPSocket*)GetSocketInternal(s); + printf("Binding l2cap socket %d to a new rfcomm server entity\n", s); + rfcomm *r = NewRfCommDevice(); + r->_l2cap = s; + r->initiator = 0;//we are server + ls->si.userData = r;//was BTDevice, make rfcomm + return 0; + } + + int new_slot(unsigned ch) { + for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) { + if (sckts[i] != 0) { //socket is in use + RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]); + if (s==0) { + printf("find_slot: socket %d not found\n", sckts[i]); + continue; + } + if ((s->dlci >> 1) == ch) { + printf("Channel %d is already in use on socket %d\n", ch, sckts[i]); + return -1; + } + } else //slot is free + return i; + } + return -2; //no free slots + } + + int find_socket(unsigned ch) { + for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) { + if (sckts[i] != 0) { //socket is in use + RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]); + if (s==0) { + printf("find_slot: socket %d not found\n", sckts[i]); + continue; + } + if ((s->dlci >> 1) == ch) { + printf("Found Channel %d on socket %d\n", ch, sckts[i]); + return sckts[i]; + } + else + printf("slot %d has socket %d has dlci %d\n", i, sckts[i], s->dlci); + } + else + printf("Slot %d is free\n", i); + } + printf("channel %d not found\n", ch); + return 0; //channel not found + } + + int remove_socket(int sock) { + for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) { + if (sckts[i] == sock) { + sckts[i] = 0; + return 0; + } + } + return -1; + } + + virtual int Listen(SocketInternal* sock, int ch) {//called by Socket_Listen(SOCKET_RFCOM, channel, callback, userData) + int slot = new_slot(ch); + switch (slot) { + case -1: + printf("There is already someone listening on ch %d\n", ch); + return ERR_SOCKET_CANT_LISTEN;//channel is occupied + case -2: + printf("All listener sockets are in use\n"); + return ERR_SOCKET_NONE_LEFT; + } + RFCOMMSocket *rs = (RFCOMMSocket*)sock; + const char dir = 0; + rs->dlci = (ch<<1)|dir; + rs->State = SocketState_Listen; + rs->serdevice = 0;//don't know yet + sckts[slot] = rs->ID; + printf("RFCOMM listener socket %d for ch %d (dlci 0x%02X) is assigned to slot %d\n", rs->ID, ch, rs->dlci, slot); + return rs->ID; + } +/* + virtual int Accept(SocketInternal *sock, int scid, int rxid) { //called indirectly from BTDevice::Control + //sock is registered as an RFCOMM sock but we use it as an L2CAP sock + //sock->type=RFCOM, meaning open/close/send/accept go to RFCOMMManager first + //sock->userData = BTDevice, necessary to make the call back to BTDevice::Accept + //Internal = L2CAPSocket, for scid, dcid + BTDevice *l2cap = (BTDevice*)sock->userData; + //sock->si.dcid = scid + //sock->si.scid = something based on sock->ID + serverSock = sock->ID; + printf("Invoking accept on %p (%s) for sock %d and scid=%d\n", l2cap, l2cap->Name(), sock->ID, scid); + return l2cap->Accept(sock, scid, rxid); //connect 'serverSock' to the remote RFCOMM client + } +*/ + virtual int Send(SocketInternal* sock, const u8* data, int len) { + RFCOMMSocket *s = (RFCOMMSocket*)sock; + return s->serdevice->Send(sock, data, len); + } + + virtual int Close(SocketInternal* sock) { + RFCOMMSocket *s = (RFCOMMSocket*)sock; + return s->serdevice->Close(sock); + } + + virtual int SetOpt(SocketInternal* sock, int so, int* data, int len) { + RFCOMMSocket *s = (RFCOMMSocket*)sock; + return s->serdevice->SetOpt(sock, so, data, len); + } + + virtual int GetOpt(SocketInternal* sock, int so, int* data, int len) { + RFCOMMSocket *s = (RFCOMMSocket*)sock; + return s->serdevice->GetOpt(sock, so, data, len); + } + + virtual char* Name() { + return "RFCOMMManager SocketHandler"; + } + + rfcomm* NewRfCommDevice() {//allocate a new RFCOMM device from the pool + for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) + if (!_devs[i].InUse()) + return _devs+i; + return 0; + } + + rfcomm* FindRfCommDevice(BD_ADDR* ad) {//get a specific RFCOMM device from the pool + for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) + if (_devs[i].InUse() && memcmp(ad, &_devs[i]._addr, 6)==0) + return _devs+i; + return 0; + } + + static void SerServer(int socket, SocketState state, const u8* data, int len, void* userData) { + printfBytes("SerServer: ", data, len); + //userData is the rfcomm + rfcomm::OnRfCommControl(socket, state, data, len, userData); + } + //friend rfcomm; +}; + +int set_remote_port_parameters(int socket, port_settings *p); +extern RFCOMMManager rfcomm_manager; + +#endif