added k60d100m project
[adk-bluetooth-test.git] / adk-stack / btRFCOMM.c
blob24becd7c365b7c9c2a4f813c64c279ff624f0720
1 /*
2 * Copyright (C) 2012 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #define ADK_INTERNAL
17 #include "fwk.h"
18 #include "btRFCOMM.h"
19 #include "BT.h"
20 #include "dbg.h"
21 #include "btL2CAP.h"
22 #include "coop.h"
24 //NOTE: to be good citizens, we really should verify incoming CRC. We have better things to do...sorry...
25 //Plus, they do not provide safety for the data since data is not checksummed.
26 //We are, however, forced to produce good CRCs.
28 #define UGLY_SCARY_DEBUGGING_CODE 0
30 #if (UGLY_SCARY_DEBUGGING_CODE == 1)
31 #define credits_printf(fmt, ...) printf(fmt, ##__VA_ARGS__)
32 #else
33 #define credits_printf(fmt, ...)
34 #endif
36 #define BT_RFCOMM_DLCI_MSK_EA 0x01
37 #define BT_RFCOMM_DLCI_MSK_CR 0x02
38 #define BT_RFCOMM_DLCI_MSK_D 0x04
39 #define BT_RFCOMM_DLCI_SHIFT 2
41 #define BT_SZ_MASK_OVER 0x01
43 #define BT_RFCOMM_CMD_DM 0x0F
44 #define BT_RFCOMM_CMD_SABM 0x3F
45 #define BT_RFCOMM_CMD_DISC 0x53
46 #define BT_RFCOMM_CMD_UA 0x73
47 #define BT_RFCOMM_CMD_UIH 0xEF
48 #define BT_RFCOMM_CMD_UIH_CRED 0xFF
50 //_C = command _R = resp
51 #define BT_RFCOMM_NSC_R 0x11
52 #define BT_RFCOMM_TEST_R 0x21
53 #define BT_RFCOMM_TEST_C 0x23
54 #define BT_RFCOMM_RLS_R 0x51
55 #define BT_RFCOMM_RLS_C 0x53
56 #define BT_RFCOMM_FCOFF_R 0x61
57 #define BT_RFCOMM_FCOFF_C 0x63
58 #define BT_RFCOMM_PN_R 0x81
59 #define BT_RFCOMM_PN_C 0x83
60 #define BT_RFCOMM_RPN_R 0x91
61 #define BT_RFCOMM_RPN_C 0x93
62 #define BT_RFCOMM_FCON_R 0xA1
63 #define BT_RFCOMM_FCON_C 0xA3
64 #define BT_RFCOMM_CLD_C 0xC3
65 #define BT_RFCOMM_MSC_R 0xE1
66 #define BT_RFCOMM_MSC_C 0xE3
69 #define BT_RFCOMM_REMOTE_CREDS 4
70 #define BT_RFCOMM_MAX_CRED_DEBT (BT_RFCOMM_REMOTE_CREDS - 1)
72 typedef struct{
74 uint8_t addr;
75 uint8_t control;
76 uint8_t length; //we do not support 2-byte length
77 uint8_t data[]; //and one byte CRC (FCS)
78 }RfcommPacket;
80 typedef struct{
82 BtRfcommPortOpenF oF;
83 BtRfcommPortCloseF cF;
84 BtRfcommPortRxF rF;
86 }RfcommPort;
88 static RfcommPort gPortHandlers[NUM_DLCIs] = {{0,}, };
90 static uint64_t reserved = 0xC000000000000003; //these are always reserved
92 typedef struct{
94 uint16_t aclConn;
95 uint16_t remChan;
96 struct{
98 sg_buf* queued;
99 uint16_t MTU;
100 uint8_t credits;
101 uint8_t creditsOwed;
102 char on;
104 }ports[NUM_DLCIs];
106 }RfcommInstanceState;
108 extern uint8_t btRfcommFcs(uint8_t *data, uint32_t len);
110 static void btRfcommSend(uint16_t conn, uint16_t remChan, const uint8_t* data, uint16_t sz){
112 int i;
114 #if UGLY_SCARY_DEBUGGING_CODE
115 dbgPrintf("Sending RFCOMM packet:");
116 for(i = 0; i < sz; i++) dbgPrintf(" %02X", data[i]);
117 dbgPrintf("\n\n");
118 #endif
120 sg_buf* buf = sg_alloc();
121 if(!buf) return;
122 if(sg_add_front(buf, data, sz, SG_FLAG_MAKE_A_COPY)){
124 l2capServiceTx(conn, remChan, buf);
125 return;
127 sg_free(buf);
128 free(buf);
131 static void btRfcommTxData(RfcommInstanceState* state, uint8_t dlci, sg_buf* buf){
133 uint8_t data[5] = {(dlci << BT_RFCOMM_DLCI_SHIFT) | BT_RFCOMM_DLCI_MSK_EA, BT_RFCOMM_CMD_UIH};
134 uint32_t dataLen = sg_length(buf);
135 uint8_t hdrLen = 3;
137 if(dataLen >= 128){ //need 2 length bytes
139 data[2] = dataLen << 1;
140 data[3] = dataLen >> 7;
141 hdrLen++;
142 } else data[2] = (dataLen << 1) | 1;
144 if(state->ports[dlci].creditsOwed){ //use the oportunity to send the credits
145 credits_printf("use the oportunity to send the creditsOwed %d\n",state->ports[dlci].creditsOwed);
146 data[1] = BT_RFCOMM_CMD_UIH_CRED;
147 data[hdrLen++] = state->ports[dlci].creditsOwed;
148 state->ports[dlci].creditsOwed = 0;
151 if(sg_add_front(buf, data, hdrLen, SG_FLAG_MAKE_A_COPY)){
153 data[0] = btRfcommFcs(data, 2);
155 if(sg_add_back(buf, data, 1, SG_FLAG_MAKE_A_COPY)){
157 l2capServiceTx(state->aclConn, state->remChan, buf);
158 return;
161 sg_free(buf);
162 free(buf);
165 static void rfcommServiceDataRx(void* service, const uint8_t* req, uint16_t reqSz){
167 RfcommInstanceState* state = service;
168 const uint16_t conn = state->aclConn;
169 const uint16_t remChan = state->remChan;
170 const RfcommPacket* p = (RfcommPacket*)req; //note that we can do this only because packet has no non-8-bit-members
171 const uint8_t* data = p->data;
172 int i;
173 uint8_t DLCI = p->addr >> BT_RFCOMM_DLCI_SHIFT;
174 uint8_t ctrl = p->control;
175 uint16_t len;
176 uint8_t buf[32];
179 if(p->length & 1){
181 len = p->length >> 1;
183 else{
185 len = *data++;
186 len <<= 7;
187 len |= p->length >> 1;
190 if(ctrl == BT_RFCOMM_CMD_SABM || ctrl == BT_RFCOMM_CMD_DISC) {
192 buf[ 0] = p->addr;
193 buf[ 1] = BT_RFCOMM_CMD_UA;
194 buf[ 2] = BT_SZ_MASK_OVER;
195 buf[ 3] = btRfcommFcs(buf, 3);
196 btRfcommSend(conn, remChan, buf, 4);
198 if(state->ports[DLCI].queued){
200 sg_free(state->ports[DLCI].queued);
201 free(state->ports[DLCI].queued);
204 // state->ports[DLCI].creditsOwed = 0;
205 // state->ports[DLCI].credits = 0;
206 state->ports[DLCI].queued = NULL;
207 credits_printf("ctrl %d => DLCI %d,creditsOwed %d, credits %d\n ",ctrl,DLCI,state->ports[DLCI].creditsOwed,state->ports[DLCI].credits);
209 if(ctrl == BT_RFCOMM_CMD_SABM){
211 if(gPortHandlers[DLCI].oF) gPortHandlers[DLCI].oF(state, DLCI);
212 else if(UGLY_SCARY_DEBUGGING_CODE) dbgPrintf("DLCI %2d opened\n", DLCI);
213 state->ports[DLCI].on = 0; //0;
214 dbgPrintf("DLCI %d on = 0 \n",DLCI);
216 else{
218 if(gPortHandlers[DLCI].cF) gPortHandlers[DLCI].cF(state, DLCI);
219 else if(UGLY_SCARY_DEBUGGING_CODE) dbgPrintf("DLCI %2d closed\n", DLCI);
220 state->ports[DLCI].on = 1; // 1;
221 dbgPrintf("DLCI %d on = 1 \n",DLCI);
223 return;
226 #if 0 /* move after ctrl == BT_RFCOMM_CMD_UIH_CRED */
227 if(ctrl == BT_RFCOMM_CMD_UIH && DLCI){ //we got a msg - send back credits if we already owe the limit, else buffer it
229 credits_printf("rx DLCI %d ,BT_RFCOMM_CMD_UIH ,creditsOwed %d will +1\n",DLCI,state->ports[DLCI].creditsOwed);
231 if(++state->ports[DLCI].creditsOwed == BT_RFCOMM_MAX_CRED_DEBT) {
233 buf[ 0] = p->addr;
234 buf[ 1] = BT_RFCOMM_CMD_UIH_CRED;
235 buf[ 2] = BT_SZ_MASK_OVER;
236 buf[ 3] = state->ports[DLCI].creditsOwed + 1;
237 buf[ 4] = btRfcommFcs(buf, 2);
238 btRfcommSend(conn, remChan, buf, 5);
239 credits_printf("rx BT_RFCOMM_CMD_UIH ,then after tx creditsOwed %d + 1, reset creditsOwed to 0\n",state->ports[DLCI].creditsOwed);
241 state->ports[DLCI].creditsOwed = 0;
244 #endif
246 if(ctrl == BT_RFCOMM_CMD_UIH_CRED){
248 credits_printf("rx BT_RFCOMM_CMD_UIH_CRED , state->ports[%d].credits %d + %d , then tx queue data\n",DLCI,state->ports[DLCI].credits,*data);
249 state->ports[DLCI].credits += *data++;
250 ctrl = BT_RFCOMM_CMD_UIH; /* note !!! */
252 if(state->ports[DLCI].queued && state->ports[DLCI].credits){
254 state->ports[DLCI].credits--;
255 credits_printf("btRfcommTxData credits -- = %d\n",state->ports[DLCI].credits);
256 btRfcommTxData(state, DLCI, state->ports[DLCI].queued);
257 state->ports[DLCI].queued = NULL;
261 #if 1
262 if((ctrl == BT_RFCOMM_CMD_UIH || ( (ctrl == BT_RFCOMM_CMD_UIH_CRED) /*&& (len > 0)*/)) && DLCI){ //we got a msg - send back credits if we already owe the limit, else buffer it
264 credits_printf("ctrl %s, DLCI %d rx len=%d ,creditsOwed %d will +1\n",
265 (ctrl == BT_RFCOMM_CMD_UIH) ? "BT_RFCOMM_CMD_UIH" : "BT_RFCOMM_CMD_UIH_CRED" ,DLCI, len, state->ports[DLCI].creditsOwed);
267 if(++state->ports[DLCI].creditsOwed == BT_RFCOMM_MAX_CRED_DEBT) {
269 buf[ 0] = p->addr;
270 buf[ 1] = BT_RFCOMM_CMD_UIH_CRED;
271 buf[ 2] = BT_SZ_MASK_OVER;
272 buf[ 3] = state->ports[DLCI].creditsOwed + 1;
273 buf[ 4] = btRfcommFcs(buf, 2);
274 btRfcommSend(conn, remChan, buf, 5);
275 credits_printf("rx BT_RFCOMM_CMD_UIH ,then after tx creditsOwed %d + 1, reset creditsOwed to 0\n",state->ports[DLCI].creditsOwed);
277 state->ports[DLCI].creditsOwed = 0;
280 #endif
282 if(DLCI == 0){ //control channel transaction
283 if(ctrl == BT_RFCOMM_CMD_UIH){ //data recieved
285 switch(data[0]){
287 case BT_RFCOMM_PN_C:{ //negotiations are for wusses!
289 uint8_t targetDLCI = data[2] & 0x3F;
291 state->ports[targetDLCI].credits = data[9];
292 state->ports[targetDLCI].MTU = (((uint16_t)data[7]) << 8) | data[6];
294 credits_printf("targetDLCI %d, MTU %d ,credits %d\n",targetDLCI,state->ports[targetDLCI].MTU,state->ports[targetDLCI].credits);
296 buf[ 0] = BT_RFCOMM_DLCI_MSK_EA;
297 buf[ 1] = BT_RFCOMM_CMD_UIH;
298 buf[ 2] = BT_SZ_MASK_OVER + (10 << 1);
299 buf[ 3] = BT_RFCOMM_PN_R;
300 buf[ 4] = BT_SZ_MASK_OVER + (8 << 1);
301 buf[ 5] = targetDLCI;
302 buf[ 6] = (data[3] == 0xF0) ? 0xE0 : 0x00; //as per spec
303 buf[ 7] = data[4]; //copy as per spec
304 buf[ 8] = 0; //0 as per spec
305 buf[ 9] = RFCOMM_MTU & 0xFF; //max_packet_size.lo
306 buf[ 10] = RFCOMM_MTU >> 8; //max_packet_size.hi
307 buf[ 11] = 0; //0 retransmissions
308 buf[ 12] = BT_RFCOMM_REMOTE_CREDS; //initial credits
309 buf[ 13] = btRfcommFcs(buf, 2);
310 btRfcommSend(conn, remChan, buf, 14);
311 credits_printf("DLCI 0,rx BT_RFCOMM_CMD_UIH ,BT_RFCOMM_PN_C ,then tx creditsOwed %d ,credits %d\n", BT_RFCOMM_REMOTE_CREDS,state->ports[targetDLCI].credits);
312 break;
315 case BT_RFCOMM_RPN_C: //we need to echo back the negotiation
316 case BT_RFCOMM_MSC_C:{ //we need to echo back the control signals
317 dbgPrintf("response the RPN_C, MSC_C\n");
318 if(len > 127) dbgPrintf("Control packet way too big\n");
319 else{
321 buf[ 0] = BT_RFCOMM_DLCI_MSK_EA;
322 buf[ 1] = BT_RFCOMM_CMD_UIH;
323 buf[ 2] = p->length;
324 buf[ 3] = (data[0] == BT_RFCOMM_MSC_C) ? BT_RFCOMM_MSC_R : /* BT_RFCOMM_RPN_C liutest */ BT_RFCOMM_RPN_R;
325 buf[ 4] = data[1];
326 for(i = 0; i < data[1] >> 1; i++) buf[ 5 + i] = data[2 + i];
327 buf[ 5 + i] = btRfcommFcs(buf, 2);
328 btRfcommSend(conn, remChan, buf, 6 + i);
330 if(data[0] == BT_RFCOMM_MSC_C){
331 //now we send our own signals (coincidentally they are identical ;-)
332 buf[ 3] = BT_RFCOMM_MSC_C;
333 btRfcommSend(conn, remChan, buf, 6 + i);
336 break;
339 case BT_RFCOMM_RPN_R:
340 case BT_RFCOMM_MSC_R:{
342 //nothing to do about this :)
343 break;
346 default:
348 dbgPrintf("Recieved unhandled RFCOMM packet:");
349 for(i = 0; i < reqSz; i++) dbgPrintf(" %02X", req[i]);
350 dbgPrintf("\n\n");
351 break;
355 else if(ctrl == BT_RFCOMM_CMD_UIH){
357 if(len){
359 if(gPortHandlers[DLCI].rF) gPortHandlers[DLCI].rF(state, DLCI, data, len); // btAdkPortRx
360 else if(UGLY_SCARY_DEBUGGING_CODE){
362 dbgPrintf("RFCOMM DLCI %d data:", p->addr >> 2);
363 for(i = 0; i < len; i++) dbgPrintf(" %02X", data[i]);
364 dbgPrintf("\n\n\n");
368 else{
370 dbgPrintf("Recieved unhandled RFCOMM cmd (dlci=%d):", DLCI);
371 for(i = 0; i < reqSz; i++) dbgPrintf(" %02X", req[i]);
372 dbgPrintf("\n\n");
376 static void* rfcommServiceAlloc(uint16_t conn, uint16_t chan, uint16_t remChan){
378 RfcommInstanceState* state = malloc(sizeof(RfcommInstanceState));
379 int i;
381 if(!state) return NULL;
383 state->aclConn = conn;
384 state->remChan = remChan;
386 for(i = 0; i < NUM_DLCIs; i++){
388 state->ports[i].creditsOwed = 0;
389 state->ports[i].credits = 0;
390 state->ports[i].on = 0;
391 state->ports[i].queued = 0;
394 return state;
397 static void rfcommServiceFree(void* service){
399 free(service);
402 void btRfcommRegisterL2capService(){
404 const L2capService rfcom = {L2CAP_FLAG_SUPPORT_CONNECTIONS, rfcommServiceAlloc, rfcommServiceFree, rfcommServiceDataRx};
405 if(!l2capServiceRegister(L2CAP_PSM_RFCOMM, &rfcom)) dbgPrintf("SDP L2CAP registration failed\n");
408 void btRfcommUnregisterL2capService(char sendDiscPacket){
409 if(!l2capServiceUnregister(L2CAP_PSM_RFCOMM,sendDiscPacket)) dbgPrintf("SDP L2CAP registration failed\n");
412 void btRfcommRegisterPort(uint8_t dlci, BtRfcommPortOpenF oF, BtRfcommPortCloseF cF, BtRfcommPortRxF rF){
414 if(dlci >= NUM_DLCIs) return; //no such DLCI;
416 gPortHandlers[dlci].oF = oF;
417 gPortHandlers[dlci].cF = cF;
418 gPortHandlers[dlci].rF = rF;
421 void btRfcommPortTx(void* port, uint8_t dlci, const uint8_t* data, uint16_t size){
423 RfcommInstanceState* state = port;
425 if(dlci >= NUM_DLCIs || dlci == 0) return; //cannot send there, buddy...
427 sg_buf* buf = sg_alloc();
428 if(!buf) return;
430 if(!sg_add_front(buf, data, size, SG_FLAG_MAKE_A_COPY)){
432 sg_free(buf);
433 free(buf);
435 else{
436 credits_printf("api tx dlci %d, credits %d\n",dlci,state->ports[dlci].credits);
437 if(state->ports[dlci].credits){ //send immediately
439 state->ports[dlci].credits--;
440 credits_printf("api btRfcommPortTx credits -- %d\n",state->ports[dlci].credits);
441 btRfcommTxData(state, dlci, buf);
443 else{ //enqueue it
444 credits_printf("no remot credits queue+\n");
445 if(state->ports[dlci].queued){
446 // do this in one task ,make no sence!
447 //while(state->ports[dlci].queued && state->ports[dlci].on) coopYield();
448 //if(!state->ports[dlci].on)
450 credits_printf("no remote credits then queued ,but closed ,return\n");
451 sg_free(buf);
452 free(buf);
453 return;} //port closed - packet dropped
455 state->ports[dlci].queued = buf;
456 credits_printf("no remot credits queue -\n");
461 #define RFCOMM_DLCI_PREFERENCE_NONE 0x80 //use this param to the below
462 #define RFCOMM_DLCI_NEED_EVEN 0x81
463 #define RFCOMM_DLCI_NEED_ODD 0x82
465 uint8_t btRfcommReserveDlci(uint8_t preference){
467 uint8_t start = 0, end = 64, step = 2;
469 if(preference == RFCOMM_DLCI_PREFERENCE_NONE) step = 1;
470 else if(preference == RFCOMM_DLCI_NEED_EVEN);
471 else if(preference == RFCOMM_DLCI_NEED_ODD) start++;
472 else{
474 start = preference;
475 end = preference + 1;
476 step = 1;
479 while(start < end && (reserved & (1ULL << ((uint64_t)start)))) start += step;
481 if(start >= end) return 0; //we failed
483 reserved |= (1ULL << ((uint64_t)start));
485 return start;
488 void btRfcommReleaseDlci(uint8_t dlci){
490 reserved &=~ (1ULL << ((uint64_t)dlci));
517 static const uint8_t crctab[256] = {
518 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75,
519 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
520 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69,
521 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
522 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D,
523 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
524 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51,
525 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
526 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05,
527 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
528 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19,
529 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
530 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D,
531 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
532 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21,
533 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
534 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95,
535 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
536 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89,
537 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
538 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD,
539 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
540 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1,
541 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
542 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5,
543 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
544 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9,
545 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
546 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD,
547 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
548 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1,
549 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
552 uint8_t btRfcommFcs(uint8_t *data, uint32_t len){ //calculate fcs value for RFCOMM
554 uint32_t i;
555 uint8_t crcval = 0xFF;
557 for (i = 0; i < len; i++) crcval = crctab[crcval ^ (*data++)];
559 return 0xFF - crcval;