BluetoothHCI.Mod 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. MODULE BluetoothHCI; (** AUTHOR "be"; PURPOSE "Bluetooth HCI driver"; *)
  2. IMPORT KernelLog, Bluetooth;
  3. CONST
  4. Trace = FALSE;
  5. TraceReceive = FALSE;
  6. TraceSend = FALSE;
  7. ModuleName = "[BTHCI]";
  8. TraceHCI = FALSE;
  9. TraceLink = FALSE;
  10. (* Timeouts (in ms) *)
  11. Timeout = 1000;
  12. ConnectionTimeout = 10000;
  13. (**--- HCI Command Packets OGF and OCF ---*)
  14. (** Link Control Commands *)
  15. ogfLinkControl* = 01H; (** OGF, OCFs follow *)
  16. ocfInquiry* = 0001H;
  17. ocfInquiryCancel* = 0002H;
  18. ocfPeriodicInquiryMode* = 0003H;
  19. ocfExitPeriodicInquiryMode* = 0004H;
  20. ocfCreateConnection* = 0005H;
  21. ocfDisconnect* = 0006H;
  22. ocfAddSCOConnection* = 0007H;
  23. ocfAcceptConnectionRequest* = 0009H;
  24. ocfRejectConnectionRequest* = 000AH;
  25. ocfLinkKeyRequestReply* = 000BH;
  26. ocfLinkKeyRequestNegativeReply* = 000CH;
  27. ocfPINCodeRequestReply* = 000DH;
  28. ocfPINCodeRequestNegativeReply* = 000EH;
  29. ocfChangeConnectionPacketType* = 000FH;
  30. ocfAuthenticationRequested* = 0011H;
  31. ocfSetConnectionEncryption* = 0013H;
  32. ocfChangeConnectionLinkKey* = 0015H;
  33. ocfMasterLinkKey* = 0017H;
  34. ocfRemoteNameRequest* = 0019H;
  35. ocfReadRemoteSupportedFeatures* = 001BH;
  36. ocfReadRemoteVersionInformation* = 001DH;
  37. ocfReadClockOffset* = 001FH;
  38. (** Link Policy Commands *)
  39. ogfLinkPolicy* = 02H; (** OGF, OCFs follow *)
  40. ocfHoldMode* = 0001H;
  41. ocfSniffMode* = 0003H;
  42. ocfExitSniffMode* = 0004H;
  43. ocfParkMode* = 0005H;
  44. ocfExitParkMode* = 0006H;
  45. ocfQoSSetup* = 0007H;
  46. ocfRoleDiscovery* = 0009H;
  47. ocfSwitchRole* = 000BH;
  48. ocfReadLinkPolicySettings* = 000CH;
  49. ocfWriteLinkPolicySettings* = 000DH;
  50. (** Host Controller & Baseband Commands *)
  51. ogfControl* = 03H; (** OGF, OCFs follow *)
  52. ocfSetEventMask* = 0001H;
  53. ocfReset* = 0003H;
  54. ocfSetEventFilter* = 0005H;
  55. ocfFlush* = 0008H;
  56. ocfReadPINType* = 0009H;
  57. ocfWritePINType* = 000AH;
  58. ocfCreateNewUnitKey* = 000BH;
  59. ocfReadStoredLinkKey* = 000DH;
  60. ocfWriteStoredLinkKey* = 0011H;
  61. ocfDeleteStoredLinkKey* = 0012H;
  62. ocfChangeLocalName* = 0013H;
  63. ocfReadLocalName* = 0014H;
  64. ocfReadConnectionAcceptTimeout* = 0015H;
  65. ocfWriteConnectionAcceptTimeout* = 0016H;
  66. ocfReadPageTimeout* = 0017H;
  67. ocfWritePageTimeout* = 0018H;
  68. ocfReadScanEnable* = 0019H;
  69. ocfWriteScanEnable* = 001AH;
  70. ocfReadPageScanActivity* = 001BH;
  71. ocfWritePageScanActivity* = 001CH;
  72. ocfReadInquiryScanActivity* = 001DH;
  73. ocfWriteInquiryScanActivity* = 001EH;
  74. ocfReadAuthenticationEnable* = 001FH;
  75. ocfWriteAuthenticationEnable* = 0020H;
  76. ocfReadEncryptionMode* = 0021H;
  77. ocfWriteEncryptionMode* = 0022H;
  78. ocfReadClassOfDevice* = 0023H;
  79. ocfWriteClassOfDevice* = 0024H;
  80. ocfReadVoiceSetting* = 0025H;
  81. ocfWriteVoiceSetting* = 0026H;
  82. ocfReadAutomaticFlushTimeout* = 0027H;
  83. ocfWriteAutomaticFlushTimeout* = 0028H;
  84. ocfReadNumBroadcastRetrans* = 0029H;
  85. ocfWriteNumBroadcastRetrans* = 002AH;
  86. ocfReadHoldModeActivity* = 002BH;
  87. ocfWriteHoldModeActivity* = 002CH;
  88. ocfReadTransmitPowerLevel* = 002DH;
  89. ocfReadSCOFlowControlEnable* = 002EH;
  90. ocfWriteSCOFlowControlEnable* = 002FH;
  91. ocfSetHostCtrlToHostFlowCtrl* = 0031H;
  92. ocfHostBufferSize* = 0033H;
  93. ocfHostNumberOfCompletedPackets* = 0035H;
  94. ocfReadLinkSupervisionTimeout* = 0036H;
  95. ocfWriteLinkSupervisionTimeout* = 0037H;
  96. ocfReadNumberOfSupportedIAC* = 0038H;
  97. ocfReadCurrentIACLAP* = 0039H;
  98. ocfWriteCurrentIACLAP* = 003AH;
  99. ocfReadPageScanPeriodMode* = 003BH;
  100. ocfWritePageScanPeriodMode* = 003CH;
  101. ocfReadPageScanMode* = 003DH;
  102. ocfWritePageScanMode* = 003EH;
  103. (** Informational Parameters *)
  104. ogfInformational* = 04H; (** OGF, OCFs follow *)
  105. ocfReadLocalVersionInformation* = 0001H;
  106. ocfReadLocalSupportedFeatures* = 0003H;
  107. ocfReadBufferSize* = 0005H;
  108. ocfReadCountryCode* = 0007H;
  109. ocfReadBDAddr* = 0009H;
  110. (** Status Parameters *)
  111. ogfStatus* = 05H; (** OGF, OCFs follow *)
  112. ocfReadFailedContactCounter* = 0001H;
  113. ocfResetFailedContactCounter* = 0002H;
  114. ocfGetLinkQuality* = 0003H;
  115. ocfHCIReadRSSI* = 0005H;
  116. (** Ericsson Parameters *)
  117. ogfEricsson* = 03FH;
  118. ocfSetUARTBaudRate* = 0009H;
  119. (**--- ACL flags (see spec chapter 4.4.3) ---*)
  120. (** Packet Boundary Flag (PBF) *)
  121. pbfFirst* = 2; (** first packet of higher layer message *)
  122. pbfContinuing* = 1; (** continuing fragment packet of higher layer message *)
  123. (** Broadcast Flag (BF) *)
  124. bfPointToPoint* = 0; (** point to point *)
  125. bfActive* = 1; (** active broadcast *)
  126. bfPiconet* = 2; (** piconet broadcast *)
  127. (** HCI Events *)
  128. EInquiryComplete* = 01X; (** params: Status *)
  129. EInquiryResult* = 02X; (** params: see spec chapter 5.2.2, p. 728 *)
  130. EConnectionComplete* = 03X; (** params: Status, Connection_Handle (2 bytes), BD_Addr (6 bytes), Link_Type, Encryption_Mode *)
  131. EDisconnectionComplete* = 05X; (** params: Status, Connection_Handle (2 bytes), Reason *)
  132. EReadRemoteVersionInfoComplete* = 0CX;
  133. ECmdComplete* = 0EX; (** params: Num_HCI_Commands, Command_Opcode (2 bytes), Return_Parameters *)
  134. ECmdStatus* = 0FX; (** params: Status, Num_HCI_Commands, Command-Opcode (2 bytes) *)
  135. ENofCompletedPackets* = 13X;
  136. EMaxSlotsChange* = 1BX;
  137. EPageScanRepModeChange* = 20X;
  138. CONST
  139. (** WriteScanEnable *)
  140. SENoScan* = 00X;
  141. SEInquiry* = 01X;
  142. SEPage* = 02X;
  143. SEInquiryPage* = 03X;
  144. (** SetEventFilter *)
  145. (** filter types *)
  146. EFClear* = 00X;
  147. EFInquiryResult* = 01X;
  148. EFConnectionSetup* = 02X;
  149. (** connection types for EFInquiryResult *)
  150. EFIRNewDevice* = 00X; (** requires no condition *)
  151. EFIRClass* = 01X; (** requires 'class of device' (3 bytes) and 'class of device mask' (3 bytes) *)
  152. EFIRAddr* = 02X; (** requires 'bd_addr' (6 bytes) *)
  153. (** connection types for EFConnectionSetup *)
  154. EFCSAll* = 00X; (** requires 'auto accept flag' (1 byte) *)
  155. EFCSClass* = 01X; (** requires 'class of device' (3 bytes), 'class of device mask' (3 bytes) and 'auto accept flag' (1 byte) *)
  156. EFCSAddr* = 02X; (** requires 'bd_addr' (6 bytes) and 'auto accept flag' (1 byte) *)
  157. (** 'auto accept flag' for EFConnectionSetup *)
  158. EFCSAAOff* = 01X; (** auto accept is off *)
  159. EFCSAAOn* = 02X; (** auto accept is on, role switch is off *)
  160. EFCSAAOnRoleSwitch* = 03X; (** auto accept is on, role switch is on *)
  161. CONST
  162. (** link states *)
  163. lsUp* = 0;
  164. lsDown* = 1;
  165. TYPE
  166. Link* = OBJECT (** HCI link *)
  167. VAR
  168. next: Link;
  169. hci : HCI;
  170. state*: LONGINT; (** link state *)
  171. remote*: Bluetooth.BDAddr; (** remote device *)
  172. handle-: LONGINT; (** connection handle *)
  173. type*: LONGINT; (** connection type *)
  174. encryption*: LONGINT; (** encryption mode *)
  175. reason*: LONGINT; (** error code (depends on state) *)
  176. nofPackets-: LONGINT; (** number of completed (transmitted or flushed) packets *)
  177. OnReceiveACLData*: ReceiveACLDataEvent;
  178. PROCEDURE &Init*(hci : HCI; remote: Bluetooth.BDAddr; handle: LONGINT);
  179. BEGIN
  180. ASSERT((0000H <= handle) & (handle <= 0EFFH));
  181. SELF.hci := hci; SELF.remote := remote; SELF.handle := handle;
  182. IF TraceLink THEN
  183. KernelLog.String(ModuleName);
  184. KernelLog.String("Link.Init: handle = "); KernelLog.Int(handle,0);
  185. KernelLog.Ln;
  186. END;
  187. END Init;
  188. (** send ACL data.
  189. PBF: packet boundary flag
  190. BF: broadcast flag
  191. *)
  192. PROCEDURE SendACL*(PBF, BF: LONGINT; VAR data: ARRAY OF CHAR; ofs, len: LONGINT): WORD;
  193. VAR v: LONGINT; res: WORD; aclhdr: ARRAY 4 OF CHAR;
  194. BEGIN
  195. ASSERT((pbfContinuing <= PBF) & (PBF <= pbfFirst));
  196. ASSERT((bfPointToPoint <= BF) & (BF <= bfPiconet));
  197. ASSERT((0 < len) & (len < 10000H));
  198. v := handle + PBF*1000H + BF*4000H;
  199. aclhdr[0] := CHR(v MOD 100H); aclhdr[1] := CHR(v DIV 100H);
  200. aclhdr[2] := CHR(len MOD 100H); aclhdr[3] := CHR(len DIV 100H);
  201. hci.tl.Send1H(Bluetooth.ACL, aclhdr, 4, data, ofs, len, res);
  202. IF TraceLink THEN
  203. KernelLog.String(ModuleName);
  204. KernelLog.String("Link.SendACL: handle = "); KernelLog.Int(handle,0);
  205. KernelLog.Ln;
  206. END;
  207. RETURN res
  208. END SendACL;
  209. PROCEDURE SendACLH*(PBF, BF: LONGINT; VAR hdr: ARRAY OF CHAR; hdrlen: LONGINT; VAR data: ARRAY OF CHAR; ofs, len: LONGINT): WORD;
  210. VAR v, totlen: LONGINT; res: WORD; aclhdr: ARRAY 4 OF CHAR;
  211. BEGIN
  212. totlen := len + hdrlen;
  213. ASSERT((pbfContinuing <= PBF) & (PBF <= pbfFirst));
  214. ASSERT((bfPointToPoint <= BF) & (BF <= bfPiconet));
  215. ASSERT((0 < totlen) & (totlen < 10000H));
  216. v := handle + PBF*1000H + BF*4000H;
  217. aclhdr[0] := CHR(v MOD 100H); aclhdr[1] := CHR(v DIV 100H);
  218. aclhdr[2] := CHR(totlen MOD 100H); aclhdr[3] := CHR(totlen DIV 100H);
  219. hci.tl.Send2H(Bluetooth.ACL, aclhdr, 4, hdr, hdrlen, data, ofs, len, res);
  220. IF TraceLink THEN
  221. KernelLog.String(ModuleName);
  222. KernelLog.String("Link.SendACLH: handle = "); KernelLog.Int(handle,0);
  223. KernelLog.Ln;
  224. END;
  225. RETURN res
  226. END SendACLH;
  227. PROCEDURE ACLDataReceived(acl: Bluetooth.ACLPacket);
  228. BEGIN
  229. IF TraceLink THEN
  230. KernelLog.String(ModuleName);
  231. KernelLog.String("Link.ACLDataReceived: handle = "); KernelLog.Int(handle,0);
  232. KernelLog.Ln;
  233. END;
  234. IF (OnReceiveACLData # NIL) THEN OnReceiveACLData(SELF, acl) END
  235. END ACLDataReceived;
  236. END Link;
  237. (* stupid Paco does not allow this definition before 'Link' *)
  238. ReceiveACLDataEvent* = PROCEDURE {DELEGATE} (sender: Link; acl: Bluetooth.ACLPacket);
  239. LinkEnumPar = POINTER TO RECORD
  240. handle: LONGINT;
  241. remote: Bluetooth.BDAddr;
  242. link: Link
  243. END;
  244. LinkEnumerator* = PROCEDURE {DELEGATE} (l: Link; par: ANY): BOOLEAN; (** return TRUE if the enumeration should be continued *)
  245. LinkManager = OBJECT
  246. VAR
  247. links: Link;
  248. numLinks: LONGINT;
  249. PROCEDURE &Init*;
  250. BEGIN
  251. NEW(links, NIL,"", 0); (* dummy head *)
  252. links.handle := -1;
  253. numLinks := 0
  254. END Init;
  255. PROCEDURE Reset;
  256. BEGIN
  257. links.next := NIL;
  258. numLinks := 0
  259. END Reset;
  260. PROCEDURE AddLink*(l: Link);
  261. BEGIN {EXCLUSIVE}
  262. l.next := links.next; links.next := l; INC(numLinks)
  263. END AddLink;
  264. PROCEDURE RemoveLink*(l: Link);
  265. VAR p,q: Link;
  266. BEGIN {EXCLUSIVE}
  267. p := links.next; q := links;
  268. WHILE (p # NIL) & (p # l) DO q := p; p := p.next END;
  269. IF (p # NIL) THEN q.next := p.next; DEC(numLinks) END
  270. END RemoveLink;
  271. PROCEDURE FindLink*(handle: LONGINT): Link;
  272. VAR l: Link;
  273. BEGIN {EXCLUSIVE}
  274. l := links.next;
  275. WHILE (l # NIL) & (l.handle # handle) DO l := l.next END;
  276. RETURN l
  277. END FindLink;
  278. PROCEDURE Enumerate(callback: LinkEnumerator; par: ANY);
  279. VAR l: Link; la: POINTER TO ARRAY OF Link; i: LONGINT;
  280. BEGIN
  281. NEW(la, numLinks);
  282. BEGIN {EXCLUSIVE}
  283. l := links.next;
  284. FOR i := 0 TO numLinks-1 DO la[i] := l; l := l.next END
  285. END;
  286. i := 0;
  287. WHILE (i < numLinks) & (callback(la[i], par)) DO
  288. INC(i)
  289. END
  290. END Enumerate;
  291. END LinkManager;
  292. HCI* = OBJECT
  293. VAR
  294. tl: Bluetooth.TransportLayer;
  295. aclQueue, eventQueue-: Bluetooth.Queue;
  296. linkManager*: LinkManager;
  297. (** info *)
  298. bdAddr-: Bluetooth.BDAddr; (* device address *)
  299. aclMTU-, scoMTU-, aclNumPackets-, scoNumPackets-: LONGINT; (* MTUs and max. # of packets for ACL/SCO connections *)
  300. (** events *)
  301. OnConnectionComplete* : ConnectionComplete;
  302. OnDisconnectionComplete* : DisconnectionComplete;
  303. OnInquiryComplete* : InquiryComplete;
  304. OnConnect*: ConnectionEvent;
  305. OnDisconnect*: ConnectionEvent;
  306. OnInquiry*: InquiryEvent;
  307. OnEvent*: GeneralEvent;
  308. OnError*: ErrorEvent;
  309. PROCEDURE &Init*(transportLayer: Bluetooth.TransportLayer);
  310. VAR q: Bluetooth.Queue;
  311. BEGIN
  312. tl := transportLayer;
  313. NEW(linkManager);
  314. NEW(eventQueue); tl.SetSink(Bluetooth.Event, eventQueue);
  315. eventQueue.RegisterPacketFilter(EricssonFilter, EricssonHandler);
  316. eventQueue.RegisterPacketFilter(EventFilter, EventHandler);
  317. NEW(aclQueue); tl.SetSink(Bluetooth.ACL, aclQueue);
  318. aclQueue.RegisterPacketFilter(ACLFilter, ACLHandler);
  319. q := tl.GetSink(Bluetooth.Default);
  320. q.RegisterPacketFilter(ErrorFilter, ErrorHandler);
  321. END Init;
  322. PROCEDURE Close*;
  323. BEGIN {EXCLUSIVE}
  324. IF TraceHCI THEN
  325. KernelLog.String(ModuleName); KernelLog.String("HCI.Close: ...");
  326. KernelLog.Ln;
  327. END;
  328. tl.Close;
  329. eventQueue.Close; aclQueue.Close;
  330. IF TraceHCI THEN
  331. KernelLog.String(ModuleName); KernelLog.String("HCI.Close: done.");
  332. KernelLog.Ln;
  333. END;
  334. END Close;
  335. (** initialize the module, get BDADDR, MTUs, etc *)
  336. PROCEDURE Initialize*(): WORD;
  337. VAR res: WORD;
  338. BEGIN
  339. IF TraceHCI THEN
  340. KernelLog.String(ModuleName);
  341. KernelLog.String("HCI.Initialize: ...");
  342. KernelLog.Ln;
  343. END;
  344. res := Reset();
  345. IF (res # 0) THEN
  346. KernelLog.String(ModuleName);
  347. KernelLog.String("HCI.Initialize: Reset failed. res = 0x"); KernelLog.Hex(res,-2);
  348. KernelLog.Ln;
  349. RETURN res
  350. END;
  351. res := ReadBDAddr(bdAddr);
  352. IF (res # 0) THEN
  353. KernelLog.String(ModuleName);
  354. KernelLog.String("HCI.Initialize: ReadBDaddr failed. res = 0x"); KernelLog.Hex(res,-2);
  355. KernelLog.Ln;
  356. RETURN res
  357. END;
  358. res := ReadBufferSize(aclMTU, scoMTU, aclNumPackets, scoNumPackets);
  359. IF TraceHCI THEN
  360. KernelLog.String(ModuleName);
  361. KernelLog.String("HCI.Initialize: done. ReadBufferSize res = "); KernelLog.Int(res,0);
  362. KernelLog.Ln;
  363. END;
  364. RETURN res;
  365. END Initialize;
  366. (** enumerate all active links. par is passed back to the callback procedure *)
  367. PROCEDURE EnumerateLinks*(enumCallback: LinkEnumerator; par: ANY);
  368. BEGIN
  369. linkManager.Enumerate(enumCallback, par)
  370. END EnumerateLinks;
  371. (** find a link. If 'handle'=-1, the first link to 'remote' is returned *)
  372. PROCEDURE FindLinkCallback(l: Link; par: ANY): BOOLEAN;
  373. BEGIN
  374. WITH par: LinkEnumPar DO
  375. IF (par.handle # -1) THEN
  376. IF (par.handle = l.handle) THEN par.link := l END
  377. ELSE
  378. IF (par.remote = l.remote) THEN par.link := l END
  379. END;
  380. RETURN par.link = NIL
  381. END
  382. END FindLinkCallback;
  383. PROCEDURE FindLink*(handle: LONGINT; remote: Bluetooth.BDAddr): Link;
  384. VAR lep: LinkEnumPar;
  385. BEGIN
  386. NEW(lep); lep.handle := handle; lep.remote := remote; lep.link := NIL;
  387. linkManager.Enumerate(FindLinkCallback, lep);
  388. RETURN lep.link
  389. END FindLink;
  390. (** send a HCI command. Return values:
  391. res: result code
  392. pending: TRUE if the command is pending
  393. packet: reply packet from BT host (may be NIL)
  394. *)
  395. PROCEDURE SendCommand*(OGF, OCF: LONGINT; params: ARRAY OF CHAR; len: LONGINT;
  396. VAR packet: Bluetooth.EventPacket;
  397. VAR pending: BOOLEAN;
  398. VAR res: WORD);
  399. BEGIN {EXCLUSIVE}
  400. InSendCommand(OGF, OCF, params, len, packet, pending, res)
  401. END SendCommand;
  402. PROCEDURE InSendCommand(OGF, OCF: LONGINT; params: ARRAY OF CHAR; len: LONGINT;
  403. VAR packet: Bluetooth.EventPacket;
  404. VAR pending: BOOLEAN;
  405. VAR res: WORD);
  406. VAR
  407. cmd: POINTER TO ARRAY OF CHAR; i: LONGINT;
  408. BEGIN (* EXCLUSIVE *)
  409. NEW(cmd,3+len);
  410. IF TraceHCI THEN
  411. KernelLog.String(ModuleName);
  412. KernelLog.String("HCI.InSendCommand: OGF= 0x"); KernelLog.Hex(OGF,-2);
  413. KernelLog.String(" OCF= 0x"); KernelLog.Hex(OCF,-2);
  414. KernelLog.String(" params= ");
  415. FOR i := 0 TO len-1 DO
  416. KernelLog.String("0x"); KernelLog.Hex(ORD(params[i]), -2);
  417. END;
  418. KernelLog.String(" ..."); KernelLog.Ln;
  419. END;
  420. pending := FALSE;
  421. ComposeCommandHeader(OGF, OCF, len, cmd^);
  422. FOR i := 0 TO len-1 DO cmd[3+i] := params[i] END;
  423. tl.Send(Bluetooth.Command, cmd^, 0, 3+len, res);
  424. IF (res = 0) THEN
  425. GetEvent(Timeout,packet,res);
  426. IF (res = 0) THEN
  427. IF (packet.code = ECmdComplete) & (packet.paramLen >= 3) &
  428. (packet.params[1] = cmd[0]) & (packet.params[2] = cmd[1]) THEN
  429. (* in BT V1.1 all commands that return a command complete event have 'status' (0 = ok)
  430. as the first parameter. *)
  431. res := ORD(packet.params[3]);
  432. (* hack... *)
  433. IF (OGF = ogfControl) & (OCF = ocfReset) & (res = 0) THEN
  434. linkManager.Reset
  435. END;
  436. ELSIF (packet.code = ECmdStatus) & (packet.paramLen >= 3) &
  437. (packet.params[2] = cmd[0]) & (packet.params[3] = cmd[1]) THEN
  438. res := ORD(packet.params[0]);
  439. pending := TRUE;
  440. ELSE
  441. res := Bluetooth.ErrInvalidEvent;
  442. IF TraceHCI THEN
  443. KernelLog.String(ModuleName);
  444. KernelLog.String("HCI.InSendCommand: invalid event received:"); KernelLog.Ln;
  445. KernelLog.String(" event code: "); KernelLog.Hex(ORD(packet.code), -2); KernelLog.Ln;
  446. KernelLog.String(" parameters: ");
  447. FOR i := 0 TO packet.paramLen-1 DO
  448. KernelLog.Hex(ORD(packet.params[i]), -2); KernelLog.Char(" ")
  449. END;
  450. KernelLog.Ln;
  451. END;
  452. END;
  453. IF TraceHCI THEN
  454. KernelLog.String(ModuleName);
  455. KernelLog.String("HCI.InSendCommand: event received. event code = 0x"); KernelLog.Hex(ORD(packet.code), -2);
  456. KernelLog.String(" result = 0x"); KernelLog.Hex(res,-2);
  457. KernelLog.String(" pending = "); IF pending THEN KernelLog.String("TRUE"); ELSE KernelLog.String("FALSE"); END;
  458. KernelLog.Ln;
  459. END;
  460. ELSE
  461. KernelLog.String(ModuleName);
  462. KernelLog.String("HCI.InSendCommand: GetEvent failed. res = 0x"); KernelLog.Hex(res,-2);
  463. KernelLog.Ln;
  464. END;
  465. ELSE
  466. KernelLog.String(ModuleName);
  467. KernelLog.String("HCI.InSendCommand: tl.Send failed. res = 0x"); KernelLog.Hex(res,-2);
  468. KernelLog.Ln;
  469. END;
  470. IF TraceHCI THEN
  471. KernelLog.String(ModuleName);
  472. KernelLog.String("HCI.InSendCommand: done.");
  473. KernelLog.Ln;
  474. END;
  475. END InSendCommand;
  476. PROCEDURE GetEvent*(timeout: LONGINT; VAR event: Bluetooth.EventPacket; VAR res: WORD);
  477. VAR p: Bluetooth.Packet;
  478. BEGIN
  479. IF TraceHCI THEN
  480. KernelLog.String(ModuleName);
  481. KernelLog.String("HCI.GetEvent: ...");
  482. KernelLog.Ln;
  483. END;
  484. eventQueue.Get(p, timeout, res);
  485. IF (res = 0) THEN
  486. IF (p IS Bluetooth.EventPacket) THEN
  487. event := p(Bluetooth.EventPacket);
  488. ELSE
  489. IF TraceHCI THEN
  490. KernelLog.String(ModuleName);
  491. KernelLog.String("HCI.GetEvent: wrong packet received");
  492. KernelLog.Ln;
  493. END;
  494. res := Bluetooth.ErrInvalidPacket;
  495. END
  496. ELSE
  497. IF TraceHCI THEN
  498. KernelLog.String(ModuleName);
  499. KernelLog.String("HCI.GetEvent: eventQueue.Get failed. res = 0x"); KernelLog.Hex(res,-2);
  500. KernelLog.Ln;
  501. END;
  502. END;
  503. IF TraceHCI THEN
  504. KernelLog.String(ModuleName);
  505. KernelLog.String("HCI.GetEvent: done.");
  506. KernelLog.Ln;
  507. END;
  508. END GetEvent;
  509. (**--- often used HCI commands ---*)
  510. (* ------- link controller commands -------- *)
  511. PROCEDURE Inquiry*(lap : LONGINT;inquiryLength : LONGINT; numResponses : LONGINT) : WORD;
  512. VAR
  513. par: ARRAY 5 OF CHAR;
  514. event: Bluetooth.EventPacket;
  515. pending: BOOLEAN;
  516. res: WORD;
  517. BEGIN
  518. par[0] := CHR(lap MOD 100H);
  519. par[1] := CHR((lap DIV 100H) MOD 100H);
  520. par[2] := CHR(lap DIV 10000H);
  521. par[3] := CHR(inquiryLength);
  522. par[4] := CHR(numResponses);
  523. InSendCommand(ogfLinkControl,ocfInquiry,par,5,event,pending,res);
  524. RETURN res;
  525. END Inquiry;
  526. PROCEDURE CreateConnection*(bdAddr: Bluetooth.BDAddr; clkofs: LONGINT): WORD;
  527. (* TODO: parameters!!! *)
  528. VAR
  529. par: ARRAY 13 OF CHAR;
  530. event: Bluetooth.EventPacket;
  531. pending: BOOLEAN;
  532. i: LONGINT; res: WORD;
  533. BEGIN
  534. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO par[i] := bdAddr[i] END;
  535. par[6] := 08X; par[7] := 00X; (* packet type: DM1 only *)
  536. par[8] := 00X; (* page scan repetition mode: R0 *)
  537. par[9] := 00X; (* page scan mode: mandatory page scan mode *)
  538. par[10] := CHR(clkofs MOD 100H); par[11] := CHR(clkofs DIV 100H MOD 100H); (* clock offset *)
  539. par[12] := 00X; (* allow role switch: local device master, no role switch *)
  540. InSendCommand(ogfLinkControl, ocfCreateConnection, par, 13, event, pending, res);
  541. RETURN res
  542. END CreateConnection;
  543. PROCEDURE Disconnect*(linkHandle,reason : LONGINT) : WORD;
  544. VAR
  545. par: ARRAY 3 OF CHAR;
  546. event: Bluetooth.EventPacket;
  547. pending: BOOLEAN;
  548. res: WORD;
  549. BEGIN
  550. par[0] := CHR(linkHandle MOD 100H);
  551. par[1] := CHR(linkHandle DIV 100H);
  552. par[2] := CHR(reason);
  553. InSendCommand(ogfLinkControl,ocfDisconnect,par,3,event,pending, res);
  554. RETURN res;
  555. END Disconnect;
  556. (* ------- host controller & bas band commands -------- *)
  557. PROCEDURE SetEventMask*(eventMask : LONGINT) : WORD;
  558. VAR
  559. par : ARRAY 8 OF CHAR;
  560. res: WORD;
  561. event: Bluetooth.EventPacket;
  562. pending: BOOLEAN;
  563. BEGIN
  564. (* TO DO *)
  565. par[0] := CHR(eventMask MOD 100H); eventMask := eventMask DIV 100H;
  566. par[1] := CHR(eventMask MOD 100H); eventMask := eventMask DIV 100H;
  567. par[2] := CHR(eventMask MOD 100H); eventMask := eventMask DIV 100H;
  568. par[3] := CHR(eventMask);
  569. InSendCommand(ogfControl, ocfSetEventMask, par, 8, event, pending, res);
  570. RETURN res;
  571. END SetEventMask;
  572. PROCEDURE Reset*(): WORD;
  573. VAR
  574. pending: BOOLEAN;
  575. event: Bluetooth.EventPacket;
  576. res: WORD;
  577. BEGIN
  578. IF TraceHCI THEN
  579. KernelLog.String(ModuleName);
  580. KernelLog.String("HCI.Reset: ..."); KernelLog.Ln;
  581. END;
  582. eventQueue.Clear;
  583. InSendCommand(ogfControl, ocfReset, "", 0, event, pending, res);
  584. IF pending & (res = 0) THEN res := Bluetooth.Error END;
  585. IF TraceHCI THEN
  586. KernelLog.String(ModuleName);
  587. KernelLog.String("HCI.Reset: done. res = "); KernelLog.Int(res,0); KernelLog.Ln;
  588. END;
  589. RETURN res
  590. END Reset;
  591. PROCEDURE SetEventFilter*(type, conditionType: CHAR; condition: ARRAY OF CHAR): WORD;
  592. VAR
  593. par: ARRAY 9 OF CHAR;
  594. i, len: LONGINT; res: WORD;
  595. event: Bluetooth.EventPacket;
  596. pending: BOOLEAN;
  597. BEGIN
  598. res := Bluetooth.ErrInvalidParameters;
  599. CASE type OF
  600. | EFClear: len := 1
  601. | EFInquiryResult:
  602. CASE conditionType OF
  603. | EFIRNewDevice: len := 2
  604. | EFIRClass: len := 8
  605. | EFIRAddr: len := 8
  606. ELSE RETURN res
  607. END
  608. | EFConnectionSetup:
  609. CASE conditionType OF
  610. | EFCSAll: len := 3
  611. | EFCSClass: len := 9
  612. | EFCSAddr: len := 9
  613. ELSE RETURN res
  614. END
  615. ELSE RETURN res
  616. END;
  617. par[0] := type;
  618. par[1] := conditionType;
  619. FOR i := 0 TO len-3 DO par[2+i] := condition[i] END;
  620. InSendCommand(ogfControl, ocfSetEventFilter, par, len, event, pending, res);
  621. IF pending & (res = 0) THEN res := Bluetooth.Error END;
  622. RETURN res
  623. END SetEventFilter;
  624. PROCEDURE WriteScanEnable*(mode: CHAR): WORD;
  625. VAR
  626. par: ARRAY 1 OF CHAR;
  627. pending: BOOLEAN;
  628. event: Bluetooth.EventPacket;
  629. res: WORD;
  630. BEGIN
  631. par[0] := mode;
  632. InSendCommand(ogfControl, ocfWriteScanEnable, par, 1, event, pending, res);
  633. IF pending & (res = 0) THEN res := Bluetooth.Error END;
  634. RETURN res
  635. END WriteScanEnable;
  636. PROCEDURE ReadScanEnable*(VAR scanEnable : CHAR) : WORD;
  637. VAR
  638. pending: BOOLEAN;
  639. event: Bluetooth.EventPacket;
  640. res : WORD;
  641. BEGIN
  642. InSendCommand(ogfControl,ocfReadScanEnable,"",0,event,pending,res);
  643. scanEnable := event.params[4];
  644. IF pending & (res = 0) THEN res := Bluetooth.Error END;
  645. RETURN res;
  646. END ReadScanEnable;
  647. PROCEDURE WriteLinkSupervisionTimeout*(inHandle, linkTimeout : LONGINT) : WORD;
  648. VAR
  649. par: ARRAY 4 OF CHAR;
  650. pending: BOOLEAN;
  651. event: Bluetooth.EventPacket;
  652. res : WORD;
  653. outHandle : LONGINT;
  654. BEGIN
  655. par[0] := CHR(inHandle MOD 100H);
  656. par[1] := CHR(inHandle DIV 100H);
  657. par[2] := CHR(linkTimeout MOD 100H);
  658. par[3] := CHR(linkTimeout DIV 100H);
  659. InSendCommand(ogfControl,ocfWriteLinkSupervisionTimeout,par,4,event,pending,res);
  660. IF pending THEN
  661. KernelLog.String(ModuleName);
  662. KernelLog.String("HCI.WriteLinkSupervisonTimout: pending! - res = "); KernelLog.Int(res,0);
  663. KernelLog.Ln;
  664. res := Bluetooth.ErrInvalidEvent;
  665. ELSIF (res = 0) THEN
  666. outHandle := (ORD(event.params[4]) + ORD(event.params[5]) * 100H) MOD 1000H;
  667. IF(outHandle # inHandle) THEN
  668. KernelLog.String(ModuleName);
  669. KernelLog.String("HCI.WriteLinkSupervisonTimout: error ?! - outHandle = "); KernelLog.Int(outHandle,0);
  670. KernelLog.String("; inHandle = "); KernelLog.Int(inHandle,0);
  671. KernelLog.Ln;
  672. END;
  673. END;
  674. RETURN res;
  675. END WriteLinkSupervisionTimeout;
  676. PROCEDURE ReadLinkSupervisionTimeout*(inHandle : LONGINT; VAR linkTimeout : LONGINT) : WORD;
  677. VAR
  678. par: ARRAY 2 OF CHAR;
  679. pending: BOOLEAN;
  680. event: Bluetooth.EventPacket;
  681. res : WORD;
  682. outHandle : LONGINT;
  683. BEGIN
  684. par[0] := CHR(inHandle MOD 100H);
  685. par[1] := CHR(inHandle DIV 100H);
  686. InSendCommand(ogfControl,ocfReadLinkSupervisionTimeout,par,2,event,pending,res);
  687. IF pending THEN
  688. KernelLog.String(ModuleName);
  689. KernelLog.String("HCI.ReadLinkSupervisonTimout: pending! - res = "); KernelLog.Int(res,0);
  690. KernelLog.Ln;
  691. res := Bluetooth.ErrInvalidEvent;
  692. ELSIF (res = 0) THEN
  693. outHandle := (ORD(event.params[4]) + ORD(event.params[5]) * 100H) MOD 1000H;
  694. IF(outHandle # inHandle) THEN
  695. KernelLog.String(ModuleName);
  696. KernelLog.String("HCI.ReadLinkSupervisonTimout: error ?! - outHandle = "); KernelLog.Int(outHandle,0);
  697. KernelLog.String("; inHandle = "); KernelLog.Int(inHandle,0);
  698. KernelLog.Ln;
  699. ELSE
  700. linkTimeout := ORD(event.params[6]) + ORD(event.params[7]) * 100H;
  701. END;
  702. END;
  703. RETURN res;
  704. END ReadLinkSupervisionTimeout;
  705. (* ------- Erricsson paramters -------- *)
  706. PROCEDURE EricssonSetUARTBaudRate*(baudRate : CHAR):WORD;
  707. VAR
  708. par: ARRAY 1 OF CHAR;
  709. pending: BOOLEAN;
  710. event: Bluetooth.EventPacket;
  711. res : WORD;
  712. BEGIN
  713. par[0] := baudRate;
  714. InSendCommand(ogfEricsson,ocfSetUARTBaudRate,par,LEN(par),event,pending,res);
  715. IF pending THEN
  716. KernelLog.String(ModuleName);
  717. KernelLog.String("HCI.EricssonSetUARTBaudRate: pending! - res = "); KernelLog.Int(res,0);
  718. KernelLog.Ln;
  719. END;
  720. IF pending & (res = 0) THEN res := Bluetooth.Error END;
  721. RETURN res;
  722. END EricssonSetUARTBaudRate;
  723. (* ------- Informational paramters -------- *)
  724. PROCEDURE ReadBDAddr*(VAR bdAddr: Bluetooth.BDAddr): WORD;
  725. VAR
  726. event: Bluetooth.EventPacket;
  727. pending: BOOLEAN;
  728. res: WORD; i: LONGINT;
  729. BEGIN
  730. IF TraceHCI THEN
  731. KernelLog.String(ModuleName);
  732. KernelLog.String("HCI.ReadBDAddr: ...");
  733. KernelLog.Ln;
  734. END;
  735. InSendCommand(ogfInformational, ocfReadBDAddr, "", 0, event, pending, res);
  736. IF pending THEN res := Bluetooth.ErrInvalidEvent
  737. ELSIF (res = 0) THEN
  738. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO bdAddr[i] := event.params[4+i] END;
  739. END;
  740. IF TraceHCI THEN
  741. KernelLog.String(ModuleName);
  742. KernelLog.String("HCI.ReadBDAddr: done. res = "); KernelLog.Int(res,0);
  743. KernelLog.Ln;
  744. END;
  745. RETURN res
  746. END ReadBDAddr;
  747. PROCEDURE ReadBufferSize*(VAR aclMaxLen, scoMaxLen, aclNumPackets, scoNumPackets: LONGINT): WORD;
  748. VAR
  749. event: Bluetooth.EventPacket;
  750. pending: BOOLEAN;
  751. res: WORD;
  752. BEGIN
  753. InSendCommand(ogfInformational, ocfReadBufferSize, "", 0, event, pending, res);
  754. IF pending THEN res := Bluetooth.ErrInvalidEvent
  755. ELSIF (res = 0) THEN
  756. aclMaxLen := ORD(event.params[5])*100H+ORD(event.params[4]);
  757. scoMaxLen := ORD(event.params[6]);
  758. aclNumPackets := ORD(event.params[8])*100H+ORD(event.params[7]);
  759. scoNumPackets := ORD(event.params[10])*100H+ORD(event.params[9])
  760. END;
  761. RETURN res
  762. END ReadBufferSize;
  763. (*--- HCI event handling ---*)
  764. PROCEDURE EventFilter(packet: Bluetooth.Packet): BOOLEAN;
  765. VAR event: Bluetooth.EventPacket; ec: CHAR;
  766. BEGIN
  767. event := packet(Bluetooth.EventPacket); ec := event.code;
  768. RETURN
  769. (ec = EConnectionComplete)
  770. OR (ec = EDisconnectionComplete)
  771. OR (ec = EInquiryResult)
  772. OR (ec = EInquiryComplete)
  773. OR (ec = ENofCompletedPackets)
  774. OR (ec = EMaxSlotsChange)
  775. OR (ec = EPageScanRepModeChange)
  776. OR (* status event to indicate host is ready *)
  777. ((ec = ECmdStatus) & (event.params[0] = 0X) & (event.params[2] = 0X) & (event.params[3] = 0X))
  778. OR (* command event to indicate host is ready *)
  779. ((ec = ECmdComplete) & (event.params[1] = 0X) & (event.params[2] = 0X))
  780. END EventFilter;
  781. PROCEDURE EventHandler(packet: Bluetooth.Packet);
  782. VAR
  783. event: Bluetooth.EventPacket;
  784. i : LONGINT;
  785. BEGIN
  786. event := packet(Bluetooth.EventPacket);
  787. IF TraceHCI THEN
  788. KernelLog.String(ModuleName);
  789. KernelLog.String("HCI.EventHandler: event.code = 0x"); KernelLog.Hex(ORD(event.code),-2);
  790. KernelLog.String(" ..."); KernelLog.Ln;
  791. END;
  792. IF (event.code = EConnectionComplete) THEN
  793. EventConnectionCompleteOLD(event);
  794. ELSIF (event.code = EDisconnectionComplete) THEN
  795. EventDisconnectionCompleteOLD(event);
  796. ELSIF (event.code = EInquiryResult) THEN
  797. EventInquiryResult(event);
  798. ELSIF (event.code = ENofCompletedPackets) THEN
  799. EventNumOfCompletedPackets(event);
  800. ELSIF (event.code = EInquiryComplete) THEN
  801. EventInquiryComplete(event);
  802. ELSIF (event.code = EMaxSlotsChange) THEN
  803. EventMaxSlotsChange(event);
  804. ELSIF (event.code = EPageScanRepModeChange) THEN
  805. EventPageScanRepModeChange(event);
  806. ELSIF ((event.code = ECmdStatus) OR (event.code = ECmdComplete)) THEN
  807. (* ignore - indicates that the host is ready *)
  808. ELSE
  809. KernelLog.String(ModuleName);
  810. KernelLog.String("HCI.EventHandler: unhandled event ! event.code = 0x");
  811. KernelLog.Hex(ORD(event.code),-2); KernelLog.String(" params:"); KernelLog.Ln;
  812. FOR i:= 0 TO event.paramLen-1 DO
  813. KernelLog.Hex(ORD(event.params[i]),-2); KernelLog.String(" ");
  814. END;
  815. KernelLog.Ln;
  816. END;
  817. IF TraceHCI THEN
  818. KernelLog.String(ModuleName);
  819. KernelLog.String("HCI.EventHandler: done."); KernelLog.Ln;
  820. END;
  821. END EventHandler;
  822. PROCEDURE EventInquiryComplete(event: Bluetooth.EventPacket);
  823. VAR
  824. status : LONGINT;
  825. BEGIN
  826. status := ORD(event.params[0]);
  827. IF (OnInquiryComplete # NIL) THEN
  828. OnInquiryComplete(SELF,status);
  829. END;
  830. END EventInquiryComplete;
  831. PROCEDURE EventInquiryResult(event: Bluetooth.EventPacket);
  832. VAR
  833. nr,psrm, pspm, psm, co: LONGINT;
  834. bdAddr : Bluetooth.BDAddr;
  835. class : Bluetooth.DeviceClass;
  836. i,k,ofs : LONGINT;
  837. BEGIN
  838. IF (OnInquiry # NIL) THEN
  839. i := 0; nr := ORD(event.params[0]);
  840. WHILE (i < nr) DO
  841. ofs := 1 + i*14;
  842. FOR k := 0 TO Bluetooth.BDAddrLen-1 DO
  843. bdAddr[k] := event.params[ofs+k]
  844. END;
  845. psrm := ORD(event.params[ofs+6]);
  846. pspm := ORD(event.params[ofs+7]);
  847. psm := ORD(event.params[ofs+8]);
  848. FOR k := 0 TO Bluetooth.DeviceClassLen-1 DO
  849. class[k] := event.params[ofs+9+k]
  850. END;
  851. co := ORD(event.params[ofs+12])+LONG(ORD(event.params[ofs+13]))*100H;
  852. OnInquiry(SELF,bdAddr,class,psrm,pspm,psm,co);
  853. INC(i);
  854. END;
  855. END;
  856. END EventInquiryResult;
  857. PROCEDURE EventConnectionComplete(event: Bluetooth.EventPacket);
  858. VAR
  859. status,handle : LONGINT;
  860. bdAddr : Bluetooth.BDAddr;
  861. linkType ,encryMode: LONGINT;
  862. i : LONGINT;
  863. BEGIN
  864. status := ORD(event.params[0]);
  865. handle := (ORD(event.params[2])*100H + ORD(event.params[1])) MOD 1000H;
  866. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO
  867. bdAddr[i] := event.params[3+i]
  868. END;
  869. linkType := ORD(event.params[9]);
  870. encryMode := ORD(event.params[10]);
  871. IF TraceHCI THEN
  872. KernelLog.String(ModuleName);
  873. KernelLog.String("HCI.EventConnectionComplete: status = 0x"); KernelLog.Hex(status,-2);
  874. KernelLog.String("; handle = "); KernelLog.Int(handle,0); KernelLog.String("; bdAddr = ");
  875. FOR i:= 0 TO Bluetooth.BDAddrLen-1 DO
  876. KernelLog.Hex(ORD(bdAddr[i]),-2);
  877. END;
  878. KernelLog.String("; linkType = "); KernelLog.Int(linkType,0);
  879. KernelLog.String("; encryptionMode = "); KernelLog.Int(encryMode,0);
  880. KernelLog.Ln;
  881. END;
  882. IF (OnConnectionComplete # NIL) THEN
  883. OnConnectionComplete(SELF,status,handle,bdAddr,linkType,encryMode);
  884. END;
  885. END EventConnectionComplete;
  886. PROCEDURE EventDisconnectionComplete(event: Bluetooth.EventPacket);
  887. VAR
  888. status,handle,reason : LONGINT;
  889. BEGIN
  890. status := ORD(event.params[0]);
  891. handle := (ORD(event.params[2])*100H + ORD(event.params[1])) MOD 1000H;
  892. reason := ORD(event.params[3]);
  893. IF TraceHCI THEN
  894. KernelLog.String(ModuleName);
  895. KernelLog.String("HCI.EventDisconnectionComplete: status = 0x"); KernelLog.Hex(status,-2);
  896. KernelLog.String("; handle = "); KernelLog.Int(handle,0);
  897. KernelLog.String("; reason = 0x"); KernelLog.Hex(reason,-2);
  898. KernelLog.Ln;
  899. END;
  900. IF (OnDisconnectionComplete # NIL) THEN
  901. OnDisconnectionComplete(SELF,status,handle,reason);
  902. END;
  903. END EventDisconnectionComplete;
  904. PROCEDURE EventConnectionCompleteOLD(event: Bluetooth.EventPacket);
  905. VAR
  906. status,handle,i : LONGINT;
  907. bdAddr : Bluetooth.BDAddr;
  908. link : Link;
  909. BEGIN
  910. status := ORD(event.params[0]);
  911. IF (status = 0) THEN
  912. handle := (ORD(event.params[2])*100H + ORD(event.params[1])) MOD 1000H;
  913. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO
  914. bdAddr[i] := event.params[3+i]
  915. END;
  916. link := linkManager.FindLink(handle);
  917. IF (link = NIL) THEN
  918. NEW(link,SELF, bdAddr,handle);
  919. linkManager.AddLink(link);
  920. END;
  921. link.state := lsUp;
  922. link.type := ORD(event.params[9]);
  923. link.encryption := ORD(event.params[10]);
  924. IF TraceHCI THEN
  925. KernelLog.String(ModuleName);
  926. KernelLog.String("HCI.EventConnectionCompleteOLD: status = 0x"); KernelLog.Hex(status,-2);
  927. KernelLog.String("; handle = "); KernelLog.Int(link.handle,0); KernelLog.String("; bdAddr = ");
  928. FOR i:= 0 TO Bluetooth.BDAddrLen-1 DO
  929. KernelLog.Hex(ORD(bdAddr[i]),-2);
  930. END;
  931. KernelLog.String("; linkType = "); KernelLog.Int(link.type,0);
  932. KernelLog.String("; encryptionMode = "); KernelLog.Int(link.encryption,0);
  933. KernelLog.Ln;
  934. END;
  935. ELSE
  936. handle := -1; link := NIL;
  937. IF TraceHCI THEN
  938. KernelLog.String(ModuleName);
  939. KernelLog.String("HCI.EventConnectionCompleteOLD: status = 0x"); KernelLog.Hex(status,-2);KernelLog.Ln;
  940. END;
  941. END;
  942. IF (OnConnect # NIL) THEN
  943. OnConnect(SELF,link,status)
  944. END;
  945. END EventConnectionCompleteOLD;
  946. PROCEDURE EventDisconnectionCompleteOLD(event: Bluetooth.EventPacket);
  947. VAR
  948. status,handle : LONGINT;
  949. link : Link;
  950. BEGIN
  951. status := ORD(event.params[0]);
  952. IF (status = 0) THEN
  953. handle := (ORD(event.params[2])*100H + ORD(event.params[1])) MOD 1000H;
  954. link := linkManager.FindLink(handle);
  955. IF (link # NIL) THEN
  956. link.state := lsDown;
  957. link.reason := ORD(event.params[3]);
  958. linkManager.RemoveLink(link);
  959. END;
  960. IF TraceHCI THEN
  961. KernelLog.String(ModuleName);
  962. KernelLog.String("HCI.EventDisconnectionCompleteOLD: status = 0x"); KernelLog.Hex(status,-2);
  963. KernelLog.String("; handle = "); KernelLog.Int(handle,0);
  964. KernelLog.String("; reason = 0x"); KernelLog.Hex(link.reason,-2);
  965. KernelLog.Ln;
  966. END;
  967. ELSE
  968. link := NIL;
  969. IF TraceHCI THEN
  970. KernelLog.String(ModuleName);
  971. KernelLog.String("HCI.EventDisconnectionCompleteOLD: status = 0x"); KernelLog.Hex(status,-2);KernelLog.Ln;
  972. END;
  973. END;
  974. IF (OnDisconnect # NIL) THEN
  975. OnDisconnect(SELF,link,status)
  976. END;
  977. END EventDisconnectionCompleteOLD;
  978. PROCEDURE EventNumOfCompletedPackets(event: Bluetooth.EventPacket);
  979. VAR
  980. numOfHandles,handle,numOfCompletedPackets : LONGINT;
  981. link : Link;
  982. ofs,i : LONGINT;
  983. BEGIN
  984. i := 0; numOfHandles := ORD(event.params[0]);
  985. WHILE (i < numOfHandles) DO
  986. ofs := 1 + i*4;
  987. handle := (ORD(event.params[ofs])+LONG(ORD(event.params[ofs+1]))*100H) MOD 1000H;
  988. numOfCompletedPackets := ORD(event.params[ofs+2])+LONG(ORD(event.params[ofs+3]))*100H;
  989. link := linkManager.FindLink(handle);
  990. IF (link # NIL) THEN
  991. INC(link.nofPackets, numOfCompletedPackets);
  992. END;
  993. INC(i);
  994. END;
  995. END EventNumOfCompletedPackets;
  996. PROCEDURE EventMaxSlotsChange(event: Bluetooth.EventPacket);
  997. VAR
  998. handle,maxSlots : LONGINT;
  999. BEGIN
  1000. handle := (ORD(event.params[1])*100H + ORD(event.params[0])) MOD 1000H;
  1001. maxSlots := ORD(event.params[2]);
  1002. KernelLog.String(ModuleName);
  1003. KernelLog.String("EventMaxSlotsChange: handle = "); KernelLog.Int(handle,0);
  1004. KernelLog.String(" max slots = "); KernelLog.Int(maxSlots,0);
  1005. KernelLog.Ln
  1006. END EventMaxSlotsChange;
  1007. PROCEDURE EventPageScanRepModeChange(event: Bluetooth.EventPacket);
  1008. VAR
  1009. i : LONGINT;
  1010. BEGIN
  1011. KernelLog.String(ModuleName);
  1012. KernelLog.String("EventPageScanRepititionModeChange: bdAddr = ");
  1013. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO
  1014. KernelLog.Hex(ORD(event.params[i]),-2);
  1015. END;
  1016. KernelLog.String(" mode = R"); KernelLog.Int(ORD(event.params[Bluetooth.BDAddrLen]),0);
  1017. KernelLog.Ln
  1018. END EventPageScanRepModeChange;
  1019. PROCEDURE EricssonFilter(packet: Bluetooth.Packet): BOOLEAN;
  1020. BEGIN RETURN packet(Bluetooth.EventPacket).code = 0FFX
  1021. END EricssonFilter;
  1022. PROCEDURE EricssonHandler(packet: Bluetooth.Packet);
  1023. VAR event: Bluetooth.EventPacket; i: LONGINT;
  1024. BEGIN
  1025. event := packet(Bluetooth.EventPacket);
  1026. KernelLog.Enter;
  1027. CASE event.params[0] OF
  1028. | 01X: KernelLog.String("Ericsson OSE crash")
  1029. | 04X: KernelLog.String("Ericsson OSE pool event")
  1030. | 06X: KernelLog.String("Message from Ericsson module on TL '"); KernelLog.String(tl.name); KernelLog.String("': ");
  1031. FOR i := 0 TO ORD(event.params[1])-1 DO KernelLog.Char(event.params[2+i]) END;
  1032. ELSE KernelLog.String("unknown Ericsson event")
  1033. END;
  1034. KernelLog.Exit
  1035. END EricssonHandler;
  1036. PROCEDURE ACLFilter(packet: Bluetooth.Packet): BOOLEAN;
  1037. BEGIN RETURN TRUE
  1038. END ACLFilter;
  1039. PROCEDURE ACLHandler(packet: Bluetooth.Packet);
  1040. VAR acl: Bluetooth.ACLPacket; l: Link;
  1041. BEGIN
  1042. IF TraceHCI THEN
  1043. KernelLog.String(ModuleName);
  1044. KernelLog.String("HCI.ACLHandler: ..."); KernelLog.Ln;
  1045. END;
  1046. acl := packet(Bluetooth.ACLPacket);
  1047. l := linkManager.FindLink(acl.handle);
  1048. IF (l # NIL) THEN l.ACLDataReceived(acl) END;
  1049. IF TraceHCI THEN
  1050. KernelLog.String(ModuleName);
  1051. KernelLog.String("HCI.ACLHandler: done."); KernelLog.Ln;
  1052. END;
  1053. END ACLHandler;
  1054. PROCEDURE ErrorFilter(packet: Bluetooth.Packet): BOOLEAN;
  1055. BEGIN RETURN (packet IS Bluetooth.UnknownPacket)
  1056. END ErrorFilter;
  1057. PROCEDURE ErrorHandler(packet: Bluetooth.Packet);
  1058. BEGIN
  1059. IF (OnError # NIL) THEN
  1060. OnError(packet)
  1061. END
  1062. END ErrorHandler;
  1063. END HCI;
  1064. ConnectionComplete* = PROCEDURE {DELEGATE} (sender: HCI; status, handle: LONGINT;
  1065. bdAddr: Bluetooth.BDAddr; linkType, encryMode: LONGINT);
  1066. DisconnectionComplete* = PROCEDURE {DELEGATE} (sender : HCI; status,handle,reason : LONGINT);
  1067. InquiryComplete* = PROCEDURE {DELEGATE} (sender: HCI; status: LONGINT);
  1068. ConnectionEvent* = PROCEDURE{DELEGATE} (sender: HCI; link: Link; res: WORD);
  1069. (*OnReceiveACLDataEvent* = PROCEDURE{DELEGATE} (link: Link; acl: Bluetooth.ACLPacket); *)
  1070. (*handle, PB, PC, len: LONGINT; VAR data: ARRAY OF CHAR);*)
  1071. InquiryEvent* = PROCEDURE {DELEGATE} (sender: HCI; bdAddr: Bluetooth.BDAddr; deviceClass: Bluetooth.DeviceClass;
  1072. psRepMode, psPeriodMode, psMode, clockOffset: LONGINT);
  1073. GeneralEvent* = PROCEDURE {DELEGATE} (sender: HCI; event: Bluetooth.EventPacket);
  1074. ErrorEvent* = PROCEDURE{DELEGATE} (packet: Bluetooth.Packet);
  1075. (** composes a HCI command packet header *)
  1076. PROCEDURE ComposeCommandHeader*(OGF, OCF, paramLen: LONGINT; VAR command: ARRAY OF CHAR);
  1077. BEGIN
  1078. ASSERT((0 <= OGF) & (OGF <= 03FH));
  1079. ASSERT((0 <= OCF) & (OCF <= 03FFH));
  1080. ASSERT((0 <= paramLen) & (paramLen <= 0FFH));
  1081. command[0] := CHR(OCF MOD 100H);
  1082. command[1] := CHR(OCF DIV 100H + OGF*4);
  1083. command[2] := CHR(paramLen)
  1084. END ComposeCommandHeader;
  1085. END BluetoothHCI.