BluetoothRFCOMM.Mod 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. MODULE BluetoothRFCOMM;
  2. IMPORT
  3. S := SYSTEM,
  4. BluetoothL2CAP,
  5. Bluetooth,
  6. Streams,
  7. KernelLog;
  8. CONST
  9. ModuleName = "[BTRFCOMM]";
  10. TraceBuffer = FALSE;
  11. TraceChannel = FALSE;
  12. TraceControlChannel = TRUE;
  13. TraceRFCOMM = FALSE;
  14. (* Frame Types *)
  15. SABMFRAME = 02FH;
  16. UAFRAME = 063H;
  17. DMFRAME = 00FH;
  18. DISCFRAME = 043H;
  19. UIHFRAME = 0EFH;
  20. (* DLC states *)
  21. DISCONNECTED = 0;
  22. CONNECTING = 1;
  23. NEGOTIATING = 2;
  24. CONNECTED = 3;
  25. DISCONNECTING = 4;
  26. MAXBUFSIZE = 1024;
  27. TYPE
  28. Buffer = OBJECT
  29. VAR
  30. maxBufSize : LONGINT;
  31. fifoBuffer : POINTER TO ARRAY OF CHAR;
  32. head, tail : LONGINT;
  33. dead : BOOLEAN;
  34. PROCEDURE &Init*(maxBufSize : LONGINT);
  35. BEGIN
  36. SELF.maxBufSize := maxBufSize;
  37. NEW(fifoBuffer,maxBufSize);
  38. head := 0; tail := 0;
  39. dead := FALSE;
  40. END Init;
  41. PROCEDURE Close;
  42. BEGIN {EXCLUSIVE}
  43. dead := TRUE;
  44. END Close;
  45. PROCEDURE Get(VAR ch : CHAR; VAR result : WORD);
  46. BEGIN {EXCLUSIVE}
  47. IF TraceBuffer THEN
  48. KernelLog.String(ModuleName);
  49. KernelLog.String("Buffer.Get: Await ... head = "); KernelLog.Int(head,0);
  50. KernelLog.String(" tail = "); KernelLog.Int(tail,0);
  51. KernelLog.Ln;
  52. END;
  53. AWAIT((tail # head) OR dead);
  54. IF(tail#head) THEN
  55. ch := fifoBuffer[head];
  56. head := (head +1) MOD maxBufSize ;
  57. result := 0;
  58. ELSE (* dead *)
  59. KernelLog.String(ModuleName);
  60. KernelLog.String("Buffer.Get: error.");
  61. KernelLog.Ln;
  62. result := -1;
  63. END;
  64. IF TraceBuffer THEN
  65. KernelLog.String(ModuleName);
  66. KernelLog.String("Buffer.Get: done. result = "); KernelLog.Hex(result,-2);
  67. KernelLog.Ln;
  68. END;
  69. END Get;
  70. PROCEDURE Put(ch : CHAR; VAR result : LONGINT);
  71. BEGIN {EXCLUSIVE}
  72. IF((tail+1) MOD MAXBUFSIZE # head) THEN
  73. fifoBuffer[tail] := ch;
  74. tail := (tail +1) MOD maxBufSize ;
  75. result := 0;
  76. ELSE (* overflow *)
  77. KernelLog.String(ModuleName);
  78. KernelLog.String("Buffer.Get: overflow.");
  79. result := -1;
  80. END;
  81. END Put;
  82. PROCEDURE IsFull() : BOOLEAN;
  83. BEGIN {EXCLUSIVE}
  84. IF((tail+1) MOD maxBufSize # head) THEN
  85. RETURN FALSE;
  86. ELSE
  87. RETURN TRUE;
  88. END;
  89. END IsFull;
  90. PROCEDURE IsEmpty() : BOOLEAN;
  91. BEGIN {EXCLUSIVE}
  92. IF(tail # head) THEN
  93. RETURN FALSE;
  94. ELSE
  95. RETURN TRUE;
  96. END;
  97. END IsEmpty;
  98. PROCEDURE Dump;
  99. VAR
  100. h,t,elements : LONGINT;
  101. BEGIN {EXCLUSIVE}
  102. h := head MOD maxBufSize;
  103. t := tail MOD maxBufSize;
  104. IF h<=t THEN
  105. elements := t-h;
  106. ELSE
  107. elements := t-h+maxBufSize;
  108. END;
  109. KernelLog.String(ModuleName);
  110. KernelLog.String("Buffer.Dump:"); KernelLog.Ln;
  111. KernelLog.String("buffer size = "); KernelLog.Int(maxBufSize,0);
  112. KernelLog.String(" head pos = "); KernelLog.Int(h,0);
  113. KernelLog.String(" tail pos = "); KernelLog.Int(t,0);
  114. KernelLog.String(" #elements = "); KernelLog.Int(elements,0);
  115. KernelLog.Ln;
  116. WHILE(h < t) DO
  117. KernelLog.Hex(ORD(fifoBuffer[h]),-2); KernelLog.String(" ");
  118. h := (h+1) MOD maxBufSize;
  119. END;
  120. KernelLog.Ln;
  121. END Dump;
  122. END Buffer;
  123. (* ------------------------------------------------------------------------------ *)
  124. Channel = OBJECT
  125. VAR
  126. dlci : LONGINT;
  127. state : LONGINT;
  128. rfcomm : RFCOMM;
  129. receiveBuffer : Buffer;
  130. (* --------------------------------------------- *)
  131. PROCEDURE &Init*(rfcomm : RFCOMM; dlci : LONGINT);
  132. BEGIN
  133. SELF.rfcomm := rfcomm;
  134. SELF.dlci := dlci;
  135. SetState(DISCONNECTED);
  136. NEW(receiveBuffer,MAXBUFSIZE);
  137. END Init;
  138. (* --------------------------------------------- *)
  139. PROCEDURE Close;
  140. BEGIN
  141. SetState(DISCONNECTED);
  142. receiveBuffer.Close();
  143. END Close;
  144. (* --------------------------------------------- *)
  145. PROCEDURE SetState(state : LONGINT);
  146. BEGIN {EXCLUSIVE}
  147. SELF.state := state;
  148. END SetState;
  149. (* --------------------------------------------- *)
  150. PROCEDURE W4State(state : LONGINT) : LONGINT;
  151. BEGIN {EXCLUSIVE}
  152. AWAIT((SELF.state = state) OR (SELF.state = DISCONNECTED));
  153. RETURN SELF.state;
  154. END W4State;
  155. (* --------------------------------------------- *)
  156. PROCEDURE SendSABM;
  157. VAR
  158. frame : ARRAY 4 OF CHAR;
  159. BEGIN
  160. IF (state = DISCONNECTED) THEN
  161. frame[0] := CHR(dlci*4+3); (* address: xxxx xx11; EA & C bit set *)
  162. frame[1] := CHR(BITLOR(SABMFRAME,010H)); (* control; SABM Frame P bit set *)
  163. frame[2] := CHR(01H); (* length: 0000 0001; Length = 0, EA bit set *)
  164. frame[3] := CalculateFCS(frame,3); (* FCS; calculate over address control and lenght *)
  165. rfcomm.SendFrame(frame,4);
  166. SetState(CONNECTING);
  167. END;
  168. END SendSABM;
  169. (* --------------------------------------------- *)
  170. PROCEDURE SendDISC;
  171. VAR
  172. frame : ARRAY 4 OF CHAR;
  173. BEGIN
  174. IF(state # DISCONNECTED) THEN
  175. frame[0] := CHR(dlci*4+3); (* address: xxxx xx11; EA & C bit set *)
  176. frame[1] := CHR(BITLOR(DISCFRAME,010H)); (* control; DISC Frame P bit set *)
  177. frame[2] := CHR(01H); (* length: 0000 0001; Length = 0, EA bit set *)
  178. frame[3] := CalculateFCS(frame,3); (* FCS; calculate over address control and lenght *)
  179. rfcomm.SendFrame(frame,4);
  180. SetState(DISCONNECTING);
  181. END;
  182. END SendDISC;
  183. (* --------------------------------------------- *)
  184. PROCEDURE SendUA;
  185. VAR
  186. frame : ARRAY 4 OF CHAR;
  187. BEGIN
  188. frame[0] := CHR(dlci*4+3); (* address: xxxx xx11; EA & C bit set *)
  189. frame[1] := CHR(BITLOR(UAFRAME,010H)); (* control; UA Frame F bit set *)
  190. frame[2] := CHR(01H); (* length: 0000 0001; Length = 0, EA bit set *)
  191. frame[3] := CalculateFCS(frame,3); (* FCS; calculate over address control and lenght *)
  192. rfcomm.SendFrame(frame,4);
  193. END SendUA;
  194. (* --------------------------------------------- *)
  195. PROCEDURE SendDM;
  196. VAR
  197. frame : ARRAY 4 OF CHAR;
  198. BEGIN
  199. frame[0] := CHR(dlci*4+3); (* address: xxxx xx11; EA & C bit set *)
  200. frame[1] := CHR(BITLOR(DMFRAME,010H)); (* control; DM Frame F bit set *)
  201. frame[2] := CHR(01H); (* length: 0000 0001; Length = 0, EA bit set *)
  202. frame[3] := CalculateFCS(frame,3); (* FCS; calculate over address control and lenght *)
  203. rfcomm.SendFrame(frame,4);
  204. END SendDM;
  205. (* --------------------------------------------- *)
  206. PROCEDURE SendUIH(info : ARRAY OF CHAR; infoLength : LONGINT);
  207. VAR
  208. frame : ARRAY 131 OF CHAR;
  209. i : LONGINT;
  210. BEGIN
  211. ASSERT(infoLength < 128);
  212. frame[0] := CHR(dlci * 4 + 3); (* address: xxxx xx11; EA & C/R bit set *)
  213. frame[1] := CHR(UIHFRAME); (* control; UIH Frame P bit not set *)
  214. frame[2] := CHR(infoLength * 2 +1); (* length; EA bit set *)
  215. FOR i := 0 TO infoLength-1 DO (* information *)
  216. frame[3+i] := info[i];
  217. END;
  218. frame[infoLength+3] := CalculateFCS(frame,2); (* FCS; calculate over address and control *)
  219. rfcomm.SendFrame(frame,infoLength + 4);
  220. END SendUIH;
  221. (* --------------------------------------------- *)
  222. PROCEDURE ReceiveSABM;
  223. BEGIN
  224. IF TraceChannel THEN
  225. KernelLog.String(ModuleName);
  226. KernelLog.String("Channel.ReceiveSABM: dlci = "); KernelLog.Hex(dlci,-2);
  227. KernelLog.Ln;
  228. END;
  229. SendDM(); (* TO DO: accept connections *)
  230. END ReceiveSABM;
  231. (* --------------------------------------------- *)
  232. PROCEDURE ReceiveUA;
  233. BEGIN
  234. IF TraceChannel THEN
  235. KernelLog.String(ModuleName);
  236. KernelLog.String("Channel.ReceiveUA: dlci = "); KernelLog.Hex(dlci,-2);
  237. KernelLog.Ln;
  238. END;
  239. IF(state = CONNECTING) THEN
  240. SetState(CONNECTED);
  241. ELSIF(state = DISCONNECTING) THEN
  242. Close();
  243. END;
  244. END ReceiveUA;
  245. (* --------------------------------------------- *)
  246. PROCEDURE ReceiveDM;
  247. BEGIN
  248. IF TraceChannel THEN
  249. KernelLog.String(ModuleName);
  250. KernelLog.String("Channel.ReceiveDM: dlci = "); KernelLog.Hex(dlci,-2);
  251. KernelLog.Ln;
  252. END;
  253. Close();
  254. END ReceiveDM;
  255. (* --------------------------------------------- *)
  256. PROCEDURE ReceiveDISC;
  257. BEGIN
  258. IF TraceChannel THEN
  259. KernelLog.String(ModuleName);
  260. KernelLog.String("Channel.ReceiveDISC: dlci = "); KernelLog.Hex(dlci,-2);
  261. KernelLog.Ln;
  262. END;
  263. IF(state = DISCONNECTED) THEN
  264. SendDM();
  265. ELSE
  266. SendUA();
  267. END;
  268. Close();
  269. END ReceiveDISC;
  270. (* --------------------------------------------- *)
  271. PROCEDURE ReceiveUIH(frame : ARRAY OF CHAR; frameLength : LONGINT);
  272. VAR
  273. infoLength : LONGINT;
  274. result : LONGINT;
  275. i : LONGINT;
  276. BEGIN
  277. IF TraceChannel THEN
  278. KernelLog.String(ModuleName);
  279. KernelLog.String("Channel.ReceiveUIH: dlci = "); KernelLog.Hex(dlci,-2);
  280. KernelLog.String(" infoLength = "); KernelLog.Int((ORD(frame[2]) - 1) DIV 2,0);
  281. KernelLog.Ln;
  282. END;
  283. IF (state = CONNECTED) THEN
  284. infoLength := (ORD(frame[2]) - 1) DIV 2;
  285. ASSERT(infoLength < 128); (* TO DO: accept larger frames *)
  286. FOR i:= 0 TO infoLength-1 DO
  287. IF (~receiveBuffer.IsFull()) THEN
  288. receiveBuffer.Put(frame[3+i],result);
  289. ASSERT(result = 0);
  290. ELSE
  291. (* TO DO: overflow *)
  292. KernelLog.String(ModuleName);
  293. KernelLog.String("Channel.ReceiveUIH: dlci = "); KernelLog.Hex(dlci,-2);
  294. KernelLog.String(" buffer overflow!");
  295. KernelLog.Ln;
  296. END;
  297. END;
  298. END;
  299. END ReceiveUIH;
  300. (* --------------------------------------------- *)
  301. PROCEDURE CalculateFCS(data : ARRAY OF CHAR; length : LONGINT) : CHAR;
  302. VAR
  303. fcs : CHAR;
  304. i : LONGINT;
  305. BEGIN
  306. fcs := CHR(0FFH);
  307. i := 0;
  308. WHILE (length > 0) DO
  309. fcs := crcTable[ORD(BITCXOR(fcs,data[i]))];
  310. INC(i); DEC(length)
  311. END;
  312. RETURN CHR(0FFH - ORD(fcs));
  313. END CalculateFCS;
  314. (* --------------------------------------------- *)
  315. PROCEDURE Sender(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  316. VAR
  317. info : ARRAY 127 OF CHAR;
  318. infoLength : LONGINT;
  319. i : LONGINT;
  320. BEGIN
  321. IF TraceChannel THEN
  322. KernelLog.String(ModuleName);
  323. KernelLog.String("Channel.Sender: dlci = "); KernelLog.Hex(dlci,-2);
  324. KernelLog.Ln;
  325. END;
  326. i := 0;
  327. WHILE(i < len) DO
  328. infoLength := 0;
  329. WHILE((infoLength < LEN(info)) & (i < len)) DO
  330. info[infoLength] := buf[i+ofs];
  331. INC(infoLength); INC(i);
  332. END;
  333. SendUIH(info,infoLength);
  334. END;
  335. END Sender;
  336. (* --------------------------------------------- *)
  337. PROCEDURE Receiver(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD);
  338. BEGIN
  339. IF TraceChannel THEN
  340. KernelLog.String(ModuleName);
  341. KernelLog.String("Channel.Receiver: dlci = "); KernelLog.Hex(dlci,-2);
  342. KernelLog.Ln;
  343. END;
  344. len := 0;
  345. res := 0;
  346. WHILE((len < min) & (res = 0)) DO
  347. receiveBuffer.Get(buf[ofs+len],res);
  348. INC(len);
  349. END;
  350. WHILE((len < size) & (~receiveBuffer.IsEmpty()) & (res = 0)) DO
  351. receiveBuffer.Get(buf[ofs+len],res);
  352. INC(len);
  353. END;
  354. END Receiver;
  355. (* --------------------------------------------- *)
  356. END Channel;
  357. (* ------------------------------------------------------------------------------ *)
  358. ControlChannel = OBJECT (Channel)
  359. (* TO DO *)
  360. PROCEDURE ReceiveUIH(info : ARRAY OF CHAR; length : LONGINT);
  361. BEGIN
  362. IF TraceControlChannel THEN
  363. KernelLog.String(ModuleName);
  364. KernelLog.String("ControlChannel.ReceiveUIH: multiplexer control command received.");
  365. KernelLog.Ln;
  366. END;
  367. END ReceiveUIH;
  368. END ControlChannel;
  369. (* ------------------------------------------------------------------------------ *)
  370. (* RFCOMM API *)
  371. RFCOMM* = OBJECT
  372. VAR
  373. l2capLayer : BluetoothL2CAP.L2CAP;
  374. l2capCID : LONGINT;
  375. l2capConfReqReceived : BOOLEAN;
  376. l2capOpen : BOOLEAN;
  377. rfcommOpen : BOOLEAN;
  378. channelList : ARRAY 62 OF Channel;
  379. ok : BOOLEAN;
  380. PROCEDURE &Init*(l2capLayer : BluetoothL2CAP.L2CAP);
  381. VAR
  382. result : WORD;
  383. controlChannel : ControlChannel;
  384. i : LONGINT;
  385. BEGIN
  386. NEW(controlChannel,SELF,i);
  387. channelList[0] := controlChannel;
  388. FOR i := 1 TO 61 DO
  389. NEW(channelList[i],SELF,i);
  390. END;
  391. SELF.l2capLayer := l2capLayer;
  392. SetL2CAPOpen(FALSE);
  393. SetL2CAPConfReqReceived(FALSE);
  394. l2capLayer.EventIndication(BluetoothL2CAP.EConfigInd,L2CAPConfigIndication,result);
  395. ASSERT(result = 0);
  396. l2capLayer.EventIndication(BluetoothL2CAP.EDisconnectInd,L2CAPDisconnectIndication,result);
  397. ASSERT(result = 0);
  398. SetRFCOMMOpen(TRUE);
  399. END Init;
  400. PROCEDURE GetL2CAPLayer*() : BluetoothL2CAP.L2CAP;
  401. BEGIN
  402. RETURN l2capLayer;
  403. END GetL2CAPLayer;
  404. PROCEDURE Start*(bdAddr: Bluetooth.BDAddr; VAR result : WORD);
  405. VAR
  406. status : LONGINT;
  407. inMTU, outFlushTO : LONGINT;
  408. outFlow,linkTO : LONGINT;
  409. ok : BOOLEAN;
  410. BEGIN
  411. l2capLayer.Connect(BluetoothL2CAP.psmRFCOMM,bdAddr,l2capCID,result,status);
  412. IF (result # 0) THEN
  413. IF TraceRFCOMM THEN
  414. KernelLog.String(ModuleName);
  415. KernelLog.String("RFCOMM.Start: L2CAP connection failed. result = "); KernelLog.Hex(result,-2);
  416. KernelLog.Ln();
  417. END;
  418. ELSE
  419. inMTU := Bluetooth.MaxACLDataLen;
  420. outFlushTO := 0FFFFH;
  421. IF TraceRFCOMM THEN
  422. KernelLog.String(ModuleName);
  423. KernelLog.String("RFCOMM.Start: configure L2CAP channel: MTU = "); KernelLog.Int(inMTU,0);
  424. KernelLog.String(" Flow = "); KernelLog.Int(outFlow,0);
  425. KernelLog.String(" FlushTo = "); KernelLog.Int(outFlushTO,0);
  426. KernelLog.String(" ...");
  427. KernelLog.Ln;
  428. END;
  429. l2capLayer.Configure(l2capCID,inMTU,outFlow,outFlushTO,linkTO,result);
  430. IF (result # 0) THEN
  431. KernelLog.String(ModuleName);
  432. KernelLog.String("RFCOMM.Start: L2CAP configuration failed. result = "); KernelLog.Hex(result,-2);
  433. KernelLog.Ln();
  434. ELSE
  435. IF TraceRFCOMM THEN
  436. KernelLog.String(ModuleName);
  437. KernelLog.String("RFCOMM.Start: configuration done. result = "); KernelLog.Hex(result,-2);
  438. KernelLog.String(" MTU = "); KernelLog.Int(inMTU,0);
  439. KernelLog.String(" Flow = "); KernelLog.Int(outFlow,0);
  440. KernelLog.String(" FlushTo = "); KernelLog.Int(outFlushTO,0);
  441. KernelLog.Ln;
  442. END;
  443. ok := W4L2CAPConfReqReceived();
  444. IF(ok) THEN
  445. SetL2CAPOpen(TRUE);
  446. channelList[0].SendSABM();
  447. ELSE
  448. result := -1;
  449. END;
  450. END;
  451. END;
  452. END Start;
  453. PROCEDURE Close*(VAR result : LONGINT);
  454. VAR i : LONGINT;
  455. BEGIN
  456. IF TraceRFCOMM THEN
  457. KernelLog.String(ModuleName);
  458. KernelLog.String("RFCOMM.Close: ...");
  459. KernelLog.Ln;
  460. END;
  461. IF ~rfcommOpen THEN
  462. IF TraceRFCOMM THEN
  463. KernelLog.String(ModuleName);
  464. KernelLog.String("RFCOMM.Close: already close");
  465. KernelLog.Ln;
  466. END;
  467. RETURN;
  468. END;
  469. FOR i:= 0 TO 61 DO
  470. channelList[i].SendDISC();
  471. channelList[i].Close();
  472. END;
  473. result := 0;
  474. IF(l2capOpen) THEN
  475. l2capLayer.Disconnect(l2capCID,result);
  476. IF (result # 0) THEN
  477. IF TraceRFCOMM THEN
  478. KernelLog.String(ModuleName);
  479. KernelLog.String("RFCOMM.Close: l2capLayer.Disconnect failed. result = "); KernelLog.Hex(result,-2);
  480. KernelLog.Ln();
  481. END;
  482. END;
  483. SetL2CAPOpen(FALSE);
  484. SetL2CAPConfReqReceived(FALSE);
  485. END;
  486. l2capLayer.Close;
  487. SetRFCOMMOpen(FALSE);
  488. IF TraceRFCOMM THEN
  489. KernelLog.String(ModuleName);
  490. KernelLog.String("RFCOMM.Close: done. result = "); KernelLog.Int(result,0);
  491. KernelLog.Ln;
  492. END;
  493. END Close;
  494. PROCEDURE EstablishChannel*(serverChannel : LONGINT; VAR result : LONGINT);
  495. VAR
  496. state : LONGINT;
  497. BEGIN
  498. channelList[serverChannel * 2].SendSABM();
  499. state := channelList[serverChannel * 2].W4State(CONNECTED);
  500. IF state = CONNECTED THEN
  501. result := 0;
  502. ELSE
  503. result := -1;
  504. END;
  505. END EstablishChannel;
  506. PROCEDURE ReleaseChannel*(serverChannel : LONGINT; VAR result : LONGINT);
  507. VAR
  508. state : LONGINT;
  509. BEGIN
  510. channelList[serverChannel*2].SendDISC();
  511. state := channelList[serverChannel * 2].W4State(DISCONNECTED);
  512. IF state = DISCONNECTED THEN
  513. result := 0;
  514. ELSE
  515. result := -1;
  516. END;
  517. END ReleaseChannel;
  518. PROCEDURE SendInformation*(serverChannel : LONGINT; info : ARRAY OF CHAR; infoLength : LONGINT);
  519. VAR
  520. result : WORD;
  521. BEGIN
  522. channelList[serverChannel * 2].Sender(info,0,infoLength,TRUE,result);
  523. END SendInformation;
  524. PROCEDURE ReceiveInformation*(serverChannel : LONGINT; VAR info : ARRAY OF CHAR; VAR infoLength : LONGINT);
  525. VAR
  526. result : WORD;
  527. BEGIN
  528. channelList[serverChannel * 2].Receiver(info,0,LEN(info),1,infoLength,result);
  529. END ReceiveInformation;
  530. PROCEDURE GetSender*(serverChannel : LONGINT) : Streams.Sender;
  531. BEGIN
  532. RETURN channelList[serverChannel * 2].Sender;
  533. END GetSender;
  534. PROCEDURE GetReceiver*(serverChannel : LONGINT) : Streams.Receiver;
  535. BEGIN
  536. RETURN channelList[serverChannel * 2].Receiver;
  537. END GetReceiver;
  538. PROCEDURE SetRFCOMMOpen(state : BOOLEAN);
  539. BEGIN {EXCLUSIVE}
  540. rfcommOpen := state;
  541. END SetRFCOMMOpen;
  542. PROCEDURE SetL2CAPConfReqReceived(state : BOOLEAN);
  543. BEGIN {EXCLUSIVE}
  544. l2capConfReqReceived := state;
  545. END SetL2CAPConfReqReceived;
  546. PROCEDURE W4L2CAPConfReqReceived() : BOOLEAN;
  547. BEGIN {EXCLUSIVE}
  548. AWAIT(l2capConfReqReceived OR ~rfcommOpen);
  549. IF(rfcommOpen) THEN
  550. RETURN TRUE;
  551. ELSE
  552. RETURN FALSE;
  553. END;
  554. END W4L2CAPConfReqReceived;
  555. PROCEDURE SetL2CAPOpen(state: BOOLEAN);
  556. BEGIN {EXCLUSIVE}
  557. l2capOpen := state;
  558. END SetL2CAPOpen;
  559. PROCEDURE W4L2CAPOpen() : BOOLEAN;
  560. BEGIN {EXCLUSIVE}
  561. AWAIT(l2capOpen OR ~rfcommOpen);
  562. IF(rfcommOpen) THEN
  563. RETURN TRUE;
  564. ELSE
  565. RETURN FALSE;
  566. END;
  567. END W4L2CAPOpen;
  568. PROCEDURE L2CAPConnectIndication(indication: BluetoothL2CAP.Indication);
  569. BEGIN
  570. KernelLog.String(ModuleName);
  571. KernelLog.String("RFCOMM.L2CAPConnectIndication: ignore!");
  572. KernelLog.Ln;
  573. END L2CAPConnectIndication;
  574. PROCEDURE L2CAPDisconnectIndication(indication: BluetoothL2CAP.Indication);
  575. VAR
  576. result : LONGINT;
  577. BEGIN
  578. KernelLog.String(ModuleName);
  579. KernelLog.String("RFCOMM.L2CAPDisconnectIndication: shutdown RFCOMM");
  580. KernelLog.Ln;
  581. Close(result);
  582. END L2CAPDisconnectIndication;
  583. PROCEDURE L2CAPConfigIndication(inParam : BluetoothL2CAP.Indication);
  584. VAR
  585. result : WORD;
  586. BEGIN
  587. WITH inParam : BluetoothL2CAP.ConfigInd DO
  588. IF TraceRFCOMM THEN
  589. KernelLog.String(ModuleName);
  590. KernelLog.String("RFCOMM.L2CAPConfigIndication: ..."); KernelLog.Ln;
  591. KernelLog.String("cid = "); KernelLog.Int(inParam.c.sid,0);
  592. KernelLog.String(" ident = "); KernelLog.Int(ORD(inParam.ident),0);
  593. KernelLog.String(" MTU = "); KernelLog.Int(inParam.outMTU,0);
  594. KernelLog.String(" FlushTO = "); KernelLog.Int(inParam.inFlushTO,0);
  595. KernelLog.Ln;
  596. END;
  597. l2capLayer.ConfigurationResponse(inParam.c.sid,inParam.ident,inParam.outMTU,
  598. inParam.inFlushTO,result);
  599. END;
  600. SetL2CAPConfReqReceived(TRUE);
  601. END L2CAPConfigIndication;
  602. PROCEDURE SendFrame(frame : ARRAY OF CHAR;length : LONGINT);
  603. VAR
  604. size : LONGINT;
  605. result : WORD;
  606. i : LONGINT;
  607. BEGIN
  608. IF TraceRFCOMM THEN
  609. KernelLog.String(ModuleName);
  610. KernelLog.String("RFCOMM.SendFrame: data size = "); KernelLog.Int(length,0);
  611. KernelLog.Ln;
  612. FOR i := 0 TO length-1 DO
  613. KernelLog.Hex(ORD(frame[i]), -2); KernelLog.String(" " );
  614. END;
  615. KernelLog.Ln;
  616. END;
  617. IF(l2capOpen = TRUE) THEN
  618. l2capLayer.Write(l2capCID,0,length,frame,size,result);
  619. END;
  620. IF (result # 0) THEN
  621. KernelLog.String(ModuleName);
  622. KernelLog.String("RFCOMM.SendFrame: l2cap.Write failed. result = "); KernelLog.Int(result,0);
  623. KernelLog.Ln;
  624. END;
  625. END SendFrame;
  626. PROCEDURE ReceiveFrame;
  627. VAR
  628. buffer : ARRAY 512 OF CHAR;
  629. i : LONGINT;
  630. result,size : LONGINT;
  631. frameType : LONGINT;
  632. dlci : LONGINT;
  633. BEGIN
  634. REPEAT
  635. l2capLayer.Read(l2capCID,LEN(buffer),buffer,result,size);
  636. IF (result = 0) THEN
  637. IF TraceRFCOMM THEN
  638. KernelLog.String(ModuleName);
  639. KernelLog.String("RFCOMM.ReceiveFrame: data size = "); KernelLog.Int(size,0);
  640. KernelLog.Ln;
  641. FOR i := 0 TO size-1 DO
  642. KernelLog.Hex(ORD(buffer[i]), -2); KernelLog.String(" " );
  643. END;
  644. KernelLog.Ln;
  645. END;
  646. dlci := ORD(buffer[0]) DIV 4;
  647. frameType := BITLAND(ORD(buffer[1]),0EFH);
  648. IF (frameType = SABMFRAME) THEN
  649. channelList[dlci].ReceiveSABM();
  650. ELSIF(frameType = UAFRAME) THEN
  651. channelList[dlci].ReceiveUA();
  652. ELSIF(frameType = DMFRAME) THEN
  653. channelList[dlci].ReceiveDM();
  654. ELSIF(frameType = DISCFRAME) THEN
  655. channelList[dlci].ReceiveDISC();
  656. ELSIF(frameType = UIHFRAME) THEN
  657. channelList[dlci].ReceiveUIH(buffer,size);
  658. ELSE
  659. KernelLog.String("unknown frame! "); KernelLog.Hex(frameType,-2);
  660. KernelLog.String(" DLCI = "); KernelLog.Hex(dlci,-2);
  661. KernelLog.Ln;
  662. END;
  663. ELSE
  664. KernelLog.String(ModuleName);
  665. KernelLog.String("RFCOMM.ReceiveFrame: l2cap.Read failed. result = "); KernelLog.Int(result,0);
  666. KernelLog.Ln;
  667. END;
  668. UNTIL (result # 0);
  669. END ReceiveFrame;
  670. BEGIN {ACTIVE}
  671. IF TraceRFCOMM THEN
  672. KernelLog.String(ModuleName);
  673. KernelLog.String("RFCOMM: {ACTIVE} ...");
  674. KernelLog.Ln;
  675. END;
  676. ok := W4L2CAPOpen();
  677. IF(ok) THEN
  678. ReceiveFrame();
  679. END;
  680. IF TraceRFCOMM THEN
  681. KernelLog.String(ModuleName);
  682. KernelLog.String("RFCOMM: {ACTIVE} done.");
  683. KernelLog.Ln;
  684. END;
  685. END RFCOMM;
  686. (* ------------------------------------------------------------------------ *)
  687. VAR
  688. crcTable: ARRAY 256 OF CHAR;
  689. (* ------------------------------------------------------------------------ *)
  690. PROCEDURE CreateCRCTable;
  691. VAR
  692. i,j : LONGINT;
  693. pol,data,sr : CHAR;
  694. op1,op2,op3 : CHAR;
  695. BEGIN
  696. pol := CHR(224);
  697. FOR j := 0 TO 255 DO
  698. sr := CHR(0);
  699. data := CHR(j);
  700. FOR i := 0 TO 7 DO
  701. op1 := BITCAND(data,CHR(1));
  702. op2 := BITCAND(sr,CHR(1));
  703. op3 := BITCXOR(op1,op2);
  704. sr := CHR(ORD(sr) DIV 2);
  705. IF (op3 #CHR( 0)) THEN
  706. sr := BITCXOR(sr,pol);
  707. END;
  708. data := CHR(ORD(data) DIV 2);
  709. sr := BITCAND(sr,CHR(255));
  710. END;
  711. crcTable[j] := sr;
  712. END;
  713. END CreateCRCTable;
  714. (* ------------------------------------------------------------------------ *)
  715. PROCEDURE BITLOR(x, y: LONGINT): LONGINT;
  716. BEGIN RETURN S.VAL(LONGINT, S.VAL(SET, x) + S.VAL(SET, y))
  717. END BITLOR;
  718. PROCEDURE BITCAND(x, y: CHAR): CHAR;
  719. BEGIN RETURN CHR(S.VAL(LONGINT, S.VAL(SET, LONG(ORD(x))) * S.VAL(SET, LONG(ORD(y)))))
  720. END BITCAND;
  721. PROCEDURE BITCXOR(x, y: CHAR): CHAR;
  722. BEGIN RETURN CHR(S.VAL(LONGINT, S.VAL(SET, LONG(ORD(x))) / S.VAL(SET, LONG(ORD(y)))))
  723. END BITCXOR;
  724. PROCEDURE BITLAND(x, y: LONGINT): LONGINT;
  725. BEGIN RETURN S.VAL(LONGINT, S.VAL(SET, x) * S.VAL(SET, y))
  726. END BITLAND;
  727. BEGIN
  728. CreateCRCTable();
  729. END BluetoothRFCOMM.