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 RFCOMM.cpp Source File

RFCOMM.cpp

00001 #include "mbed.h"
00002 #include "Utils.h"
00003 #include "RFCOMM.h"
00004 
00005 // Control field values      bit no.       1 2 3 4 5   6 7 8
00006 #define BT_RFCOMM_SABM       0x3F       // 1 1 1 1 P/F 1 0 0
00007 #define BT_RFCOMM_UA         0x73       // 1 1 0 0 P/F 1 1 0
00008 #define BT_RFCOMM_DM         0x0F       // 1 1 1 1 P/F 0 0 0
00009 #define BT_RFCOMM_DM_PF      0x1F
00010 #define BT_RFCOMM_DISC       0x53       // 1 1 0 0 P/F 0 1 0
00011 #define BT_RFCOMM_UIH        0xEF       // 1 1 1 1 P/F 1 1 1
00012 #define BT_RFCOMM_UIH_PF     0xFF
00013 
00014 // Multiplexer message types
00015 #define BT_RFCOMM_PN_CMD     0x83
00016 #define BT_RFCOMM_PN_RSP     0x81
00017 #define BT_RFCOMM_TEST_CMD   0x23
00018 #define BT_RFCOMM_TEST_RSP   0x21
00019 #define BT_RFCOMM_FCON_CMD   0xA3
00020 #define BT_RFCOMM_FCON_RSP   0xA1
00021 #define BT_RFCOMM_FCOFF_CMD  0x63
00022 #define BT_RFCOMM_FCOFF_RSP  0x61
00023 #define BT_RFCOMM_MSC_CMD    0xE3
00024 #define BT_RFCOMM_MSC_RSP    0xE1
00025 #define BT_RFCOMM_RPN_CMD    0x93
00026 #define BT_RFCOMM_RPN_RSP    0x91
00027 #define BT_RFCOMM_RLS_CMD    0x53
00028 #define BT_RFCOMM_RLS_RSP    0x51
00029 #define BT_RFCOMM_NSC_RSP    0x11
00030 
00031 // FCS calc
00032 #define BT_RFCOMM_CODE_WORD         0xE0 // pol = x8+x2+x1+1
00033 #define BT_RFCOMM_CRC_CHECK_LEN     3
00034 #define BT_RFCOMM_UIHCRC_CHECK_LEN  2
00035 
00036 #define NR_CREDITS  1
00037 #define INITIAL_CREDITS 1 //0...7
00038 
00039 #define DCD (1<<7) //DV data carrier detect
00040 #define RI  (1<<6) //IC ring indicator
00041 #define RTS (1<<3) //RTR request to send
00042 #define DSR (1<<2) //RTC data set ready
00043 #define FC  (1<<1) //Flow Control
00044 #define EA  (1<<0) //extended address (always 1)
00045 #define SIGNALS (DCD | RTS | DSR | EA)
00046 
00047 #define DEBUG   1
00048 #define TAKE_INITIATIVE
00049 
00050 RFCOMMManager rfcomm_manager;
00051 
00052 //uint8_t rfcomm_out_buffer[1000];//seems a bit big as default max framesize is 127
00053 //unsigned rfcomm::maxframesize = MAX_FRAME_SIZE; //only initial value
00054 
00055 //these functions are obtained from rfcomm.c on google code
00056 void _bt_rfcomm_send_sabm(unsigned short source_cid, unsigned char initiator, unsigned char channel);
00057 void _bt_rfcomm_send_uih_pn_command(unsigned short source_cid, unsigned char initiator, unsigned char channel, unsigned short max_frame_size);
00058 void _bt_rfcomm_send_uih_msc_cmd(unsigned short source_cid, unsigned char initiator, unsigned char channel, unsigned char signals);
00059 void _bt_rfcomm_send_uih_rpn_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, port_settings *val);
00060 int rfcomm_send_packet(unsigned short source_cid, unsigned char address, unsigned char control, unsigned char credits, const unsigned char *data, unsigned short len);
00061 uint8_t crc8_calc(uint8_t *data, uint16_t len);
00062 
00063 
00064 //find a free socket slot for channel ch
00065 int rfcomm::find_slot(unsigned ch) {
00066     for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
00067         if (sckts[i] != 0) { //socket is in use
00068             RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
00069             if (s==0) {
00070                 printf("find_slot: socket  %d not found\n", sckts[i]);
00071                 continue;
00072             }
00073             if (s->dlci >> 1 == ch) {
00074                 printf("Channel %d is already in use on socket %d\n", ch, sckts[i]);
00075                 return -1;
00076             }
00077         } else //slot is free
00078             return i;
00079     }
00080     return -2; //no free slots
00081 }
00082 
00083 //find the rfcomm socket for dlci
00084 RFCOMMSocket* rfcomm::find_socket(unsigned dlci) {
00085     for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
00086         if (sckts[i] != 0) { //socket is in use
00087             RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
00088             if (s==0) {
00089                 printf("find_socket: socket  %d not found\n", sckts[i]);
00090                 continue;
00091             }
00092             if (s->dlci == dlci) {
00093                 return s;
00094             }
00095         }
00096     }
00097     printf("RFCOMMSocket for dlci %d was not found!\n", dlci);
00098     return 0; //socket not found
00099 }
00100 
00101 //send a PN command to all sockets waiting to be opened
00102 void rfcomm::initChannels(int socket) {
00103     for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
00104         if (sckts[i] != 0) { //socket is in use
00105             RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
00106             if (s==0) {
00107                 printf("initChannels: socket  %d not found\n", sckts[i]);
00108                 continue;
00109             }
00110             if (s->State == SocketState_Opening) {
00111                 printf("Sending PN for DLCI %d on socket %d\n", s->dlci, sckts[i]);
00112                 _bt_rfcomm_send_uih_pn_command(socket, 1, s->dlci, maxframesize);
00113                 s->State = SocketState_L2CAP_Config_wait;
00114             }
00115         }
00116     }
00117 }
00118 
00119 unsigned rfcomm::release_channel(unsigned dlci) {
00120     int n = 0;
00121     for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
00122         if (sckts[i] != 0) { //socket is in use
00123             RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
00124             if (s==0) {
00125                 printf("Release: socket for dlci %d not found\n", dlci);
00126                 continue;
00127             }
00128             if (s->dlci == dlci)
00129                 sckts[i] = 0;
00130             else
00131                 n++;
00132         }
00133     }
00134     return n;
00135 }
00136 
00137 int rfcomm::Send(SocketInternal *sock, const u8* data, int len) {//also see if credits need to be send
00138     RFCOMMSocket *s = (RFCOMMSocket*)sock;
00139     char credits = 0;
00140     char control = BT_RFCOMM_UIH;
00141     if (len + 14 > maxframesize) //hci/l2cap header =8, rfcomm header ~ 6
00142         printf("Error! packetsize = %d, maxframesize = %d\n", len, maxframesize);
00143     if (s->peer_credits == 0) {//peer is low on credits
00144         credits = NR_CREDITS;
00145         control = BT_RFCOMM_UIH_PF;
00146         s->peer_credits += NR_CREDITS;//so provide some more
00147     }
00148     unsigned char address = (1 << 0) | (initiator << 1) | (s->dlci << 2);
00149     if (s->my_credits) {
00150         s->my_credits--;
00151         return rfcomm_send_packet(_l2cap, address, control, credits, data, len);
00152     } else
00153         return rfcomm_send_packet(_l2cap, address, control, credits, data, 0);//send an empty packet when credits run out
00154 }
00155 
00156 int rfcomm::Close(SocketInternal* sock) {
00157     RFCOMMSocket *s = (RFCOMMSocket*)sock;
00158     int id = s->dlci;
00159     printf("Closing rfcomm dlci %d state=%d\n", id, s->State);
00160     Disconnect(s);
00161     int n = release_channel(id);
00162     printf("%d channels are still open\n", n);
00163     if (n == 0) {//all rfcomm channels are closed
00164         printf("....L2CAP must be closed as well\n");
00165         rfcomm_send_packet(_l2cap, (1 << 0) | (initiator << 1), BT_RFCOMM_DISC, 0, 0, 0); //close dlci0
00166         Socket_Close(_l2cap);
00167         _l2cap = 0; //return rfcomm to the pool
00168     }
00169     return 0;
00170 }
00171 
00172 int rfcomm::SetOpt(SocketInternal *sock, int so, int* data, int len) {
00173   switch (so) {
00174     case SO_RECBUF:
00175     case SO_SNDBUF:
00176        maxframesize = *data; //pointless because setting takes effect only before socket is opened (before PN)
00177        break;
00178     default: return NOPROTOOPT;
00179   }
00180   return 0;
00181 }
00182 
00183 int rfcomm::GetOpt(SocketInternal *sock, int so, int* data, int len) {
00184   switch (so) {
00185     case SO_RECBUF:
00186     case SO_SNDBUF:
00187          if (len >= sizeof(int))
00188            *data = maxframesize;
00189          break;
00190     default: return NOPROTOOPT;
00191   }
00192   return 0;
00193 }
00194 
00195 int rfcomm::Disconnect(RFCOMMSocket *s) {
00196     unsigned char address = (1 << 0) | (initiator << 1) | (s->dlci << 2);
00197     return rfcomm_send_packet(_l2cap, address, BT_RFCOMM_DISC, 0, 0, 0);
00198 }
00199 
00200 //expect this to be called with socket type=SOCKET_RFCOM and addr->psm = channel and addr->bdaddr is the BT addr
00201 //of the device to connect to.
00202 //eg. Socket_Open(SOCKET_RFCOM, rfcommaddr(bdaddr, chan), receiver_func, appl_obj);
00203 int rfcomm::Open(SocketInternal* sock, SocketAddrHdr* addr) {
00204     int ch = ((L2CAPAddr*)addr)->psm;//abused psm for channel ID
00205     RFCOMMSocket *s = (RFCOMMSocket*)sock;
00206     int slot = find_slot(ch);
00207     if (slot < 0) return 0;
00208     sckts[slot] = s->ID;
00209     s->serdevice = this;
00210     s->State = SocketState_Opening;
00211 
00212     if (_l2cap == 0) { //no rfcomm -> l2cap connection yet
00213         printf("Need to open L2CAP channel first before opening RFCOMM channel %d\n", s->dlci);
00214         ((L2CAPAddr*)addr)->psm = L2CAP_PSM_RFCOMM;//open the l2cap channel and the rfcomm_ch channel
00215         initiator = 1;
00216         s->dlci = (ch<<1)|!initiator; 
00217         _l2cap = Socket_Open(SOCKET_L2CAP, addr, OnRfCommControl, this);//this is the socket between the RFCOMM and the L2CAP layer
00218         if (_l2cap)
00219             printf("Successfully opened L2CAP channel on socket %d\n", _l2cap);
00220         else {
00221             printf("Opening L2CAP channel failed\n");
00222             sckts[slot] = 0;
00223             s->State = SocketState_Closed;
00224             return 0;
00225         }
00226     } else {//bypass the l2cap channel creation
00227         s->dlci = (ch<<1)|!initiator; 
00228         _bt_rfcomm_send_uih_pn_command(_l2cap, initiator, s->dlci, maxframesize);
00229         s->State = SocketState_L2CAP_Config_wait;
00230     }
00231     return s->ID; //return the application unique socket nr.
00232 }
00233 
00234 int rfcomm::set_remote_port_parameters(unsigned char dlci, port_settings *p) {
00235     _bt_rfcomm_send_uih_rpn_cmd(_l2cap, initiator, dlci, p);
00236     return 0;
00237 }
00238 
00239 //socket is an L2CAP socket and state is the state of the L2CAP socket, not the RFCOMM socket
00240 void rfcomm::OnRfCommControl(int socket, SocketState state, const u8* data, int len, void* userData) {
00241     int packet_processed = 0;
00242     rfcomm* self = (rfcomm*)userData;
00243     const u8 initiator = self->initiator;
00244     printf("\x1B[%dm", 32); //debug: set a different colour
00245     printf("OnRfCommControl sock = %d, state = %d, length = %d\n", socket, state, len);
00246 
00247     if (len == 0) {//client only
00248         if (state==SocketState_Open) {//callback after change to 'open', the rfcomm->l2cap channel is now open
00249             _bt_rfcomm_send_sabm(socket, initiator, 0); //setup the rfcomm control channel dlci==0
00250             return;
00251         }
00252         return; //or other states to handle, e.g. Closing or Closed
00253     }
00254     //we have data, so parse the header
00255     const u8 &addr = data[0];
00256     u8 dlci = addr>>2;
00257     const u8 &control = data[1];
00258     u16 length = data[2]>>1;
00259     const u8 *payload = data+3;
00260     const u8 *pFCS = data+len-1; //expected position of the CRC
00261     if (!(data[2]&1)) { //two byte length
00262         length += ((unsigned)data[3])<<7;
00263         payload++;
00264     }
00265     u8 credits = 0;
00266     if (control == BT_RFCOMM_UIH_PF)//this packet carries credits
00267         credits = *(payload++);
00268     //sanity check
00269     if (payload+length != pFCS)
00270         printf("RFCOMM size mismatch, expected %d payload bytes, got %d\n", length, pFCS-payload);
00271 
00272     if (DEBUG) {
00273         printf("RFCOMM: EA=%d, C/R=%d, D=%d, ch=%d; control=%02X (P/F=%d); length=%d\n", addr&1, (addr>>1)&1, (addr>>2)&1, (addr>>3), control, (control>>4)&1, length);
00274         printfBytes("payload:", payload, length);
00275     }
00276     if (dlci == 0) { //dlci==0 control channel
00277         L2CAPSocket *s = (L2CAPSocket*)GetSocketInternal(socket);
00278         switch (control) {
00279             case BT_RFCOMM_UA://     received 1. message BT_RF_COMM_UA
00280                 packet_processed++;
00281                 if (s->si.State == SocketState_Closing || s->si.State==SocketState_L2CAP_WaitDisconnect) { //Confirmation of disconnect
00282                     printf("Remote side confirmed disconnect for socket %d\n", s->si.ID);
00283                     s->si.SetState(SocketState_Closed);
00284                     break;
00285                 }
00286                 printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
00287                 printf("Sending UIH Parameter Negotiation Command from OnRfCommControl\n");
00288                 self->initChannels(socket);
00289                 break;
00290             case BT_RFCOMM_UIH://  received UIH Parameter Negotiation Response
00291                 switch (payload[0]) {
00292                     case BT_RFCOMM_PN_RSP: {//client
00293                         packet_processed++;
00294                         printf("UIH Parameter Negotiation Response\n");
00295                         printf("Sending SABM #%u\n", payload[2]);
00296                         _bt_rfcomm_send_sabm(socket, initiator, payload[2]);//was rfcomm_ch
00297                         RFCOMMSocket *r = self->find_socket(payload[2]);
00298                         if (r==0) break;
00299                         r->my_credits = payload[9]; //initial amount of credits
00300                         self->maxframesize = min(self->maxframesize, payload[6] + (payload[7]<<8));
00301                         printf("Max Frame Size = %d, got %d initial credits\n", self->maxframesize, payload[9]);
00302                     }
00303                     break;
00304                     case BT_RFCOMM_PN_CMD: { //remote side sent PN command, mtu and initial credits
00305                         packet_processed++;
00306                         printf("UIH Parameter Negotiation Indication\n");
00307                         self->maxframesize = min(self->maxframesize, payload[6] + (payload[7]<<8));
00308                         unsigned char cred = payload[9] & 7;
00309                         unsigned char _dlci = payload[2];
00310 
00311                         int skt = rfcomm_manager.find_socket(_dlci>>1);
00312                         if (skt == 0) { //No-one is listening
00313                             printf("No-one is Listening on channel %d\n", _dlci>>1);
00314                             rfcomm_send_packet(socket, (_dlci<<2)|1, BT_RFCOMM_DM, 0, 0, 0);
00315                             break;
00316                         }
00317                         RFCOMMSocket *r = (RFCOMMSocket*)GetSocketInternal(skt);
00318                         r->my_credits = cred;
00319                         r->peer_credits = INITIAL_CREDITS;
00320                         unsigned char reply[10];
00321                         memcpy(reply, payload, sizeof(reply));
00322                         reply[0] = BT_RFCOMM_PN_RSP;//[1]=len, [2]=dlci, [4]=priority, [5]=timer(must be 0), [8] retransmissions (must be 0)
00323                         reply[3] = payload[3]==0xF0 ? 0xE0 : 0; //support credit based flow control
00324                         reply[6] = self->maxframesize;
00325                         reply[7] = self->maxframesize>>8;
00326                         reply[9] = payload[3]==0xF0 ? r->peer_credits : 0;
00327                         printf("Max Frame Size = %d, give %d initial credits\n", self->maxframesize, reply[9]);
00328                         rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, sizeof(reply));
00329                     }
00330                     break;
00331                     case BT_RFCOMM_MSC_CMD:
00332                         packet_processed++;
00333                         {
00334                             printf("Received BT_RFCOMM_MSC_IND\n");
00335                             // fine with this, return the same status and ignore the value, there is no room in the socket to store the value, rfcomm could generate an event
00336                             RFCOMMSocket *r = self->find_socket(payload[2]>>2);
00337                             if (r==0) break;
00338                             unsigned char reply[5];
00339                             memcpy(reply, payload, 5); //keep length, dlci and value(s)
00340                             reply[0]  = BT_RFCOMM_MSC_RSP;  // change command into response
00341                             printf("Sending MSC_RSP (%d bytes)\n", length);
00342                             rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, (payload[1]>>1)+2); // reply is 4 or 5 bytes
00343                             switch (r->State) {
00344                                 case SocketState_L2CAP_Config_wait:
00345                                     r->State = SocketState_L2CAP_Config_wait_send;
00346                                     printf("Sending MSC_CMD\n");
00347                                     _bt_rfcomm_send_uih_msc_cmd(socket, initiator, payload[2]>>2, SIGNALS);  // ea=1,fc=0,rtc(DSR/DTR)=1,rtr(RTS/CTs)=1,ic(RI)=0,dv(DCD)=1
00348                                     r->State = SocketState_L2CAP_Config_wait_rsp;
00349                                     break;
00350                                 case SocketState_L2CAP_Config_wait_reqrsp:
00351                                     r->State = SocketState_L2CAP_Config_wait_rsp;
00352                                     break;
00353                                 case SocketState_L2CAP_Config_wait_req:
00354                                     r->SetState(SocketState_Open);
00355                                     break;
00356                                 case SocketState_Open:
00357                                     //inform port adaptation layer
00358                                     printf("Received MSC IND in state Open for dlci 0x%02x\n", payload[2]>>2);
00359                                     break;
00360                                 default:
00361                                     printf("Received MSC IND in state %d for dlci 0x%02x\n", r->State, payload[2]>>2);
00362                             }
00363                         }
00364                         break;
00365                     case BT_RFCOMM_MSC_RSP:
00366                         packet_processed++;
00367                         {
00368                             RFCOMMSocket *r = self->find_socket(payload[2]>>2);
00369                             if (r==0) break;
00370                             if (r->State == SocketState_L2CAP_Config_wait_reqrsp)
00371                                 r->State =  SocketState_L2CAP_Config_wait_req;
00372                             else if (r->State == SocketState_L2CAP_Config_wait_rsp)
00373                                 r->SetState(SocketState_Open);
00374                             else
00375                                 printf("Received MSC confirmation in state %d for dlci 0x%02x\n", r->State, payload[2]>>2);
00376                         }
00377                         break;
00378                     case BT_RFCOMM_RPN_CMD:
00379                         packet_processed++;
00380                         //accept and ignore all settings
00381                         unsigned char reply[10];
00382                         memcpy(reply, payload, length); //keep length, dlci and value(s)
00383                         reply[0]  = BT_RFCOMM_RPN_RSP;  // change command into response
00384                         printf("Responding to RPN indication (%d bytes)\n", length);
00385                         rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, length);
00386                         break;
00387                     case BT_RFCOMM_RPN_RSP:
00388                         packet_processed++;
00389                         //ignore a response
00390                         printf("Received RPN confirmation\n");
00391                         break;
00392                     default:
00393                         printf("Unsupported multiplexer frame, type=%02XH\n", data[3]);
00394                 }
00395                 break;
00396             case BT_RFCOMM_DISC:
00397                 printf("Remote site actively disconnected from DLCI0\n");
00398                 rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm disconnection
00399                 //intentional fall through
00400             case BT_RFCOMM_DM:
00401                 packet_processed++;
00402                 printf("Remote side refused connection on DLCI0\n");
00403                 self->_l2cap = Socket_Close(socket);
00404                 break;
00405             case BT_RFCOMM_SABM:
00406                 packet_processed++;
00407                 printf("Remote site is seeking connection on DLCI0\n"); //respond with UA
00408                 rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm connection
00409                 break;
00410             default:
00411                 printf("Unexpected RFCOMM cmd %02XH for address %02XH, length=%d\n", control, addr, length);
00412         }
00413     } else { //data is for one of the serial sockets
00414         RFCOMMSocket *s = 0;
00415         if (control == BT_RFCOMM_SABM) { //req. for conn on this dlci
00416             //cannot call self->rfcomm::find_socket because it has no socket yet
00417             int skt = rfcomm_manager.find_socket(dlci>>1); //find the server socket
00418             s = (RFCOMMSocket*)GetSocketInternal(skt);//the listening socket
00419             if (s) {//move the listening socket to the appropriate rfcomm
00420                 int slot = self->find_slot(dlci>>1);
00421                 if (slot < 0) {
00422                     printf("RFCOMM Channel %d is not free on rfcomm with l2cap socket %d\n", dlci>>1, self->_l2cap);
00423                     return;
00424                 }
00425                 s->serdevice = self; //bind the socket to this refcomm entity
00426                 self->sckts[slot] = skt;
00427                 rfcomm_manager.remove_socket(skt);
00428             } else {
00429                 printf("Couln't find a listening socket for dlci %d\n", dlci);
00430                 return;
00431             }
00432         } else
00433             s = self->find_socket(dlci);
00434         if (s==0){
00435           printf("DLCI %d not found\n", dlci);
00436           return;
00437         }
00438         switch (control) {
00439             case BT_RFCOMM_SABM:
00440                 packet_processed++;
00441                 rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm connection
00442                 s->State = SocketState_L2CAP_Config_wait; //wait for msc cmd
00443 #ifdef TAKE_INITIATIVE
00444                   printf("Sending MSC_CMD\n");
00445                   _bt_rfcomm_send_uih_msc_cmd(socket, initiator, dlci, 0x8d);  // ea=1,fc=0,rtc(DSR/DTR)=1,rtr(RTS/CTs)=1,ic(RI)=0,dv(DCD)=1
00446                   s->State = SocketState_L2CAP_Config_wait_reqrsp;
00447 #endif
00448                 break;
00449             case BT_RFCOMM_UA://     received 2. message BT_RF_COMM_UA
00450                 packet_processed++;
00451                 if (s->State == SocketState_Closing) { //Confirmation of disconnect
00452                     printf("Remote side confirmed disconnect for socket %d\n", s->ID);
00453                     s->SetState(SocketState_Closed);
00454                     break;
00455                 }
00456                 printf("Received RFCOMM unnumbered acknowledgement for dlci %u - channel opened\n", dlci);
00457                 if (s->State == SocketState_L2CAP_Config_wait) {
00458                     printf("Sending MSC  CMD\n");
00459                     _bt_rfcomm_send_uih_msc_cmd(socket, initiator, dlci, 0x8d);  // ea=1,fc=0,rtc(DSR/DTR)=1,rtr(RTS/CTs)=1,ic(RI)=0,dv(DCD)=1
00460                     s->State = SocketState_L2CAP_Config_wait_reqrsp;
00461                 }
00462                 break;
00463             case BT_RFCOMM_UIH_PF: //user data with credits
00464                 printf("Got %u credits\n", credits);
00465                 s->my_credits += credits;
00466                 //intentional fall-through
00467             case BT_RFCOMM_UIH: //user data
00468                 packet_processed++;
00469                 if (DEBUG) {
00470                     printf("RX: address %02x, control %02x: ", addr, control);
00471                     printHex( payload, length);
00472                 }
00473                 if (length) {
00474                     s->peer_credits--;
00475                     s->Recv(payload, length);
00476                 } else
00477                     printf("Received empty packet\n");
00478                 if (length == 0 || s->peer_credits == 0) {//send credits when peer runs out
00479                     //char ini = !(dlci & 1);
00480                     unsigned char address = (1 << 0) | (initiator << 1) | (dlci << 2);
00481                     printf("send %d credits to dlci %d\n", NR_CREDITS, addr>>2);
00482                     rfcomm_send_packet(socket, address, BT_RFCOMM_UIH_PF, NR_CREDITS, NULL, 0);
00483                     s->peer_credits += NR_CREDITS;
00484                 }
00485                 break;
00486             case BT_RFCOMM_DISC:
00487                 packet_processed++;
00488                 printf("Received DISC IND for dlci %d\n", dlci);
00489                 rfcomm_send_packet(socket, addr, BT_RFCOMM_UA, 0, 0, 0);//confirm disconnection
00490                 s->SetState(SocketState_Closed);                
00491                 break;
00492             case BT_RFCOMM_DM:
00493             case BT_RFCOMM_DM_PF:
00494                 packet_processed++;
00495                 printf("Received DM IND (%02X) for dlci %d\n", control, dlci);
00496                 s->SetState(SocketState_Closed);
00497                 break;
00498             default:
00499                 printf("Unexpected RFCOMM cmd %02XH for address %02XH, length=%d\n", control, addr, length);
00500         }
00501     }
00502 
00503     if (!packet_processed) {
00504         // just dump data for now
00505         printf("??: address %02x, control %02x: ", data[0], data[1]);
00506         printHex( data, len );
00507     }
00508     printf("\x1B[%dm", 0);//reset terminal colour
00509 }
00510 
00511 //should make the functions below member functions
00512 
00513 /**
00514  * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
00515  */
00516 /* Questionable optimisation. When OFFSET==8 a buffer is (dynamically) allocated that provides space for the lower
00517    layer headers, this reduces copying to, and allocation of, a lower layer buffer. However, all other layers using
00518    HCI/L2CAP must do the same.
00519 */
00520 #define OFFSET  8
00521 
00522 int rfcomm_send_packet(uint16_t source_cid, uint8_t address, uint8_t control, uint8_t credits, const uint8_t *data, uint16_t len) {
00523 
00524     uint16_t pos = OFFSET;
00525     uint8_t crc_fields = 3;
00526 
00527 #if OFFSET == 8
00528     uint8_t* rfcomm_out_buffer = new uint8_t[OFFSET+len+6];
00529 #else
00530     static uint8_t rfcomm_out_buffer[MAXFRAMESIZE+6];//seems a bit big as default max framesize is 127
00531 #endif
00532     rfcomm_out_buffer[pos++] = address;
00533     rfcomm_out_buffer[pos++] = control;
00534 
00535     // length field can be 1 or 2 octets
00536     if (len < 128) {
00537         rfcomm_out_buffer[pos++] = (len << 1)| 1;     // bits 0-6
00538     } else {
00539         rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
00540         rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
00541         crc_fields++;
00542     }
00543 
00544     // add credits for UIH frames when PF bit is set
00545     if (control == BT_RFCOMM_UIH_PF) {
00546         rfcomm_out_buffer[pos++] = credits;
00547     }
00548 
00549     // copy actual data
00550     memcpy(&rfcomm_out_buffer[pos], data, len);
00551     pos += len;
00552 
00553     // UIH frames only calc FCS over address + control (5.1.1)
00554     if ((control & 0xef) == BT_RFCOMM_UIH) {
00555         crc_fields = 2;
00556     }
00557     rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer+OFFSET, crc_fields); // calc fcs
00558     int retval = Socket_Send( source_cid, rfcomm_out_buffer, pos);
00559 #if OFFSET == 8
00560     delete[] rfcomm_out_buffer;
00561 #endif
00562     if (retval <= 0)
00563         return retval;
00564     return len;//return the size of the payload
00565 }
00566 
00567 void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t dlci) {
00568     uint8_t address = (1 << 0) | (initiator << 1) |  (dlci << 2);
00569     rfcomm_send_packet(source_cid, address, BT_RFCOMM_SABM, 0, NULL, 0);
00570 }
00571 
00572 void _bt_rfcomm_send_uih_pn_command(uint16_t source_cid, uint8_t initiator, uint8_t dlci, uint16_t max_frame_size) {
00573     uint8_t payload[10];
00574     uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
00575     uint8_t pos = 0;
00576     payload[pos++] = BT_RFCOMM_PN_CMD;
00577     payload[pos++] = 8 << 1 | 1;  // len
00578     payload[pos++] = dlci;
00579     payload[pos++] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
00580     payload[pos++] = 0; // priority
00581     payload[pos++] = 0; // max 60 seconds ack
00582     payload[pos++] = max_frame_size & 0xff; // max framesize low
00583     payload[pos++] = max_frame_size >> 8;   // max framesize high
00584     payload[pos++] = 0x00; // number of retransmissions
00585     payload[pos++] = INITIAL_CREDITS; // unused error recovery window
00586     rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
00587 }
00588 
00589 void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
00590     uint8_t address = (1 << 0) | (initiator << 1) |  (!initiator << 2) | (channel << 3);
00591     rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, data, len);
00592 }
00593 
00594 void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, uint8_t signals) {
00595     uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
00596     uint8_t payload[5];
00597     uint8_t pos = 0;
00598     payload[pos++] = BT_RFCOMM_MSC_CMD;
00599     payload[pos++] = 2 << 1 | 1;  // len, should be adapted when adding break byte
00600     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); //C/R is always 1
00601     payload[pos++] = signals;
00602     // payload[pos++]   = brk;
00603     rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
00604 }
00605 
00606 void _bt_rfcomm_send_uih_rpn_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, port_settings *val) {
00607     uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
00608     uint8_t payload[sizeof(port_settings)+3];
00609     uint8_t pos = 0;
00610     payload[pos++] = BT_RFCOMM_RPN_CMD;//type
00611     if (val) {
00612         payload[pos++] = ((1+sizeof(port_settings)) << 1) | 1;  // len
00613         payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2);
00614         memcpy(payload+pos, (char*)val, sizeof(port_settings));
00615         pos += sizeof(port_settings);
00616     } else {
00617         payload[pos++] = (1 << 1) | 1;  // len
00618         payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2);
00619     }
00620     rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
00621 }
00622 
00623 int set_remote_port_parameters(int socket, port_settings *p) {
00624     RFCOMMSocket* si = (RFCOMMSocket*)GetSocketInternal(socket);//gets the RFCOMM socket
00625     if (!si || si->ID != socket)
00626         return ERR_SOCKET_NOT_FOUND;
00627     return si->serdevice->set_remote_port_parameters(si->dlci, p);
00628 }
00629 
00630 
00631 /*
00632  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
00633  */
00634 static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
00635     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
00636     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
00637     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
00638     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
00639     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
00640     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
00641     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
00642     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
00643     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
00644     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
00645     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
00646     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
00647     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
00648     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
00649     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
00650     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
00651 };
00652 
00653 #define CRC8_INIT  0xFF          // Initial FCS value 
00654 #define CRC8_OK    0xCF          // Good final FCS value 
00655 /*-----------------------------------------------------------------------------------*/
00656 uint8_t crc8(uint8_t *data, uint16_t len) {
00657     uint16_t count;
00658     uint8_t crc = CRC8_INIT;
00659     for (count = 0; count < len; count++)
00660         crc = crc8table[crc ^ data[count]];
00661     return crc;
00662 }
00663 
00664 /*-----------------------------------------------------------------------------------*/
00665 uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum) {
00666     uint8_t crc;
00667 
00668     crc = crc8(data, len);
00669 
00670     crc = crc8table[crc ^ check_sum];
00671     if (crc == CRC8_OK)
00672         return 0;               /* Valid */
00673     else
00674         return 1;               /* Failed */
00675 
00676 }
00677 
00678 /*-----------------------------------------------------------------------------------*/
00679 uint8_t crc8_calc(uint8_t *data, uint16_t len) {
00680     /* Ones complement */
00681     return 0xFF - crc8(data, len);
00682 }