BluetoothL2CAP.Mod 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264
  1. MODULE BluetoothL2CAP; (** AUTHOR "be"; PURPOSE "Bluetooth L2CAP driver"; *)
  2. IMPORT
  3. KernelLog, Objects, Bluetooth, HCI := BluetoothHCI;
  4. CONST
  5. (*
  6. Trace = FALSE;
  7. TraceRead = FALSE;
  8. TraceSignallingChannel = FALSE;
  9. TraceReassembler = FALSE;
  10. TraceChannelManager = FALSE;
  11. TraceHCIEvents = FALSE;
  12. TraceL2CAPEventHandling = FALSE;
  13. Trace = TRUE;
  14. TraceRead = TRUE;
  15. TraceSignallingChannel = TRUE;
  16. TraceReassembler = TRUE;
  17. TraceChannelManager = TRUE;
  18. TraceHCIEvents = FALSE;
  19. TraceL2CAPEventHandling = TRUE;
  20. *)
  21. TraceChannel = FALSE;
  22. TraceChannelManager = FALSE;
  23. TraceHCIManager = TRUE;
  24. TraceL2CAP = FALSE;
  25. TracePacketBuffer = FALSE;
  26. TraceReassembler = FALSE;
  27. TraceSignallingChannel = FALSE;
  28. ModuleName = "[BTL2CAP]";
  29. Error* = -1;
  30. TYPE
  31. (** event types *)
  32. Event* = LONGINT;
  33. CONST
  34. (**----- event indication -----*)
  35. EConnectInd* = 1; (** connection indication event *)
  36. EConfigInd* = 2; (** configuration indication event *)
  37. EDisconnectInd* = 3; (** disconnection indication event *)
  38. EQoSViolationInd* = 4; (** QoS violation indication event *)
  39. MinEventIndication = EConnectInd;
  40. MaxEventIndication = EQoSViolationInd;
  41. (** Protocol/Service Multiplexor (PSM) *)
  42. psmSDP* = 1; (** service discovery protocol *)
  43. psmRFCOMM* = 3; (** RFCOMM *)
  44. psmTCP* = 5; (** telephony control protocol *)
  45. MaxPacketQueue = 256;
  46. TYPE
  47. (** callback parameters *)
  48. Indication* = POINTER TO RECORD (** base type for indication parameters *)
  49. c-: Channel; (** channel *)
  50. ident-: CHAR; (* identifier of request *)
  51. END;
  52. ConnectInd* = POINTER TO RECORD(Indication) (** parameter for connection indication events *)
  53. bdAddr*: Bluetooth.BDAddr; (** Bluetooth device address *)
  54. cid*: LONGINT; (** channel ID *)
  55. psm*: LONGINT; (** protocol/service multiplexor *)
  56. END;
  57. ConfigInd* = POINTER TO RECORD(Indication) (** parameter for configuration indication events *)
  58. cid*: LONGINT; (** channel ID *)
  59. outMTU*: LONGINT; (** outgoing MTU information *)
  60. inFlow*: LONGINT; (** incoming flow information *)
  61. inFlushTO*: LONGINT (** incoming flush timeout *)
  62. END;
  63. DisconnectInd* = POINTER TO RECORD(Indication) (** parameter for desconnection indication events *)
  64. cid*: LONGINT (** channel ID *)
  65. END;
  66. QoSViolationInd* = POINTER TO RECORD(Indication) (** parameter for QoS violation indication events *)
  67. bdAddr*: Bluetooth.BDAddr (** Bluetooth device address *)
  68. END;
  69. (** callback type *)
  70. EventIndicationCallback* = PROCEDURE {DELEGATE} (indication: Indication);
  71. (**----- additional types -----*)
  72. (** list of group members *)
  73. GroupMembers* = POINTER TO ARRAY OF Bluetooth.BDAddr;
  74. CONST
  75. MinCID = 3; (* 0: reserved, 1: signalling channel, 2: connection-less channel *)
  76. MaxCIDs = 1024;
  77. ConnectTimeout = 10000;
  78. RTXTimeout = 5000;
  79. MaxTries = 3;
  80. (* L2CAP channel states *)
  81. Closed = 0; (* !! 1 or 0 ?? !! mm *)
  82. W4L2CAPConnectRsp = 1;
  83. W4L2CAConnectRsp = 2;
  84. Config = 3; Open = 4;
  85. W4L2CAPDisconnectRsp = 5;
  86. W4L2CADisconnectRsp = 6;
  87. cidSignalling = 1; (* CID of signalling channel *)
  88. cidConnectionless = 2; (* CID of connectionless channel *)
  89. (* signals *)
  90. sigCommandReject = 01X;
  91. sigConnectionReq = 02X;
  92. sigConnectionResp = 03X;
  93. sigConfigureReq = 04X;
  94. sigConfigureResp = 05X;
  95. sigDisconnectionReq = 06X;
  96. sigDisconnectionResp = 07X;
  97. sigEchoReq = 08X;
  98. sigEchoResp = 09X;
  99. sigInformationReq = 0AX;
  100. sigInformationResp = 0BX;
  101. (* configuration options *)
  102. optMTU = 01X;
  103. optFlushTO = 02X;
  104. optQoS = 03X;
  105. TYPE
  106. PChar = POINTER TO ARRAY OF CHAR;
  107. (* ----------------------------------------------------------------------------------------- *)
  108. (* L2CAP packet *)
  109. Packet = POINTER TO RECORD
  110. next: Packet;
  111. link: HCI.Link; (* packet comes from this link *)
  112. cid, len: LONGINT;
  113. data: PChar;
  114. END;
  115. PacketBuffer = OBJECT
  116. VAR
  117. head, num: LONGINT;
  118. closed: BOOLEAN;
  119. buffer: POINTER TO ARRAY OF Packet;
  120. PROCEDURE Append(x: Packet);
  121. BEGIN {EXCLUSIVE}
  122. AWAIT((num # LEN(buffer)) OR closed);
  123. buffer[(head+num) MOD LEN(buffer)] := x;
  124. IF num > 100 THEN KernelLog.String("!") END;
  125. INC(num)
  126. END Append;
  127. PROCEDURE Remove(): Packet;
  128. VAR x: Packet;
  129. BEGIN {EXCLUSIVE}
  130. AWAIT((num # 0) OR closed);
  131. x := buffer[head];
  132. head := (head+1) MOD LEN(buffer);
  133. DEC(num);
  134. RETURN x
  135. END Remove;
  136. PROCEDURE &Init*(n: LONGINT);
  137. BEGIN
  138. head := 0; num := 0; closed := FALSE; NEW(buffer, n)
  139. END Init;
  140. PROCEDURE Close;
  141. BEGIN {EXCLUSIVE}
  142. closed := TRUE
  143. END Close;
  144. END PacketBuffer;
  145. (* ----------------------------------------------------------------------------------------- *)
  146. Channel* = OBJECT (** L2CAP channel *)
  147. VAR
  148. next: Channel;
  149. l2cap: L2CAP;
  150. link: HCI.Link;
  151. psm-, mtu: LONGINT;
  152. sid-, did-: LONGINT; (** CIDs (local & remote) (channel identifier, range: 00040H..0FFFFH) *)
  153. state-: LONGINT; (* channel state (Closed...W2L2CADisconnectRsp) *)
  154. t: Objects.Timer;
  155. reply, timeout: BOOLEAN;
  156. (*
  157. readers: LONGINT;
  158. readerData: Packet;
  159. *)
  160. packetBuffer: PacketBuffer;
  161. PROCEDURE &Init*(l2cap: L2CAP; link: HCI.Link; cid: LONGINT);
  162. BEGIN
  163. IF TraceChannel THEN
  164. KernelLog.String(ModuleName);
  165. KernelLog.String("Channel.Init: ...");
  166. KernelLog.Ln
  167. END;
  168. SELF.l2cap := l2cap; SELF.link := link; sid := cid; state := Closed; mtu := l2cap.aclMTU;
  169. (*readers := 0; readerData := NIL;*)
  170. NEW(packetBuffer, MaxPacketQueue);
  171. NEW(t); reply := FALSE; timeout := FALSE;
  172. IF TraceChannel THEN
  173. KernelLog.String(ModuleName);
  174. KernelLog.String("Channel.Init: done. CID = "); KernelLog.Int(sid,0);
  175. KernelLog.Ln
  176. END;
  177. END Init;
  178. PROCEDURE Close;
  179. BEGIN {EXCLUSIVE}
  180. IF TraceChannel THEN
  181. KernelLog.String(ModuleName);
  182. KernelLog.String("Channel.Close: ... CID = "); KernelLog.Int(sid,0);
  183. KernelLog.Ln;
  184. END;
  185. packetBuffer.Close();
  186. state := Closed;
  187. IF TraceChannel THEN
  188. KernelLog.String(ModuleName);
  189. KernelLog.String("Channel.Close: done. CID = "); KernelLog.Int(sid,0);
  190. KernelLog.Ln;
  191. END;
  192. END Close;
  193. PROCEDURE Timeout;
  194. BEGIN {EXCLUSIVE}
  195. timeout := TRUE
  196. END Timeout;
  197. PROCEDURE SetRTXTimer(ms: LONGINT);
  198. BEGIN
  199. Objects.SetTimeout(t, Timeout, ms)
  200. END SetRTXTimer;
  201. PROCEDURE Connect(psm: LONGINT; VAR status: LONGINT): WORD;
  202. VAR
  203. cmd: ARRAY 8 OF CHAR;
  204. ofs, n: LONGINT; res: WORD;
  205. tmp: LONGINT;
  206. sc: SignallingChannel;
  207. identifier: CHAR;
  208. response: Response;
  209. BEGIN {EXCLUSIVE}
  210. ASSERT(state = Closed);
  211. IF TraceChannel THEN
  212. KernelLog.String(ModuleName);
  213. KernelLog.String("Channel.Connect (CID = "); KernelLog.Int(sid,0); KernelLog.String(") ...");
  214. KernelLog.Ln
  215. END;
  216. sc := l2cap.channelManager.GetSignallingChannel();
  217. ASSERT(sc # NIL);
  218. (* send connection request (first 4 bytes must be left free) *)
  219. cmd[4] := CHR(psm MOD 100H); cmd[5] := CHR(psm DIV 100H); (* PSM *)
  220. cmd[6] := CHR(sid MOD 100H); cmd[7] := CHR(sid DIV 100H); (* CID *)
  221. identifier := sc.GetIdentifier();
  222. state := W4L2CAConnectRsp;
  223. n := 0;
  224. REPEAT
  225. INC(n);
  226. IF TraceChannel THEN
  227. KernelLog.String(ModuleName);
  228. KernelLog.String("Channel.Connect: req #"); KernelLog.Int(n,0);
  229. KernelLog.String(" psm= "); KernelLog.Hex(psm,-2);
  230. KernelLog.String(" source CID= "); KernelLog.Hex(sid,-2);
  231. KernelLog.Ln;
  232. END;
  233. res := sc.Signal(link, sigConnectionReq, identifier, cmd, 4);
  234. IF TraceChannel THEN
  235. KernelLog.String(ModuleName);
  236. KernelLog.String("Channel.Connect: request send, waiting for reply...");
  237. KernelLog.Ln;
  238. END;
  239. sc.WaitForReply(identifier, n*RTXTimeout, response)
  240. UNTIL ((response # NIL) OR (n = MaxTries) OR (state = Closed));
  241. IF (response # NIL) THEN
  242. IF (response.code = sigConnectionResp) THEN
  243. ofs := response.ofs;
  244. did := ORD(response.data[ofs]) + LONG(ORD(response.data[ofs+1]))*100H;
  245. tmp := ORD(response.data[ofs+2])+LONG(ORD(response.data[ofs+3]))*100H;
  246. IF (sid # tmp) THEN
  247. KernelLog.String(ModuleName);
  248. KernelLog.String("Channel.Connect: Warning! Wrong SID in connect response: sid = "); KernelLog.Hex(sid, 0);
  249. KernelLog.String("; got "); KernelLog.Hex(tmp, 0); KernelLog.Ln;
  250. KernelLog.String(" did = "); KernelLog.Hex(did, 0); KernelLog.Ln
  251. END;
  252. res := ORD(response.data[ofs+4])+LONG(ORD(response.data[ofs+5]))*100H;
  253. IF (res = 0001H) THEN (* result = Pending *)
  254. status := ORD(response.data[ofs+6])+LONG(ORD(response.data[ofs+7]))*100H
  255. ELSE
  256. status := 0;
  257. END;
  258. state := Config; (* TODO: check!!! *)
  259. IF TraceChannel THEN
  260. KernelLog.String(ModuleName);
  261. KernelLog.String("Channel.Connect: done.");
  262. KernelLog.String(" destination CID= "); KernelLog.Hex(did, -2);
  263. KernelLog.String(" source CID= "); KernelLog.Hex(sid, -2);
  264. KernelLog.String(" result= "); KernelLog.Hex(res,-2);
  265. KernelLog.String(" status= "); KernelLog.Hex(status,-2);
  266. KernelLog.Ln;
  267. END;
  268. RETURN res
  269. ELSE
  270. KernelLog.String(ModuleName);
  271. KernelLog.String("Channel.Connect: connection request failed (wrong response)");
  272. KernelLog.Ln;
  273. RETURN Error
  274. END
  275. ELSE (* timeout *)
  276. KernelLog.String(ModuleName);
  277. KernelLog.String("Channel.Connect: connection request failed (no response or channel closed)");
  278. KernelLog.Ln;
  279. state := Closed; packetBuffer.Close;
  280. RETURN Error
  281. END
  282. END Connect;
  283. PROCEDURE ConnectResponse(identifier: CHAR; response, status: LONGINT): WORD;
  284. VAR cmd: ARRAY 12 OF CHAR; res: WORD; sc: SignallingChannel;
  285. BEGIN {EXCLUSIVE}
  286. ASSERT(state = W4L2CAConnectRsp);
  287. IF TraceChannel THEN
  288. KernelLog.String(ModuleName);
  289. KernelLog.String("Channel.ConnectResponse: sid = "); KernelLog.Hex(sid, 0); KernelLog.String("; did = "); KernelLog.Hex(did, 0); KernelLog.Ln
  290. END;
  291. sc := l2cap.channelManager.GetSignallingChannel();
  292. ASSERT(sc # NIL);
  293. IF TraceChannel THEN
  294. KernelLog.String(" sending connection request on signalling channel"); KernelLog.Ln;
  295. KernelLog.String(" sid = "); KernelLog.Hex(sid, 0); KernelLog.String("; did = "); KernelLog.Hex(did, 0); KernelLog.Ln
  296. END;
  297. (* send connection response (first 4 bytes must be left free) *)
  298. cmd[4] := CHR(sid MOD 100H); cmd[5] := CHR(sid DIV 100H); (* our cid (remote CID viewed from the remote side) *)
  299. cmd[6] := CHR(did MOD 100H); cmd[7] := CHR(did DIV 100H); (* remote cid (local CID viewed from the remote side) *)
  300. cmd[8] := CHR(response MOD 100H); cmd[9] := CHR(response DIV 100H); (* response code *)
  301. cmd[10] := CHR(status MOD 100H); cmd[11] := CHR(status DIV 100H); (* status code *)
  302. res := sc.Signal(link, sigConnectionResp, identifier, cmd, 8);
  303. IF (res = 0) THEN state := Config
  304. ELSE state := Closed; packetBuffer.Close
  305. END;
  306. IF TraceChannel THEN KernelLog.String(" connection response sent."); KernelLog.Ln END;
  307. RETURN res
  308. END ConnectResponse;
  309. PROCEDURE Configure(VAR inMTU, outFlow, outFlushTO: LONGINT; linkTO: LONGINT): WORD;
  310. (* linkTO is not used!! mazda *)
  311. VAR
  312. cmd: ARRAY 48 OF CHAR;
  313. ofs, pos, n, value: LONGINT; res: WORD;
  314. tmp: LONGINT;
  315. sc: SignallingChannel; identifier, type: CHAR;
  316. response: Response;
  317. BEGIN
  318. IF TraceChannel THEN
  319. KernelLog.String(ModuleName);
  320. KernelLog.String("Channel.Configure (CID = "); KernelLog.Int(sid,0); KernelLog.String(") ...");
  321. KernelLog.Ln
  322. END;
  323. sc := l2cap.channelManager.GetSignallingChannel();
  324. ASSERT(sc # NIL);
  325. IF TraceChannel THEN
  326. KernelLog.String(ModuleName);
  327. KernelLog.String("Channel.Configure: sending configuration request. ");
  328. KernelLog.Ln;
  329. END;
  330. (* send configuration request (first 4 bytes must be left free) *)
  331. cmd[4] := CHR(did MOD 100H); cmd[5] := CHR(did DIV 100H); (* remote CID *)
  332. cmd[6] := 0X; cmd[7] := 0X; (* flags (no continuation packet) *)
  333. pos := 8;
  334. PutOption(optMTU, inMTU, cmd, pos);
  335. PutOption(optFlushTO, outFlushTO, cmd, pos);
  336. PutOption(optQoS, outFlow, cmd, pos);
  337. identifier := sc.GetIdentifier();
  338. n := 0;
  339. REPEAT
  340. INC(n);
  341. IF TraceChannel THEN
  342. KernelLog.String(ModuleName);
  343. KernelLog.String("Channel.Configure: req #"); KernelLog.Int(n,0);
  344. KernelLog.Ln;
  345. END;
  346. res := sc.Signal(link, sigConfigureReq, identifier, cmd, pos-4); (* pos includes the 4 header bytes *)
  347. IF TraceChannel THEN
  348. KernelLog.String(ModuleName);
  349. KernelLog.String("Channel.Configure: request send, waiting for reply...");
  350. KernelLog.Ln
  351. END;
  352. sc.WaitForReply(identifier, n*RTXTimeout, response)
  353. UNTIL (response # NIL) OR (n = MaxTries);
  354. IF (response # NIL) THEN
  355. IF (response.code = sigConfigureResp) THEN
  356. ofs := response.ofs;
  357. tmp := ORD(response.data[ofs])+LONG(ORD(response.data[ofs+1]))*100H;
  358. IF (sid # tmp) THEN
  359. KernelLog.String("Warning: wrong SID in connect response: sid = "); KernelLog.Hex(sid, 0);
  360. KernelLog.String("; got "); KernelLog.Hex(tmp, 0); KernelLog.Ln;
  361. KernelLog.String(" did = "); KernelLog.Hex(did, 0); KernelLog.Ln
  362. END;
  363. IF (response.data[ofs+2] # 0X) OR (response.data[ofs+3] # 0X) THEN
  364. KernelLog.String("Warning: continuation flag set; not supported!"); KernelLog.Ln
  365. END;
  366. res := ORD(response.data[ofs+4])+LONG(ORD(response.data[ofs+5]))*100H;
  367. pos := ofs+6;
  368. WHILE (pos < response.length) & (type # 0FFX) DO
  369. GetOption(response.data^, pos, type, value);
  370. CASE type OF
  371. | optMTU: inMTU := value; mtu := value
  372. | optFlushTO: outFlushTO := value
  373. ELSE
  374. END
  375. END;
  376. IF TraceChannel THEN
  377. KernelLog.String(ModuleName);
  378. KernelLog.String("Channel.Configure: done. ");
  379. KernelLog.Ln
  380. END;
  381. state := Open; (* TODO: check config values *)
  382. RETURN 0
  383. ELSE
  384. IF TraceChannel THEN
  385. KernelLog.String(ModuleName);
  386. KernelLog.String("Channel.Configure: failed (wrong reply code "); KernelLog.Hex(ORD(response.code), -2);
  387. KernelLog.Char(")"); KernelLog.Ln
  388. END;
  389. RETURN 2 (* unacceptable parameters *)
  390. END
  391. ELSE (* timeout *)
  392. IF TraceChannel THEN
  393. KernelLog.String(ModuleName);
  394. KernelLog.String("Channel.Configure: failed (no response)"); KernelLog.Ln;
  395. END;
  396. state := Closed; packetBuffer.Close;
  397. RETURN Error
  398. END
  399. END Configure;
  400. PROCEDURE ConfigurationResponse(identifier: CHAR; outMTU, inFlow: LONGINT): WORD;
  401. VAR
  402. cmd: ARRAY 48 OF CHAR;
  403. pos: LONGINT; res: WORD;
  404. sc: SignallingChannel;
  405. BEGIN
  406. ASSERT((state = Config) OR (state = Open));
  407. IF TraceChannel THEN
  408. KernelLog.String(ModuleName);
  409. KernelLog.String("Channel.ConfigurationResponse (CID = "); KernelLog.Int(sid,0); KernelLog.String(") ...");
  410. KernelLog.Ln
  411. END;
  412. sc := l2cap.channelManager.GetSignallingChannel();
  413. ASSERT(sc # NIL);
  414. (* send configuration response (first 4 bytes must be left free) *)
  415. cmd[4] := CHR(did MOD 100H); cmd[5] := CHR(did DIV 100H); (* remote cid (local CID viewed from the remote side) *)
  416. cmd[6] := 00X; cmd[7] := 00X; (* flags (no continuation packet) *)
  417. cmd[8] := 00X; cmd[9] := 00X; (* result = 0... *)
  418. pos := 10;
  419. IF (outMTU > 0) THEN PutOption(optMTU, outMTU, cmd, pos) END;
  420. IF (inFlow > 0) THEN PutOption(optQoS, inFlow, cmd, pos) END;
  421. IF TraceChannel THEN
  422. KernelLog.String(ModuleName);
  423. KernelLog.String("Channel.ConfigurationResponse: sending response on signalling channel"); KernelLog.Ln;
  424. KernelLog.String(" Source CID = "); KernelLog.Hex(did, 0);
  425. KernelLog.String(" Flags = 0");
  426. KernelLog.String(" Result = 0");
  427. KernelLog.String(" Config = -");
  428. KernelLog.Ln
  429. END;
  430. res := sc.Signal(link, sigConfigureResp, identifier, cmd, pos-4); (* pos includes the 4 header bytes *)
  431. IF (res = 0) THEN
  432. state := Open
  433. ELSE
  434. state := Closed;
  435. packetBuffer.Close
  436. END;
  437. IF TraceChannel THEN
  438. KernelLog.String(ModuleName);
  439. KernelLog.String("Channel.ConfigurationResponse: done. res = "); KernelLog.Int(res,0);
  440. KernelLog.Ln
  441. END;
  442. RETURN res
  443. END ConfigurationResponse;
  444. PROCEDURE Disconnect(): LONGINT;
  445. VAR
  446. sc: SignallingChannel;
  447. cmd: ARRAY 8 OF CHAR;
  448. identifier: CHAR;
  449. response: Response;
  450. ofs, rsid, rdid: LONGINT; res: WORD;
  451. BEGIN
  452. IF state = Closed THEN
  453. IF TraceChannel THEN
  454. KernelLog.String(ModuleName);
  455. KernelLog.String("Disconnect: channel already closed"); KernelLog.Ln END;
  456. RETURN 0
  457. END;
  458. ASSERT((state = Config) OR (state = Open));
  459. IF TraceChannel THEN
  460. KernelLog.String(ModuleName);
  461. KernelLog.String("Channel.Disconnect: sid = "); KernelLog.Hex(sid, -2); KernelLog.String("; did = "); KernelLog.Hex(did, -2);
  462. KernelLog.Ln
  463. END;
  464. sc := l2cap.channelManager.GetSignallingChannel();
  465. ASSERT(sc # NIL);
  466. IF TraceChannel THEN
  467. KernelLog.String(ModuleName);
  468. KernelLog.String(" sending disconnection request on signalling channel"); KernelLog.Ln
  469. END;
  470. (* send disconnection request (first 4 bytes must be left free) *)
  471. cmd[4] := CHR(did MOD 100H); cmd[5] := CHR(did DIV 100H); (* remote CID *)
  472. cmd[6] := CHR(sid MOD 100H); cmd[7] := CHR(sid DIV 100H); (* CID *)
  473. identifier := sc.GetIdentifier();
  474. state := W4L2CADisconnectRsp;
  475. res := sc.Signal(link, sigDisconnectionReq, identifier, cmd, 4);
  476. sc.WaitForReply(identifier, RTXTimeout, response);
  477. (*state := Closed; packetBuffer.Close;*)
  478. Close();
  479. IF (response # NIL) THEN
  480. IF (response.code = sigDisconnectionResp) THEN
  481. ofs := response.ofs;
  482. rdid := ORD(response.data[ofs])+LONG(ORD(response.data[ofs+1]))*100H;
  483. rsid := ORD(response.data[ofs+2])+LONG(ORD(response.data[ofs+3]))*100H;
  484. IF (sid = rsid) & (did = rdid) THEN
  485. RETURN 0 (* ok *)
  486. ELSE
  487. KernelLog.String(ModuleName);
  488. KernelLog.String("Channel.Disconnect: error: sid # rsid or did # rdid");
  489. KernelLog.Ln;
  490. END;
  491. ELSE
  492. KernelLog.String(ModuleName);
  493. KernelLog.String("Channel.Disconnect: error: wrong response.code");
  494. KernelLog.Ln;
  495. END;
  496. ELSE
  497. KernelLog.String(ModuleName);
  498. KernelLog.String("Channel.Disconnect: error: response = NIL");
  499. KernelLog.Ln;
  500. END;
  501. RETURN 0EEEEH (* disconnection timeout *)
  502. END Disconnect;
  503. (** sends an L2CAP packet over ACL *)
  504. PROCEDURE Send(VAR data: ARRAY OF CHAR; ofs, len: LONGINT): WORD;
  505. VAR
  506. hdr: ARRAY 4 OF CHAR;
  507. count: LONGINT; res: WORD;
  508. BEGIN {EXCLUSIVE}
  509. IF TraceChannel THEN
  510. KernelLog.String(ModuleName);
  511. KernelLog.String("Channel.Send (CID = "); KernelLog.Int(sid,0); KernelLog.String(") ...");
  512. KernelLog.Ln
  513. END;
  514. ASSERT((0 <= len) & (len < 10000H));
  515. hdr[0] := CHR(len MOD 100H); hdr[1] := CHR(len DIV 100H);
  516. hdr[2] := CHR(did MOD 100H); hdr[3] := CHR(did DIV 100H);
  517. count := Min(Bluetooth.MaxACLDataLen - 4, len); (* Min(l2cap.aclMTU - 4, len); *)
  518. IF TraceChannel THEN
  519. KernelLog.String(ModuleName);
  520. KernelLog.String("Channel.Send: first packet (payload: "); KernelLog.Int(count, 0); KernelLog.String(" bytes)");
  521. KernelLog.Ln
  522. END;
  523. res := link.SendACLH(HCI.pbfFirst, HCI.bfPointToPoint, hdr, 4, data, ofs, count);
  524. IF (res # 0) THEN
  525. RETURN res
  526. END;
  527. DEC(len, count); INC(ofs, count);
  528. WHILE (len > 0) DO
  529. count := Min(Bluetooth.MaxACLDataLen, len); (* Min(l2cap.aclMTU, len); *)
  530. IF TraceChannel THEN
  531. KernelLog.String(ModuleName);
  532. KernelLog.String("Channel.Send: continuing packet (payload: "); KernelLog.Int(count, 0); KernelLog.String(" bytes)");
  533. KernelLog.Ln
  534. END;
  535. res := link.SendACL(HCI.pbfContinuing, HCI.bfPointToPoint, data, ofs, count);
  536. IF (res # 0) THEN RETURN res END;
  537. DEC(len, count); INC(ofs, count)
  538. END;
  539. IF TraceChannel THEN
  540. KernelLog.String(ModuleName);
  541. KernelLog.String("Channel.Send: done.");
  542. KernelLog.Ln
  543. END;
  544. RETURN res
  545. END Send;
  546. (* receive an L2CAP packet *)
  547. PROCEDURE Receive(p: Packet);
  548. BEGIN (*{EXCLUSIVE}*)
  549. IF TraceChannel THEN
  550. KernelLog.String(ModuleName);
  551. KernelLog.String("Channel.Receive: (CID = "); KernelLog.Int(sid,0); KernelLog.String(") ...");
  552. KernelLog.Ln
  553. END;
  554. (*
  555. IF (readers > 0) THEN (* if no readers are available, drop the data *)
  556. IF TraceRead THEN
  557. KernelLog.String("Channel "); KernelLog.Hex(sid, 0); KernelLog.String(": received data!"); KernelLog.Ln
  558. END;
  559. readerData := p
  560. ELSE
  561. KernelLog.String("Warning: channel "); KernelLog.Hex(sid, 0); KernelLog.String(" is dropping data"); KernelLog.Ln
  562. END
  563. *)
  564. packetBuffer.Append(p);
  565. IF TraceChannel THEN
  566. KernelLog.String(ModuleName);
  567. KernelLog.String("Channel.Receive: done.");
  568. KernelLog.Ln
  569. END;
  570. END Receive;
  571. PROCEDURE Write*(VAR buffer: ARRAY OF CHAR; ofs, len: LONGINT; VAR size: LONGINT): WORD;
  572. VAR
  573. res: WORD;
  574. BEGIN
  575. IF TraceChannel THEN
  576. KernelLog.String(ModuleName);
  577. KernelLog.String("Channel.Write: (CID = "); KernelLog.Hex(sid,-2);
  578. KernelLog.String(" mtu = "); KernelLog.Int(mtu,0);
  579. KernelLog.String(") ...");
  580. KernelLog.Ln;
  581. END;
  582. IF mtu = 0 THEN
  583. KernelLog.Ln; KernelLog.Ln; KernelLog.String("**** Warning: MTU = 0 ****"); KernelLog.Ln; KernelLog.Ln; KernelLog.Ln;
  584. mtu := 1000H
  585. END;
  586. len := Min(len, mtu);
  587. res := Send(buffer, ofs, len);
  588. IF (res = 0) THEN
  589. size := len
  590. ELSE
  591. size := 0
  592. END;
  593. IF TraceChannel THEN
  594. KernelLog.String(ModuleName);
  595. KernelLog.String("Channel.Write: done.");
  596. KernelLog.Ln
  597. END;
  598. RETURN res
  599. END Write;
  600. PROCEDURE Read*(VAR buffer: ARRAY OF CHAR; min: LONGINT; VAR size: LONGINT): LONGINT;
  601. VAR i: LONGINT;
  602. p: Packet;
  603. BEGIN (*{EXCLUSIVE}*)
  604. (*INC(readers);*)
  605. size := 0;
  606. (*WHILE (size < min) & (state = Open) DO*)
  607. IF TraceChannel THEN
  608. KernelLog.String(ModuleName);
  609. KernelLog.String("Channel.Read: (CID = "); KernelLog.Hex(sid,-2); KernelLog.String(") ...");
  610. KernelLog.Ln;
  611. END;
  612. (*AWAIT((readerData # NIL) OR (state # Open));
  613. IF (readerData # NIL) & (state = Open) THEN*)
  614. (*
  615. IF TraceChannel THEN
  616. KernelLog.String("Channel.Read (cid"); KernelLog.Hex(sid, 0); KernelLog.String("): got data"); KernelLog.Ln;
  617. KernelLog.String(" pos = "); KernelLog.Int(size, 0);
  618. (*KernelLog.String("; readerData.len = "); KernelLog.Int(readerData.len, 0); *)
  619. KernelLog.String("; min = "); KernelLog.Int(min, 0); KernelLog.Ln
  620. END;
  621. *)
  622. (*
  623. FOR i := 0 TO Min(readerData.len, min-size)-1 DO
  624. buffer[size] := readerData.data[i]; INC(size)
  625. END;
  626. readerData := NIL
  627. *)
  628. p := packetBuffer.Remove();
  629. IF ~packetBuffer.closed THEN
  630. size := p.len;
  631. FOR i := 0 TO size-1 DO
  632. buffer[i] := p.data[i]
  633. END
  634. ELSE
  635. size := 0
  636. END
  637. (*ELSIF TraceRead THEN
  638. KernelLog.String("Channel.Read (cid"); KernelLog.Hex(sid, 0); KernelLog.String("): failed to get data"); KernelLog.Ln
  639. END*);
  640. (*END;*)
  641. (*DEC(readers);*)
  642. IF (state = Open) THEN
  643. IF TraceChannel THEN
  644. KernelLog.String(ModuleName);
  645. KernelLog.String("Channel.Read: (CID = "); KernelLog.Hex(sid, -2); KernelLog.String(") done.");
  646. KernelLog.Ln;
  647. END;
  648. RETURN 0
  649. ELSE
  650. IF TraceChannel THEN
  651. KernelLog.String("Channel.Read (CID = "); KernelLog.Hex(sid, -2); KernelLog.String("): returning failure!"); KernelLog.Ln END;
  652. RETURN 1
  653. END
  654. END Read;
  655. END Channel;
  656. (* ----------------------------------------------------------------------------------------- *)
  657. (* packet type for a signalling *)
  658. SignalPacket = POINTER TO RECORD
  659. link: HCI.Link; (* signal comes from this link *)
  660. code: CHAR;
  661. identifier: CHAR;
  662. length: LONGINT;
  663. data: PChar;
  664. ofs: LONGINT;
  665. END;
  666. Request = POINTER TO RECORD(SignalPacket) (* code one of sig*Req *)
  667. next: Request;
  668. END;
  669. Response = POINTER TO RECORD(SignalPacket) (* code one of sig*Resp *)
  670. END;
  671. (* signalling channel (cid 0001H) *)
  672. SignallingChannel = OBJECT(Channel)
  673. VAR
  674. dead: BOOLEAN;
  675. identifier: CHAR;
  676. timeout: Bluetooth.IDTimer;
  677. response: Response;
  678. firstReq, lastReq: Request;
  679. PROCEDURE &Init*(l2cap: L2CAP; link: HCI.Link; cid: LONGINT);
  680. BEGIN
  681. IF TraceSignallingChannel THEN
  682. KernelLog.String(ModuleName);
  683. KernelLog.String("SignallingChannel.Init: ... ");
  684. KernelLog.Ln
  685. END;
  686. Init^(l2cap, link, cid); sid := 1; did := 1;
  687. IF TraceSignallingChannel THEN
  688. KernelLog.String(ModuleName);
  689. KernelLog.String("SignallingChannel.Init: done.");
  690. KernelLog.Ln
  691. END;
  692. END Init;
  693. PROCEDURE Close;
  694. BEGIN {EXCLUSIVE}
  695. IF TraceSignallingChannel THEN
  696. KernelLog.String(ModuleName);
  697. KernelLog.String("SignallingChannel.Close: ...");
  698. KernelLog.Ln;
  699. END;
  700. dead := TRUE;
  701. IF TraceSignallingChannel THEN
  702. KernelLog.String(ModuleName);
  703. KernelLog.String("SignallingChannel.Close: done.");
  704. KernelLog.Ln;
  705. END;
  706. END Close;
  707. (* return the next identifier (c.f. SignalPacket.identifier) *)
  708. PROCEDURE GetIdentifier(): CHAR;
  709. VAR c: CHAR;
  710. BEGIN {EXCLUSIVE}
  711. c := identifier;
  712. identifier := CHR((ORD(identifier)+1) MOD 100H);
  713. RETURN c
  714. END GetIdentifier;
  715. (* signal an remote L2CAP entity using link *)
  716. (* LEN(command) must be >= 4 and the first 4 bytes of command MUST be left free *)
  717. PROCEDURE Signal(link: HCI.Link; code, identifier: CHAR; command: ARRAY OF CHAR; len: LONGINT): WORD;
  718. VAR
  719. res : WORD;
  720. BEGIN (* {EXCLUSIVE} TODO *)
  721. IF TraceSignallingChannel THEN
  722. KernelLog.String(ModuleName);
  723. KernelLog.String("SignallingChannel.Signal: command code = "); KernelLog.Hex(ORD(code), -2);
  724. KernelLog.String("; identifier = "); KernelLog.Hex(ORD(identifier), -2);
  725. KernelLog.String("; length = "); KernelLog.Int(len, 0); KernelLog.String(" ... ");
  726. KernelLog.Ln
  727. END;
  728. ASSERT((LEN(command) >= 4) & (command[0] = 0X) & (command[1] = 0X) & (command[2] = 0X) & (command[3] = 0X));
  729. ASSERT((0 <= len) & (len < 1000H));
  730. command[0] := code; command[1] := identifier;
  731. command[2] := CHR(len MOD 100H); command[3] := CHR(len DIV 100H);
  732. SELF.link := link;
  733. (*
  734. IF TraceSignallingChannel THEN
  735. KernelLog.String(ModuleName);
  736. KernelLog.String("SignallingChannel.Signal: sending command:");
  737. KernelLog.Ln;
  738. FOR i:=0 TO len+4-1 DO
  739. KernelLog.Hex(ORD(command[i]),-2); KernelLog.String(" ");
  740. END;
  741. KernelLog.Ln;
  742. END;
  743. *)
  744. res := Send(command,0,len+4);
  745. IF TraceSignallingChannel THEN
  746. KernelLog.String(ModuleName);
  747. KernelLog.String("SignallingChannel.Signal: done.");
  748. KernelLog.Ln
  749. END;
  750. RETURN res;
  751. END Signal;
  752. (* receive and parse a signalling packet *)
  753. PROCEDURE Receive(p: Packet);
  754. VAR
  755. pos: LONGINT; res: WORD;
  756. c: CHAR;
  757. s: SignalPacket;
  758. request: Request;
  759. reply: ARRAY 8 OF CHAR;
  760. ch: Channel;
  761. BEGIN
  762. IF TraceSignallingChannel THEN
  763. KernelLog.String(ModuleName);
  764. KernelLog.String("SignallingChannel.Receive ... ");
  765. KernelLog.Ln
  766. END;
  767. pos := 0;
  768. WHILE (pos < p.len) DO
  769. c := p.data[pos];
  770. IF (c = sigConnectionReq) OR (c = sigConfigureReq) OR
  771. (c = sigDisconnectionReq) OR (c = sigEchoReq) OR (c = sigInformationReq)
  772. THEN
  773. NEW(request); s := request
  774. ELSIF (c = sigConnectionResp) OR (c = sigConfigureResp) OR (c = sigDisconnectionResp) OR
  775. (c = sigEchoResp) OR (c = sigInformationResp) OR (c = sigCommandReject)
  776. THEN
  777. NEW(response); s := response
  778. ELSE
  779. (* hmmm....this is not good *)
  780. KernelLog.String(ModuleName);
  781. KernelLog.String("SignallingChannel.Receive: invalid command ("); KernelLog.Hex(ORD(c),-2); KernelLog.String("X)");
  782. KernelLog.Ln;
  783. RETURN
  784. END;
  785. s.link := p.link;
  786. s.code := c;
  787. s.identifier := p.data[pos+1];
  788. s.length := ORD(p.data[pos+2])+LONG(ORD(p.data[pos+3]))*100H;
  789. s.data := p.data;
  790. s.ofs := pos + 4;
  791. IF TraceSignallingChannel THEN
  792. KernelLog.String(ModuleName);
  793. KernelLog.String("SignallingChannel.Receive: command code = "); KernelLog.Hex(ORD(s.code), -2);
  794. KernelLog.String(" identifier = "); KernelLog.Hex(ORD(p.data[pos+1]), -2);
  795. KernelLog.Ln;
  796. (*
  797. FOR i:=0 TO p.len-1 DO
  798. KernelLog.Hex(ORD(p.data[i]),-2); KernelLog.String(" ");
  799. END;
  800. KernelLog.Ln;
  801. *)
  802. END;
  803. IF (s IS Response) THEN
  804. BEGIN {EXCLUSIVE}
  805. (* this will activate the one process waiting for this identifier, or if not process is waiting, drop it *)
  806. IF TraceSignallingChannel THEN
  807. KernelLog.String(ModuleName);
  808. KernelLog.String("SignallingChannel.Receive: {EXCLUSIVE} got response, setting identifier (");
  809. KernelLog.Int(ORD(p.data[pos+1]),0); KernelLog.String(") ...");
  810. KernelLog.Ln
  811. END;
  812. response.identifier := p.data[pos+1];
  813. IF TraceSignallingChannel THEN
  814. KernelLog.String(ModuleName);
  815. KernelLog.String("SignallingChannel.Receive: {EXCLUSIVE} identifier set.");
  816. KernelLog.Ln
  817. END;
  818. END
  819. ELSE (* s IS Request *)
  820. ASSERT(s IS Request);
  821. (* reply to Echo and Information requests, queue other requests *)
  822. IF (request.code = sigEchoReq) THEN
  823. IF TraceSignallingChannel THEN
  824. KernelLog.String(ModuleName);
  825. KernelLog.String("SignallingChannel.Receive: got echo request, sending echo reply");
  826. KernelLog.Ln
  827. END;
  828. res := Signal(request.link, sigEchoResp, request.identifier, reply, 0) (* ignore result *)
  829. ELSIF (request.code = sigInformationReq) THEN
  830. IF TraceSignallingChannel THEN
  831. KernelLog.String(ModuleName);
  832. KernelLog.String("SignallingChannel.Receive: got information request, sending information reply");
  833. KernelLog.Ln
  834. END;
  835. reply[4] := request.data[request.ofs]; reply[5] := request.data[request.ofs+1]; (* InfoType: same as request *)
  836. reply[6] := 01X; reply[7] := 00X; (* not supported *)
  837. res := Signal(request.link, sigInformationResp, request.identifier, reply, 4) (* ignore result *)
  838. ELSE
  839. IF (request.code = sigDisconnectionReq) THEN
  840. IF TraceSignallingChannel THEN
  841. KernelLog.String(ModuleName);
  842. KernelLog.String("SignallingChannel.Receive: got disconnection request, sending disconnection reply"); KernelLog.Ln
  843. END;
  844. ch := l2cap.channelManager.FindChannel(ORD(request.data[request.ofs])+LONG(ORD(request.data[request.ofs+1]))*100H);
  845. IF (ch # NIL) THEN
  846. ch.state := Closed; ch.packetBuffer.Close;
  847. reply[4] := request.data[request.ofs+2]; reply[5] := request.data[request.ofs+3];
  848. reply[6] := request.data[request.ofs]; reply[7] := request.data[request.ofs+1];
  849. res := Signal(request.link, sigDisconnectionResp, request.identifier, reply, 4); (* ignore result *)
  850. ELSE request := NIL (* discard request *)
  851. END
  852. END;
  853. IF (request # NIL) THEN
  854. IF TraceSignallingChannel THEN
  855. KernelLog.String(ModuleName);
  856. KernelLog.String("SignallingChannel.Receive: queueing request..."); KernelLog.Ln
  857. END;
  858. QueueRequest(request);
  859. END;
  860. END;
  861. END; (* s IS Request *)
  862. INC(pos, 4+s.length);
  863. END; (* WHILE *)
  864. IF TraceSignallingChannel THEN
  865. KernelLog.String(ModuleName);
  866. KernelLog.String("SignallingChannel.Receive: done."); KernelLog.Ln
  867. END;
  868. END Receive;
  869. PROCEDURE TimeoutHandler(timer: Bluetooth.IDTimer);
  870. BEGIN {EXCLUSIVE}
  871. timeout := timer
  872. END TimeoutHandler;
  873. (* wait for a reply to a signalling packet with identifier from a remote L2CAP entity *)
  874. PROCEDURE WaitForReply(identifier: CHAR; wait: LONGINT; VAR r: Response);
  875. VAR
  876. idTimer: Bluetooth.IDTimer;
  877. BEGIN {EXCLUSIVE}
  878. IF TraceSignallingChannel THEN
  879. KernelLog.String(ModuleName);
  880. KernelLog.String("SignallingChannel.WaitForReply: {EXCLUSIVE} await (identifier = ");
  881. KernelLog.Int(ORD(identifier),0); KernelLog.String(") ...."); KernelLog.Ln
  882. END;
  883. NEW(idTimer, TimeoutHandler, wait);
  884. AWAIT(((response # NIL) & (response.identifier = identifier)) OR (timeout = idTimer) OR dead);
  885. r := response; response := NIL;
  886. IF TraceSignallingChannel THEN
  887. KernelLog.String(ModuleName);
  888. KernelLog.String("SignallingChannel.WaitForReply: {EXCLUSIVE} done."); KernelLog.Ln
  889. END;
  890. END WaitForReply;
  891. (* request queue for the local L2CAP entity *)
  892. PROCEDURE QueueRequest(request: Request);
  893. BEGIN {EXCLUSIVE}
  894. IF TraceSignallingChannel THEN
  895. KernelLog.String(ModuleName);
  896. KernelLog.String("SignallingChannel.QueueRequest: {EXCLUSIVE} ...."); KernelLog.Ln
  897. END;
  898. IF (lastReq = NIL) THEN firstReq := request; lastReq := request
  899. ELSE lastReq.next := request; lastReq := request
  900. END;
  901. IF TraceSignallingChannel THEN
  902. KernelLog.String(ModuleName);
  903. KernelLog.String("SignallingChannel.QueueRequest: {EXCLUSIVE} done."); KernelLog.Ln
  904. END;
  905. END QueueRequest;
  906. PROCEDURE GetRequest(): Request;
  907. VAR r: Request;
  908. BEGIN {EXCLUSIVE}
  909. IF TraceSignallingChannel THEN
  910. KernelLog.String(ModuleName);
  911. KernelLog.String("SignallingChannel.GetRequest: ...."); KernelLog.Ln;
  912. END;
  913. AWAIT((firstReq # NIL) OR dead);
  914. IF ~dead THEN
  915. r := firstReq; firstReq := firstReq.next;
  916. IF (firstReq = NIL) THEN lastReq := NIL END
  917. END;
  918. IF TraceSignallingChannel THEN
  919. KernelLog.String(ModuleName);
  920. KernelLog.String("SignallingChannel.GetRequest: done."); KernelLog.Ln
  921. END;
  922. RETURN r;
  923. END GetRequest;
  924. END SignallingChannel;
  925. (* ----------------------------------------------------------------------------------------- *)
  926. (* L2CAP data packet reassembly and multiplexing *)
  927. Reassembler = OBJECT
  928. VAR
  929. l2cap: L2CAP;
  930. packet: Packet;
  931. tail:Packet;
  932. pos: LONGINT;
  933. packetList: Packet;
  934. dead: BOOLEAN;
  935. packetListLength : LONGINT;
  936. PROCEDURE &Init*(l2cap: L2CAP);
  937. BEGIN
  938. IF TraceReassembler THEN
  939. KernelLog.String(ModuleName);
  940. KernelLog.String("Reassembler.Init: ...");
  941. KernelLog.Ln
  942. END;
  943. SELF.l2cap := l2cap; packet := NIL; pos := 0; packetList := NIL; dead := FALSE;
  944. tail := NIL; packetListLength := 0;
  945. IF TraceReassembler THEN
  946. KernelLog.String(ModuleName);
  947. KernelLog.String("Reassembler.Init: done.");
  948. KernelLog.Ln
  949. END;
  950. END Init;
  951. PROCEDURE Close;
  952. BEGIN {EXCLUSIVE}
  953. IF TraceReassembler THEN
  954. KernelLog.String(ModuleName);
  955. KernelLog.String("Reassembler.Close: ...");
  956. KernelLog.Ln;
  957. END;
  958. dead := TRUE;
  959. IF TraceReassembler THEN
  960. KernelLog.String(ModuleName);
  961. KernelLog.String("Reassembler.Close: done.");
  962. KernelLog.Ln;
  963. END;
  964. END Close;
  965. (* called by the HCI layer upon reception of an ACL data packet *)
  966. PROCEDURE ReceiveData(link: HCI.Link; acl: Bluetooth.ACLPacket);
  967. VAR i: LONGINT;
  968. BEGIN
  969. IF TraceReassembler THEN
  970. KernelLog.String(ModuleName);
  971. KernelLog.String("Reassembler.ReceiveData (called by the HCI layer [Link.OnReceiveACLData]): ...");
  972. KernelLog.Ln
  973. END;
  974. IF (acl.PB = HCI.pbfFirst) THEN
  975. NEW(packet); packet.link := link;
  976. GetL2CAPHeader(acl.data, packet.cid, packet.len);
  977. NEW(packet.data, packet.len);
  978. pos := 0;
  979. FOR i := 4 TO acl.len-1 DO
  980. packet.data[pos] := acl.data[i];
  981. INC(pos);
  982. END;
  983. IF TraceReassembler THEN
  984. KernelLog.String(ModuleName);
  985. KernelLog.String("Reassembler.ReceiveData: first packet: cid="); KernelLog.Int(packet.cid, 0);
  986. KernelLog.String("; length = "); KernelLog.Int(packet.len, 0); KernelLog.String("; payload received: "); KernelLog.Int(pos, 0);
  987. KernelLog.Ln
  988. END
  989. ELSE (* acl.PB = HCI.pbfContinuing *)
  990. FOR i := 0 TO acl.len-1 DO
  991. packet.data[pos] := acl.data[i];
  992. INC(pos);
  993. END;
  994. IF TraceReassembler THEN
  995. KernelLog.String(ModuleName);
  996. KernelLog.String("Reassembler.ReceiveData: continuing packet: cid="); KernelLog.Int(packet.cid, 0);
  997. KernelLog.String("; length = "); KernelLog.Int(packet.len, 0); KernelLog.String("; payload received: "); KernelLog.Int(pos, 0);
  998. KernelLog.Ln
  999. END
  1000. END;
  1001. IF (packet.len <= pos) THEN (* complete *)
  1002. IF TraceReassembler THEN
  1003. KernelLog.String(ModuleName);
  1004. KernelLog.String("Reassembler.ReceiveData: packet complete");
  1005. KernelLog.Ln
  1006. END;
  1007. AddPacket(packet)
  1008. END;
  1009. IF TraceReassembler THEN
  1010. KernelLog.String(ModuleName);
  1011. KernelLog.String("Reassembler.ReceiveData: done.");
  1012. KernelLog.String("(pos = "); KernelLog.Int(pos,0);
  1013. KernelLog.String("; packet.len = "); KernelLog.Int(packet.len,0);
  1014. KernelLog.String(")");
  1015. KernelLog.Ln
  1016. END;
  1017. END ReceiveData;
  1018. PROCEDURE AddPacket(p: Packet);
  1019. BEGIN {EXCLUSIVE}
  1020. IF TraceReassembler THEN
  1021. KernelLog.String(ModuleName);
  1022. KernelLog.String("Reassembler.AddPacket: {EXCLUSIVE} .... packetListLength = ");
  1023. KernelLog.Int(packetListLength,0);
  1024. KernelLog.Ln
  1025. END;
  1026. (*
  1027. (* TODO: insert at the end.... *)
  1028. packet.next := packetList; packetList := packet;
  1029. *)
  1030. IF (packetList = NIL) THEN
  1031. p.next := NIL;
  1032. packetList := p;
  1033. tail := p;
  1034. ELSE
  1035. p.next := NIL;
  1036. tail.next := p;
  1037. tail := p;
  1038. END;
  1039. INC(packetListLength);
  1040. IF TraceReassembler THEN
  1041. KernelLog.String(ModuleName);
  1042. KernelLog.String("Reassembler.AddPacket: {EXCLUSIVE} done. packetListLength = ");
  1043. KernelLog.Int(packetListLength,0);
  1044. KernelLog.Ln
  1045. END;
  1046. END AddPacket;
  1047. PROCEDURE GetPacket(): Packet;
  1048. VAR p: Packet;
  1049. BEGIN {EXCLUSIVE}
  1050. IF TraceReassembler THEN
  1051. KernelLog.String(ModuleName);
  1052. KernelLog.String("Reassembler.GetPacket: {EXCLUSIVE} await .... packetListLength = ");
  1053. KernelLog.Int(packetListLength,0);
  1054. KernelLog.Ln
  1055. END;
  1056. AWAIT((packetList # NIL) OR dead);
  1057. IF (packetList # NIL) THEN
  1058. p := packetList; packetList := packetList.next;
  1059. DEC(packetListLength);
  1060. ELSE
  1061. p := NIL
  1062. END;
  1063. IF TraceReassembler THEN
  1064. KernelLog.String(ModuleName);
  1065. KernelLog.String("Reassembler.GetPacket: {EXCLUSIVE} done. packetListLength = ");
  1066. KernelLog.Int(packetListLength,0);
  1067. KernelLog.Ln
  1068. END;
  1069. RETURN p
  1070. END GetPacket;
  1071. (* activity: wait for a (complete) L2CAP packet and send it to the corresponding channel *)
  1072. PROCEDURE Run;
  1073. VAR
  1074. p: Packet; c: Channel;
  1075. BEGIN
  1076. REPEAT
  1077. IF TraceReassembler THEN
  1078. KernelLog.String(ModuleName);
  1079. KernelLog.String("Reassembler.Run: {ACTIVE} waiting for L2CAP packets ... "); KernelLog.Ln;
  1080. END;
  1081. p := GetPacket();
  1082. IF (p # NIL) THEN
  1083. IF TraceReassembler THEN
  1084. KernelLog.String(ModuleName);
  1085. KernelLog.String("Reassembler.Run: {ACTIVE} packet received. Pass it to the receiving channel ...");
  1086. KernelLog.Ln;
  1087. END;
  1088. c := l2cap.channelManager.FindChannel(p.cid);
  1089. IF (c # NIL) THEN
  1090. c.Receive(p);
  1091. ELSE
  1092. IF TraceReassembler THEN
  1093. KernelLog.String(ModuleName);
  1094. KernelLog.String("Reassembler.Run: {ACTIVE} no receiving channel (cid = "); KernelLog.Int(packet.cid, 0); KernelLog.Char(")");
  1095. KernelLog.Ln;
  1096. END
  1097. END;
  1098. END;
  1099. IF TraceReassembler THEN
  1100. KernelLog.String(ModuleName);
  1101. KernelLog.String("Reassembler.Run: {ACTIVE} L2CAP packet processed."); KernelLog.Ln;
  1102. END
  1103. UNTIL dead;
  1104. END Run;
  1105. BEGIN {ACTIVE}
  1106. (*Objects.SetPriority(4);*)
  1107. IF TraceReassembler THEN
  1108. KernelLog.String(ModuleName);
  1109. KernelLog.String("Reassembler: {ACTIVE} ...");
  1110. KernelLog.Ln;
  1111. END;
  1112. Run;
  1113. IF TraceReassembler THEN
  1114. KernelLog.String(ModuleName);
  1115. KernelLog.String("Reassembler: {ACTIVE} done.");
  1116. KernelLog.Ln
  1117. END;
  1118. END Reassembler;
  1119. (* ----------------------------------------------------------------------------------------- *)
  1120. (* manages channels, the CID pool and supports searching for channels with a specific CID *)
  1121. ChannelManager = OBJECT
  1122. VAR
  1123. l2cap: L2CAP;
  1124. channels: Channel;
  1125. numChannels: LONGINT;
  1126. cidPool: ARRAY (MaxCIDs DIV 32) OF SET;
  1127. nextCID: LONGINT;
  1128. PROCEDURE &Init*(l2cap: L2CAP);
  1129. VAR sc: SignallingChannel;
  1130. BEGIN
  1131. IF TraceChannelManager THEN
  1132. KernelLog.String(ModuleName);
  1133. KernelLog.String("ChannelManager.Init: ...");
  1134. KernelLog.Ln
  1135. END;
  1136. SELF.l2cap := l2cap;
  1137. NEW(sc, l2cap, NIL, cidSignalling); (* signalling channel *)
  1138. channels := sc;
  1139. numChannels := 1;
  1140. nextCID := MinCID;
  1141. IF TraceChannelManager THEN
  1142. KernelLog.String(ModuleName);
  1143. KernelLog.String("ChannelManager.Init: done.");
  1144. KernelLog.Ln
  1145. END;
  1146. END Init;
  1147. (* get the next CID *)
  1148. PROCEDURE AllocCID(): LONGINT;
  1149. VAR oldCID: LONGINT;
  1150. BEGIN (* [EXCLUSIVE] *)
  1151. oldCID := nextCID;
  1152. WHILE ((nextCID MOD 32) IN cidPool[nextCID DIV 32]) DO
  1153. nextCID := (nextCID+1) MOD MaxCIDs;
  1154. IF (nextCID = 0) THEN nextCID := MinCID END;
  1155. IF (nextCID = oldCID) THEN RETURN -1 END;
  1156. END;
  1157. INCL(cidPool[nextCID DIV 32], nextCID MOD 32);
  1158. RETURN nextCID
  1159. END AllocCID;
  1160. (* free a CID *)
  1161. PROCEDURE FreeCID(cid: LONGINT);
  1162. BEGIN (* [EXCLUSIVE] *)
  1163. ASSERT((cid MOD 32) IN cidPool[cid DIV 32]);
  1164. EXCL(cidPool[cid DIV 32], cid MOD 32)
  1165. END FreeCID;
  1166. (* reset everything *)
  1167. PROCEDURE Reset;
  1168. VAR i: LONGINT;
  1169. BEGIN {EXCLUSIVE}
  1170. IF TraceChannelManager THEN
  1171. KernelLog.String(ModuleName);
  1172. KernelLog.String("ChannelManager.Reset");
  1173. KernelLog.Ln
  1174. END;
  1175. channels.next := NIL;
  1176. numChannels := 1;
  1177. FOR i := 0 TO (MaxCIDs DIV 32)-1 DO cidPool[i] := {} END;
  1178. nextCID := MinCID
  1179. END Reset;
  1180. (* returns a new channel with a unique CID. 'link' is the link used to send data to the remote channel endpoint *)
  1181. PROCEDURE AddChannel(l2cap: L2CAP; link: HCI.Link): Channel;
  1182. VAR
  1183. c: Channel; cid: LONGINT;
  1184. BEGIN {EXCLUSIVE}
  1185. IF TraceChannelManager THEN
  1186. KernelLog.String(ModuleName);
  1187. KernelLog.String("ChannelManager.AddChannel: {EXCLUSIVE} ...");
  1188. KernelLog.Ln
  1189. END;
  1190. cid := AllocCID();
  1191. IF (cid # -1) THEN
  1192. NEW(c, l2cap, link, cid);
  1193. c.next := channels.next; channels.next := c; INC(numChannels)
  1194. END;
  1195. IF TraceChannelManager THEN
  1196. KernelLog.String(ModuleName);
  1197. KernelLog.String("ChannelManager.AddChannel: {EXCLUSIVE} done. CID = "); KernelLog.Hex(cid,0);
  1198. KernelLog.Ln
  1199. END;
  1200. RETURN c
  1201. END AddChannel;
  1202. (* close a channel *)
  1203. PROCEDURE RemoveChannel(c: Channel);
  1204. VAR p,q: Channel;
  1205. BEGIN {EXCLUSIVE}
  1206. IF TraceChannelManager THEN
  1207. KernelLog.String("{ChannelManager.RemoveChannel: cid = "); KernelLog.Hex(c.sid, 0); KernelLog.Char("}"); KernelLog.Ln
  1208. END;
  1209. p := channels.next; q := channels;
  1210. WHILE (p # NIL) & (p # c) DO q := p; p := p.next END;
  1211. IF (p # NIL) THEN
  1212. FreeCID(p.sid);
  1213. q.next := p.next; DEC(numChannels)
  1214. END
  1215. END RemoveChannel;
  1216. (* find a channel with a specific CID *)
  1217. PROCEDURE FindChannel(cid: LONGINT): Channel;
  1218. VAR c: Channel;
  1219. BEGIN {EXCLUSIVE}
  1220. c := channels;
  1221. WHILE (c # NIL) & (c.sid # cid) DO
  1222. c := c.next
  1223. END;
  1224. RETURN c
  1225. END FindChannel;
  1226. (* get the signalling channel *)
  1227. PROCEDURE GetSignallingChannel(): SignallingChannel;
  1228. VAR c: Channel;
  1229. BEGIN
  1230. c := FindChannel(cidSignalling);
  1231. IF (c # NIL) & (c IS SignallingChannel) THEN RETURN c(SignallingChannel)
  1232. ELSE RETURN NIL
  1233. END
  1234. END GetSignallingChannel;
  1235. END ChannelManager;
  1236. (* handles connection/disconnection events from the HCI layer and can wait for a connection event *)
  1237. HCIManager* = OBJECT
  1238. VAR
  1239. hci : HCI.HCI;
  1240. expiredTimer: Bluetooth.IDTimer;
  1241. newLink: HCI.Link;
  1242. l2caps : L2CAP;
  1243. PROCEDURE &Init*(hci : HCI.HCI);
  1244. BEGIN
  1245. IF TraceHCIManager THEN
  1246. KernelLog.String(ModuleName);
  1247. KernelLog.String("HCIManager.Init: ...");
  1248. KernelLog.Ln
  1249. END;
  1250. SELF.hci := hci;
  1251. hci.OnConnect := Connect;
  1252. hci.OnDisconnect := Disconnect;
  1253. NEW(l2caps); (* dummy head *)
  1254. l2caps.next := NIL;
  1255. IF TraceHCIManager THEN
  1256. KernelLog.String(ModuleName);
  1257. KernelLog.String("HCIManager.Init: done.");
  1258. KernelLog.Ln
  1259. END;
  1260. END Init;
  1261. PROCEDURE CreateACLConnection*(l2cap : L2CAP;bdAddr : Bluetooth.BDAddr;VAR result : WORD);
  1262. VAR link : HCI.Link;
  1263. BEGIN
  1264. result := hci.CreateConnection(bdAddr, 0);
  1265. IF (result # 0) THEN
  1266. IF TraceHCIManager THEN
  1267. KernelLog.String(ModuleName);
  1268. KernelLog.String("HCIManager.CreateACLConnection: hci.CreateConnection failed! res = "); KernelLog.Hex(result, -2);
  1269. KernelLog.Ln;
  1270. END;
  1271. RETURN;
  1272. END;
  1273. link := AwaitACLConnection(bdAddr);
  1274. IF (link = NIL) THEN
  1275. result := 0EEEEH; (* timeout *)
  1276. RETURN;
  1277. END;
  1278. link.OnReceiveACLData := l2cap.reassembler.ReceiveData;
  1279. l2cap.link := link;
  1280. l2cap.next := l2caps.next;
  1281. l2caps.next := l2cap;
  1282. END CreateACLConnection;
  1283. PROCEDURE ReleaseACLConnection*(link:HCI.Link;VAR result:WORD);
  1284. BEGIN
  1285. ASSERT(link # NIL);
  1286. result := hci.Disconnect(link.handle,013H);
  1287. IF (result # 0) THEN
  1288. IF TraceHCIManager THEN
  1289. KernelLog.String(ModuleName);
  1290. KernelLog.String("HCIManager.ReleaseACLConnection: hci.Disconnect failed! res = "); KernelLog.Hex(result, -2);
  1291. KernelLog.Ln;
  1292. END;
  1293. END;
  1294. END ReleaseACLConnection;
  1295. PROCEDURE AcceptACLConnection*(l2cap : L2CAP;bdAddr : Bluetooth.BDAddr;VAR result : WORD);
  1296. VAR link : HCI.Link;
  1297. BEGIN
  1298. link := AwaitACLConnection(bdAddr);
  1299. IF (link = NIL) THEN
  1300. result := 0EEEEH; (* timeout *)
  1301. RETURN;
  1302. END;
  1303. result := 0;
  1304. link.OnReceiveACLData := l2cap.reassembler.ReceiveData;
  1305. l2cap.link := link;
  1306. l2cap.next := l2caps.next;
  1307. l2caps.next := l2cap;
  1308. END AcceptACLConnection;
  1309. (*----- lower layer events -----*)
  1310. PROCEDURE Connect(sender: HCI.HCI; link: HCI.Link; res: WORD);
  1311. BEGIN {EXCLUSIVE}
  1312. IF (res = 0) THEN
  1313. IF TraceHCIManager THEN
  1314. KernelLog.String(ModuleName);
  1315. KernelLog.String("HCIManager.Connect: got a new link. handle = "); KernelLog.Int(link.handle,0);
  1316. KernelLog.Ln
  1317. END;
  1318. newLink := link
  1319. ELSE
  1320. IF TraceHCIManager THEN
  1321. KernelLog.String(ModuleName);
  1322. KernelLog.String("HCIManager.Connect: failed! res = 0x"); KernelLog.Hex(res, -2);
  1323. KernelLog.Ln
  1324. END;
  1325. END;
  1326. END Connect;
  1327. PROCEDURE Disconnect(sender: HCI.HCI; link: HCI.Link; res: WORD);
  1328. VAR p,q : L2CAP;
  1329. BEGIN {EXCLUSIVE}
  1330. IF TraceHCIManager THEN
  1331. KernelLog.String(ModuleName);
  1332. KernelLog.String("HCIManager.Disconnect: ");
  1333. KernelLog.Ln;
  1334. IF(link # NIL) THEN
  1335. KernelLog.String("link.handle = "); KernelLog.Int(link.handle,0);
  1336. KernelLog.String(" link.reason = 0x"); KernelLog.Hex(link.reason,-2);
  1337. ELSE
  1338. KernelLog.String("link is NIL");
  1339. END;
  1340. KernelLog.String(" res = 0x"); KernelLog.Hex(res, -2);
  1341. KernelLog.Ln
  1342. END;
  1343. IF(res = 0) THEN
  1344. p := l2caps.next; q := l2caps;
  1345. WHILE (p # NIL) & (p.link.handle # link.handle) DO
  1346. q := p; p := p.next
  1347. END;
  1348. IF (p # NIL) THEN
  1349. p.link := NIL;
  1350. p.Close();
  1351. q.next := p.next;
  1352. IF (p.linkDisconnectHandler # NIL) THEN p.linkDisconnectHandler(link.remote) END
  1353. END;
  1354. END;
  1355. END Disconnect;
  1356. (*------ connection handling ------*)
  1357. PROCEDURE TimeoutHandler(sender: Bluetooth.IDTimer);
  1358. BEGIN {EXCLUSIVE}
  1359. expiredTimer := sender
  1360. END TimeoutHandler;
  1361. PROCEDURE AwaitACLConnection(bdAddr: Bluetooth.BDAddr): HCI.Link;
  1362. VAR
  1363. idTimer: Bluetooth.IDTimer;
  1364. l : HCI.Link;
  1365. i : LONGINT;
  1366. BEGIN {EXCLUSIVE}
  1367. NEW(idTimer, TimeoutHandler, ConnectTimeout);
  1368. AWAIT(((newLink # NIL) & (newLink.remote = bdAddr)) OR (expiredTimer = idTimer));
  1369. IF (expiredTimer = idTimer) THEN
  1370. IF TraceHCIManager THEN
  1371. KernelLog.String(ModuleName);
  1372. KernelLog.String("HCIManager.AwaitACLConnection: timeout. bdAddr = ");
  1373. FOR i:=0 TO Bluetooth.BDAddrLen-1 DO
  1374. KernelLog.Hex(ORD(bdAddr[i]), -2);
  1375. END;
  1376. KernelLog.Ln;
  1377. END;
  1378. RETURN NIL
  1379. ELSE
  1380. l := newLink;
  1381. newLink := NIL;
  1382. RETURN l;
  1383. END
  1384. END AwaitACLConnection;
  1385. END HCIManager;
  1386. OnACLLinkDisconnect* = PROCEDURE {DELEGATE} (bdAddr : Bluetooth.BDAddr);
  1387. (* L2CAP interface *)
  1388. L2CAP* = OBJECT
  1389. VAR
  1390. bdAddr-: Bluetooth.BDAddr; (** BD Addr of local device *)
  1391. aclMTU, scoMTU, aclNumPackets, scoNumPackets: LONGINT; (* limitations of local device *)
  1392. indications: ARRAY MaxEventIndication-MinEventIndication+1 OF EventIndicationCallback;
  1393. reassembler: Reassembler;
  1394. channelManager-: ChannelManager;
  1395. signallingChannel: SignallingChannel;
  1396. dead: BOOLEAN;
  1397. next : L2CAP;
  1398. link : HCI.Link;
  1399. linkDisconnectHandler* : OnACLLinkDisconnect;
  1400. PROCEDURE &Init*;
  1401. VAR i: LONGINT;
  1402. BEGIN
  1403. IF TraceL2CAP THEN
  1404. KernelLog.String(ModuleName);
  1405. KernelLog.String("L2CAP.Init: ...");
  1406. KernelLog.Ln;
  1407. END;
  1408. bdAddr := hciManager.hci.bdAddr;
  1409. aclMTU := hciManager.hci.aclMTU; aclNumPackets := hciManager.hci.aclNumPackets;
  1410. scoMTU := hciManager.hci.scoMTU; scoNumPackets := hciManager.hci.scoNumPackets;
  1411. link := NIL;
  1412. NEW(channelManager, SELF);
  1413. signallingChannel := channelManager.GetSignallingChannel();
  1414. NEW(reassembler, SELF);
  1415. IF TraceL2CAP THEN
  1416. KernelLog.String(ModuleName);
  1417. KernelLog.String("L2CAP.Init: done.");
  1418. KernelLog.String(" Addr: "); FOR i := 0 TO Bluetooth.BDAddrLen-1 DO KernelLog.Hex(ORD(bdAddr[i]), -2) END;
  1419. KernelLog.String("; ACL length: "); KernelLog.Int(aclMTU, 0);
  1420. KernelLog.String("; SCO length: "); KernelLog.Int(scoMTU, 0);
  1421. KernelLog.String("; ACL packets: "); KernelLog.Int(aclNumPackets, 0);
  1422. KernelLog.String("; SCO packets: "); KernelLog.Int(scoNumPackets, 0);
  1423. KernelLog.Ln;
  1424. END
  1425. END Init;
  1426. (*----- L2CAP interface -----*)
  1427. (** request a callback when the selected indication event occurs *)
  1428. PROCEDURE EventIndication*(event: Event; callback: EventIndicationCallback; VAR result: WORD);
  1429. BEGIN
  1430. IF (MinEventIndication <= event) & (event <= MaxEventIndication) THEN
  1431. indications[event-MinEventIndication] := callback;
  1432. result := 0
  1433. ELSE
  1434. result := 1
  1435. END
  1436. END EventIndication;
  1437. (** initiates the sending of a L2CAP_ConnectReq message and blocks until a corresponding L2CA_ConnectCfm(Neg)
  1438. or L2CA_TimeoutInd event is received.
  1439. *)
  1440. PROCEDURE Connect*(psm: LONGINT; bdAddr: Bluetooth.BDAddr; VAR lcid: LONGINT; VAR result: WORD; VAR status: LONGINT);
  1441. VAR
  1442. c: Channel;
  1443. BEGIN
  1444. IF TraceL2CAP THEN
  1445. KernelLog.String(ModuleName);
  1446. KernelLog.String("L2CAP.Connect: ...");
  1447. KernelLog.Ln
  1448. END;
  1449. lcid := 0; result := 0; status := 0;
  1450. IF (link = NIL) THEN (* create ACL connection first *)
  1451. IF TraceL2CAP THEN
  1452. KernelLog.String(ModuleName);
  1453. KernelLog.String("L2CAP.Connect: no link on HCI layer; creating link ...");
  1454. KernelLog.Ln;
  1455. END;
  1456. hciManager.CreateACLConnection(SELF,bdAddr,result);
  1457. IF (result # 0) THEN
  1458. IF TraceL2CAP THEN
  1459. KernelLog.String(ModuleName);
  1460. KernelLog.String("L2CAP.Connect: hciManager.CreateConnection failed!");
  1461. KernelLog.Ln;
  1462. END;
  1463. RETURN
  1464. END;
  1465. IF TraceL2CAP THEN
  1466. KernelLog.String(ModuleName);
  1467. KernelLog.String("L2CAP.Connect: HCI link established.");
  1468. KernelLog.Ln
  1469. END;
  1470. END;
  1471. c := channelManager.AddChannel(SELF, link);
  1472. IF TraceL2CAP THEN
  1473. KernelLog.String(ModuleName);
  1474. KernelLog.String("L2CAP.Connect: connecting the new channel ...");
  1475. KernelLog.Ln
  1476. END;
  1477. result := c.Connect(psm, status);
  1478. IF (result = 0) OR (result = 1) THEN
  1479. lcid := c.sid;
  1480. IF TraceL2CAP THEN
  1481. KernelLog.String(ModuleName);
  1482. KernelLog.String("L2CAP.Connect: done. CID = ");
  1483. KernelLog.Hex(lcid,-2);
  1484. KernelLog.Ln
  1485. END;
  1486. ELSE
  1487. channelManager.RemoveChannel(c);
  1488. KernelLog.String(ModuleName);
  1489. KernelLog.String("L2CAP.Connect: faild! result= 0x"); KernelLog.Hex(result,-2);
  1490. KernelLog.Ln
  1491. END
  1492. END Connect;
  1493. (** issues a response to a connection request event indication *)
  1494. PROCEDURE ConnectResponse*(bdAddr: Bluetooth.BDAddr; identifier : CHAR; lcid, response, status: LONGINT; VAR result: WORD);
  1495. VAR c: Channel;
  1496. BEGIN
  1497. c := channelManager.FindChannel(lcid);
  1498. IF (c # NIL) & (c.link.remote = bdAddr) THEN
  1499. result := c.ConnectResponse(identifier, response, status);
  1500. IF result # 0 THEN KernelLog.String("response sent but something went wrong"); KernelLog.Ln; END;
  1501. ELSE
  1502. KernelLog.String("channel not found"); KernelLog.Ln;
  1503. result := 1 (* invalid lcid *)
  1504. END
  1505. END ConnectResponse;
  1506. (** initiates the sending of a L2CAP_ConfigReq message and blocks until a corresponding L2CA_ConfigCfm(Neg)
  1507. or L2CA_Timeout event is received.
  1508. inMTU, outFlow and outFlushTO: input/output parameters
  1509. *)
  1510. PROCEDURE Configure*(cid: LONGINT; VAR inMTU, outFlow, outFlushTO: LONGINT; linkTO: LONGINT; VAR result: WORD);
  1511. VAR c: Channel;
  1512. BEGIN
  1513. IF TraceL2CAP THEN
  1514. KernelLog.String(ModuleName);
  1515. KernelLog.String("L2CAP.Configure: MTU = "); KernelLog.Int(inMTU,0);
  1516. KernelLog.String(" Flow = "); KernelLog.Int(outFlow,0);
  1517. KernelLog.String(" FlushTo = "); KernelLog.Int(outFlushTO,0);
  1518. KernelLog.String(" ...");
  1519. KernelLog.Ln;
  1520. END;
  1521. c := channelManager.FindChannel(cid);
  1522. IF (c # NIL) THEN
  1523. result := c.Configure(inMTU, outFlow, outFlushTO, linkTO)
  1524. ELSE
  1525. result := 1 (* invalid cid *)
  1526. END;
  1527. IF TraceL2CAP THEN
  1528. KernelLog.String(ModuleName);
  1529. KernelLog.String("L2CAP.Configure: done. result = "); KernelLog.Int(result,0);
  1530. KernelLog.String("; MTU = "); KernelLog.Int(inMTU,0);
  1531. KernelLog.String(" Flow = "); KernelLog.Int(outFlow,0);
  1532. KernelLog.String(" FlushTo = "); KernelLog.Int(outFlushTO,0);
  1533. KernelLog.Ln;
  1534. END;
  1535. END Configure;
  1536. (** issues a response to a configuration request event indication *)
  1537. PROCEDURE ConfigurationResponse*(cid: LONGINT; identifier: CHAR; outMTU, inFlow: LONGINT; VAR result: WORD);
  1538. VAR c: Channel;
  1539. BEGIN
  1540. IF TraceL2CAP THEN
  1541. KernelLog.String(ModuleName);
  1542. KernelLog.String("L2CAP.ConfigurationResponse: ...");
  1543. KernelLog.Ln;
  1544. END;
  1545. c := channelManager.FindChannel(cid);
  1546. IF (c # NIL) THEN
  1547. result := c.ConfigurationResponse(identifier, outMTU, inFlow)
  1548. ELSE
  1549. result := 3 (* invalid cid *)
  1550. END;
  1551. IF TraceL2CAP THEN
  1552. KernelLog.String(ModuleName);
  1553. KernelLog.String("L2CAP.ConfigurationResponse: done. result = "); KernelLog.Int(result,0);
  1554. KernelLog.Ln;
  1555. END;
  1556. END ConfigurationResponse;
  1557. (** initiates the sending of a L2CAP_DisconnectReq message and blocks until a corresponding L2CA_DisconnectRsp
  1558. or L2CA_TimeoutInd event is received.
  1559. *)
  1560. PROCEDURE Disconnect*(cid: LONGINT; VAR result: LONGINT);
  1561. VAR
  1562. chan : Channel;
  1563. BEGIN
  1564. IF TraceL2CAP THEN
  1565. KernelLog.String(ModuleName);
  1566. KernelLog.String("L2CAP.Disconnect: ...");
  1567. KernelLog.Ln
  1568. END;
  1569. chan := channelManager.FindChannel(cid);
  1570. IF (chan # NIL) THEN
  1571. result := chan.Disconnect();
  1572. (*chan.Close();*)
  1573. channelManager.RemoveChannel(chan);
  1574. ELSE
  1575. result := 1 (* invalid cid *)
  1576. END;
  1577. IF TraceL2CAP THEN
  1578. KernelLog.String(ModuleName);
  1579. KernelLog.String("L2CAP.Disconnect: done. result = "); KernelLog.Hex(result,-2);
  1580. KernelLog.Ln
  1581. END;
  1582. END Disconnect;
  1583. PROCEDURE DisconnectResponse*(identifier : CHAR; lcid, response, status: LONGINT; VAR result: LONGINT);
  1584. VAR c: Channel;
  1585. BEGIN
  1586. c := channelManager.FindChannel(lcid);
  1587. IF (c # NIL) THEN
  1588. result := -1; (* Some work TO DO *)
  1589. ELSE
  1590. KernelLog.String(ModuleName);
  1591. KernelLog.String("channel not found"); KernelLog.Ln;
  1592. result := 1 (* invalid lcid *)
  1593. END
  1594. END DisconnectResponse;
  1595. (** requests the transfer of data across the channel. If the length of the data exceeds the outMTU then only the first
  1596. outMTU bytes are sent.
  1597. *)
  1598. PROCEDURE Write*(cid, ofs, length: LONGINT; VAR buffer: ARRAY OF CHAR; VAR size: LONGINT; VAR result: WORD);
  1599. VAR c: Channel;
  1600. BEGIN
  1601. IF TraceL2CAP THEN
  1602. KernelLog.String(ModuleName);
  1603. KernelLog.String("L2CAP.Write: ...");
  1604. KernelLog.Ln;
  1605. END;
  1606. c := channelManager.FindChannel(cid);
  1607. IF (c # NIL) THEN
  1608. (*
  1609. result := c.Send(buffer, length, size)
  1610. *)
  1611. result := c.Write(buffer, ofs, length, size)
  1612. ELSE
  1613. result := 3 (* invalid cid *)
  1614. END;
  1615. IF TraceL2CAP THEN
  1616. KernelLog.String(ModuleName);
  1617. KernelLog.String("L2CAP.Write: done. result = "); KernelLog.Int(result,0);
  1618. KernelLog.Ln;
  1619. END;
  1620. END Write;
  1621. (** reqests for reception of data. This reqest returns when data is available or the link is terminated. The data returned
  1622. represents a single L2CAP payload. If the payload is bigger than the buffer, the remainder of the payload will be discarded.
  1623. *)
  1624. PROCEDURE Read*(cid, length: LONGINT; VAR buffer: ARRAY OF CHAR; VAR result, N: LONGINT);
  1625. VAR c: Channel;
  1626. BEGIN
  1627. IF TraceL2CAP THEN
  1628. KernelLog.String(ModuleName);
  1629. KernelLog.String("L2CAP.Read: ... ");
  1630. KernelLog.Ln;
  1631. END;
  1632. c := channelManager.FindChannel(cid);
  1633. IF (c # NIL) THEN
  1634. result := c.Read(buffer, length, N)
  1635. ELSE
  1636. result := 3 (* invalid cid *)
  1637. END;
  1638. IF TraceL2CAP THEN
  1639. KernelLog.String(ModuleName);
  1640. KernelLog.String("L2CAP.Read: done. result = "); KernelLog.Int(result,0);
  1641. KernelLog.Ln;
  1642. END;
  1643. END Read;
  1644. (** requests the creation of a cid to represent a logical connection to multiple devices. *)
  1645. PROCEDURE GroupCreate*(psm: LONGINT; VAR cid: LONGINT);
  1646. END GroupCreate;
  1647. (** closes a group. *)
  1648. PROCEDURE GroupClose*(cid: LONGINT; VAR result: LONGINT);
  1649. END GroupClose;
  1650. (** request the addiction of a member to a group. *)
  1651. PROCEDURE GroupAddMember*(cid: LONGINT; bdAddr: Bluetooth.BDAddr; VAR result: LONGINT);
  1652. END GroupAddMember;
  1653. (** reqest the removal of a member from a group. *)
  1654. PROCEDURE GroupRemoveMember*(cid: LONGINT; bdAddr: Bluetooth.BDAddr; VAR result: LONGINT);
  1655. END GroupRemoveMember;
  1656. (** request a report of the members of a group *)
  1657. PROCEDURE GetGroupMembership*(cid: LONGINT; VAR result: LONGINT; VAR bdAddrList: GroupMembers);
  1658. END GetGroupMembership;
  1659. (** initiates a L2CA_EchoReq message and receives the corresponding L2CAP_EchoRsp message.
  1660. echoData and length are input/output parameters
  1661. *)
  1662. PROCEDURE Ping*(bdAddr: Bluetooth.BDAddr; VAR echoData: ARRAY OF CHAR; VAR length, result: LONGINT);
  1663. (*
  1664. VAR l: HCI.Link; data: ARRAY 4 OF CHAR; i: LONGINT; id: CHAR; response: Response;
  1665. BEGIN
  1666. IF TraceL2CAP THEN KernelLog.String("L2CAP.Ping"); KernelLog.Ln END;
  1667. l := hci.FindLink(-1, bdAddr);
  1668. IF (l # NIL) THEN
  1669. id := signallingChannel.GetIdentifier();
  1670. result := signallingChannel.Signal(l, sigEchoReq, id, data, 0);
  1671. IF (result = 0) THEN
  1672. signallingChannel.WaitForReply(id, RTXTimeout, response);
  1673. IF (response # NIL) THEN
  1674. result := 0;
  1675. length := Min(response.length, LEN(echoData));
  1676. FOR i := 0 TO length-1 DO echoData[i] := response.data[response.ofs+i] END
  1677. ELSE
  1678. result := 1 (* Ping timeout *)
  1679. END
  1680. END
  1681. ELSE
  1682. IF TraceL2CAP THEN KernelLog.String(" no link on HCI layer, exiting"); KernelLog.Ln END;
  1683. result := -1
  1684. END
  1685. *)
  1686. END Ping;
  1687. (** initiates a L2CA_InfoReq message and receives the corresponding L2CAP_InfoRsp message. *)
  1688. PROCEDURE GetInfo*(bdAddr: Bluetooth.BDAddr; infoType: LONGINT; VAR result, size: LONGINT; VAR infoData: ARRAY OF CHAR);
  1689. (*
  1690. VAR l: HCI.Link; data: ARRAY 6 OF CHAR; i, it: LONGINT; id: CHAR; response: Response;
  1691. BEGIN
  1692. ASSERT((0 <= infoType) & (infoType < 10000H));
  1693. IF TraceL2CAP THEN KernelLog.String("L2CAP.GetInfo"); KernelLog.Ln END;
  1694. l := hci.FindLink(-1, bdAddr);
  1695. IF (l # NIL) THEN
  1696. id := signallingChannel.GetIdentifier();
  1697. data[4] := CHR(infoType MOD 100H); data[5] := CHR(infoType DIV 100H);
  1698. result := signallingChannel.Signal(l, sigInformationReq, id, data, 2);
  1699. IF (result = 0) THEN
  1700. signallingChannel.WaitForReply(id, RTXTimeout, response);
  1701. IF (response # NIL) THEN
  1702. it := ORD(response.data[response.ofs])+LONG(ORD(response.data[response.ofs+1]))*100H;
  1703. IF (infoType = it) THEN
  1704. result := ORD(response.data[response.ofs+2])+LONG(ORD(response.data[response.ofs+3]))*100H;
  1705. size := Min(response.length-4, LEN(infoData));
  1706. FOR i := 0 TO size-1 DO infoData[i] := response.data[response.ofs+4+i] END
  1707. ELSE
  1708. result := 1 (* wrong infoType in reply *)
  1709. END
  1710. ELSE
  1711. result := 3 (* GetInfo timeout *)
  1712. END
  1713. END
  1714. ELSE
  1715. IF TraceL2CAP THEN KernelLog.String(" no link on HCI layer, exiting"); KernelLog.Ln END;
  1716. result := -1
  1717. END
  1718. *)
  1719. END GetInfo;
  1720. (** general request to disable the reception of connectionless packets. *)
  1721. PROCEDURE DisableConnectionlessTraffic*(psm: LONGINT; VAR result: LONGINT);
  1722. END DisableConnectionlessTraffic;
  1723. (** general request to enable the reception of connectionless packets. *)
  1724. PROCEDURE EnableConnectionlessTraffic*(psm: LONGINT; VAR result: WORD);
  1725. END EnableConnectionlessTraffic;
  1726. PROCEDURE Close*;
  1727. VAR
  1728. c: Channel;
  1729. result: WORD; i: LONGINT;
  1730. BEGIN {EXCLUSIVE}
  1731. IF TraceL2CAP THEN
  1732. KernelLog.String(ModuleName);
  1733. KernelLog.String("L2CAP.Close: ...");
  1734. KernelLog.Ln;
  1735. END;
  1736. IF (~dead) THEN
  1737. FOR i := MinCID TO MaxCIDs DO
  1738. c := channelManager.FindChannel(i);
  1739. IF (c # NIL) THEN
  1740. c.Close();
  1741. channelManager.RemoveChannel(c);
  1742. END;
  1743. END;
  1744. dead := TRUE;
  1745. signallingChannel.Close();
  1746. reassembler.Close();
  1747. IF (link # NIL) THEN
  1748. hciManager.ReleaseACLConnection(link,result);
  1749. END;
  1750. IF TraceL2CAP THEN
  1751. KernelLog.String(ModuleName);
  1752. KernelLog.String("L2CAP.Close: done. result = ");KernelLog.Int(result,0);
  1753. KernelLog.Ln;
  1754. END;
  1755. ELSE
  1756. IF TraceL2CAP THEN
  1757. KernelLog.String(ModuleName);
  1758. KernelLog.String("L2CAP.Close: done. dead = TRUE; already closed ?");
  1759. KernelLog.Ln;
  1760. END;
  1761. END;
  1762. END Close;
  1763. PROCEDURE GetLinkHandle*() : LONGINT;
  1764. BEGIN
  1765. RETURN link.handle;
  1766. END GetLinkHandle;
  1767. PROCEDURE L2CAConnectInd(request : Request);
  1768. VAR
  1769. indication: EventIndicationCallback;
  1770. connectInd: ConnectInd;
  1771. bdStr: ARRAY 32 OF CHAR;
  1772. BEGIN
  1773. IF TraceL2CAP THEN
  1774. Bluetooth.CharArrayToString(request.link.remote, 0, Bluetooth.BDAddrLen, bdStr);
  1775. KernelLog.String(ModuleName);
  1776. KernelLog.String("L2CAP.L2CAConnectInd: request from "); KernelLog.String(bdStr);
  1777. KernelLog.String(" ... ");
  1778. KernelLog.Ln
  1779. END;
  1780. indication := indications[EConnectInd-MinEventIndication];
  1781. IF (indication # NIL) THEN
  1782. NEW(connectInd);
  1783. connectInd.bdAddr := request.link.remote;
  1784. connectInd.cid := ORD(request.data[request.ofs+2])+LONG(ORD(request.data[request.ofs+3]))*100H;
  1785. connectInd.psm := ORD(request.data[request.ofs])+LONG(ORD(request.data[request.ofs+1]))*100H;
  1786. connectInd.ident := request.identifier;
  1787. connectInd.c := channelManager.AddChannel(SELF, request.link);
  1788. connectInd.c.did := connectInd.cid;
  1789. connectInd.c.psm := connectInd.psm;
  1790. connectInd.c.state := W4L2CAConnectRsp;
  1791. indication(connectInd);
  1792. END;
  1793. IF TraceL2CAP THEN
  1794. KernelLog.String(ModuleName);
  1795. KernelLog.String("L2CAP.L2CAConnectInd: done.");
  1796. KernelLog.Ln
  1797. END
  1798. END L2CAConnectInd;
  1799. PROCEDURE L2CAConfigInd(request : Request);
  1800. VAR
  1801. indication: EventIndicationCallback;
  1802. configureInd: ConfigInd;
  1803. pos, value: LONGINT;
  1804. option: CHAR;
  1805. bdStr: ARRAY 32 OF CHAR;
  1806. BEGIN
  1807. IF TraceL2CAP THEN
  1808. Bluetooth.CharArrayToString(request.link.remote, 0, Bluetooth.BDAddrLen, bdStr);
  1809. KernelLog.String(ModuleName);
  1810. KernelLog.String("L2CAP.L2CAConfigInd: request from "); KernelLog.String(bdStr);
  1811. KernelLog.String(" ... ");
  1812. KernelLog.Ln
  1813. END;
  1814. indication := indications[EConfigInd-MinEventIndication];
  1815. IF (indication # NIL) THEN
  1816. NEW(configureInd);
  1817. configureInd.cid := ORD(request.data[request.ofs])+LONG(ORD(request.data[request.ofs+1]))*100H;
  1818. configureInd.c := channelManager.FindChannel(configureInd.cid);
  1819. configureInd.ident := request.identifier;
  1820. (* request.data[ofs+2:ofs+3]: flags (ignore for now) *)
  1821. pos := request.ofs+4;
  1822. WHILE (pos < request.ofs+request.length) DO
  1823. GetOption(request.data^, pos, option, value);
  1824. CASE option OF
  1825. | optMTU: configureInd.outMTU := value; configureInd.c.mtu := value
  1826. | optFlushTO: configureInd.inFlushTO := value
  1827. | optQoS: (* ignore for now *)
  1828. ELSE
  1829. KernelLog.String(ModuleName);
  1830. KernelLog.String("L2CAP.L2CAConfigInd: error in configuration request (option= 0x");
  1831. KernelLog.Hex(ORD(option), -2); KernelLog.String(")"); KernelLog.Ln;
  1832. END
  1833. END;
  1834. indication(configureInd);
  1835. END;
  1836. IF TraceL2CAP THEN
  1837. KernelLog.String(ModuleName);
  1838. KernelLog.String("L2CAP.L2CAConfigInd: done.");
  1839. KernelLog.Ln
  1840. END
  1841. END L2CAConfigInd;
  1842. PROCEDURE L2CADisconnectInd(request : Request);
  1843. VAR
  1844. indication: EventIndicationCallback;
  1845. disconnectInd: DisconnectInd;
  1846. bdStr: ARRAY 32 OF CHAR;
  1847. BEGIN
  1848. IF TraceL2CAP THEN
  1849. Bluetooth.CharArrayToString(request.link.remote, 0, Bluetooth.BDAddrLen, bdStr);
  1850. KernelLog.String(ModuleName);
  1851. KernelLog.String("L2CAP.L2CADisconnectInd: request from "); KernelLog.String(bdStr);
  1852. KernelLog.String(" ... ");
  1853. KernelLog.Ln
  1854. END;
  1855. indication := indications[EDisconnectInd-MinEventIndication];
  1856. IF (indication # NIL) THEN
  1857. NEW(disconnectInd);
  1858. disconnectInd.cid := ORD(request.data[request.ofs])+LONG(ORD(request.data[request.ofs+1]))*100H;
  1859. disconnectInd.c := channelManager.FindChannel(disconnectInd.cid);
  1860. indication(disconnectInd);
  1861. END;
  1862. IF TraceL2CAP THEN
  1863. KernelLog.String(ModuleName);
  1864. KernelLog.String("L2CAP.L2CADisconnectInd: done.");
  1865. KernelLog.Ln
  1866. END
  1867. END L2CADisconnectInd;
  1868. (*----- event handling -----*)
  1869. PROCEDURE Run;
  1870. VAR
  1871. request: Request;
  1872. bdStr: ARRAY 32 OF CHAR;
  1873. BEGIN
  1874. REPEAT
  1875. request := signallingChannel.GetRequest();
  1876. IF (request # NIL) THEN
  1877. CASE request.code OF
  1878. | sigConnectionReq:
  1879. L2CAConnectInd(request);
  1880. | sigConfigureReq:
  1881. L2CAConfigInd(request);
  1882. | sigDisconnectionReq:
  1883. L2CADisconnectInd(request);
  1884. ELSE
  1885. Bluetooth.CharArrayToString(request.link.remote, 0, Bluetooth.BDAddrLen, bdStr);
  1886. KernelLog.String(ModuleName);
  1887. KernelLog.String("L2CAP.Run: request from "); KernelLog.String(bdStr);
  1888. KernelLog.String(" not supported; request.code= 0x"); KernelLog.Hex(ORD(request.code),-2);
  1889. KernelLog.Ln;
  1890. END;
  1891. ELSE
  1892. KernelLog.String(ModuleName);
  1893. KernelLog.String("L2CAP.Run: request = NIL"); KernelLog.String(bdStr);
  1894. KernelLog.Ln;
  1895. END;
  1896. UNTIL dead;
  1897. END Run;
  1898. BEGIN {ACTIVE}
  1899. IF TraceL2CAP THEN
  1900. KernelLog.String(ModuleName);
  1901. KernelLog.String("L2CAP: {ACTIVE}: ...");
  1902. KernelLog.Ln;
  1903. END;
  1904. Run;
  1905. IF TraceL2CAP THEN
  1906. KernelLog.String(ModuleName);
  1907. KernelLog.String("L2CAP: {ACTIVE}: done. ");
  1908. KernelLog.Ln;
  1909. END;
  1910. END L2CAP;
  1911. VAR
  1912. hciManager : HCIManager;
  1913. PROCEDURE PutOption(option: CHAR; value: LONGINT; VAR data: ARRAY OF CHAR; VAR pos: LONGINT);
  1914. VAR i: LONGINT;
  1915. BEGIN
  1916. data[pos] := option; INC(pos);
  1917. CASE option OF
  1918. | optMTU:
  1919. data[pos] := 02X; INC(pos); (* length *)
  1920. data[pos] := CHR(value MOD 100H); data[pos+1] := CHR(value DIV 100H MOD 100H); INC(pos, 2)
  1921. | optFlushTO:
  1922. data[pos] := 02X; INC(pos); (* length *)
  1923. data[pos] := CHR(value MOD 100H); data[pos+1] := CHR(value DIV 100H MOD 100H); INC(pos, 2)
  1924. | optQoS:
  1925. data[pos] := 16X; INC(pos); (* length *)
  1926. data[pos] := 0X; INC(pos); (* flags *)
  1927. data[pos] := 01X; INC(pos); (* service type 1: best effort *)
  1928. (* replaced data[pos] with data[i] mm *)
  1929. FOR i := pos TO pos+12 DO data[i] := 0X END; INC(pos, 12); (* token rate & bucket, peak bandwith = 0 *)
  1930. FOR i := pos TO pos+8 DO data[i] := 0FFX END; INC(pos, 8) (* latency, delay variation = 0FFFFFFFFH *)
  1931. END
  1932. END PutOption;
  1933. PROCEDURE GetOption(VAR data: ARRAY OF CHAR; VAR pos: LONGINT; VAR option: CHAR; VAR value: LONGINT);
  1934. BEGIN
  1935. option := data[pos]; INC(pos, 2); (* skip length field *)
  1936. CASE option OF
  1937. | optMTU, optFlushTO:
  1938. value := ORD(data[pos])+LONG(ORD(data[pos+1]))*100H; INC(pos, 2)
  1939. | optQoS:
  1940. INC(pos, 16H); (* ignored *)
  1941. ELSE option := 0FFX (* error *)
  1942. END
  1943. END GetOption;
  1944. PROCEDURE GetL2CAPHeader(VAR data: ARRAY OF CHAR; VAR cid, len: LONGINT);
  1945. BEGIN
  1946. len := LONG(ORD(data[1]))*100H + ORD(data[0]);
  1947. cid := LONG(ORD(data[3]))*100H + ORD(data[2])
  1948. END GetL2CAPHeader;
  1949. (*
  1950. PROCEDURE SetL2CAPHeader(cid, len: LONGINT; VAR data: ARRAY OF CHAR);
  1951. BEGIN
  1952. ASSERT((0 <= len) & (len < 10000H));
  1953. ASSERT((0 <= cid) & (cid < 10000H));
  1954. data[0] := CHR(len MOD 100H); data[1] := CHR(len DIV 100H);
  1955. data[2] := CHR(cid MOD 100H); data[3] := CHR(cid DIV 100H)
  1956. END SetL2CAPHeader;
  1957. *)
  1958. PROCEDURE Min(a,b: LONGINT): LONGINT;
  1959. BEGIN
  1960. IF (a <= b) THEN RETURN a
  1961. ELSE RETURN b
  1962. END
  1963. END Min;
  1964. PROCEDURE InitL2CAP*(hci : HCI.HCI);
  1965. BEGIN
  1966. NEW(hciManager,hci);
  1967. END InitL2CAP;
  1968. PROCEDURE GetHCIManager*() : HCIManager;
  1969. BEGIN
  1970. RETURN hciManager;
  1971. END GetHCIManager;
  1972. PROCEDURE GetHCILayer*() : HCI.HCI;
  1973. BEGIN
  1974. IF hciManager = NIL THEN
  1975. RETURN NIL;
  1976. ELSE
  1977. RETURN hciManager.hci
  1978. END;
  1979. END GetHCILayer;
  1980. END BluetoothL2CAP.